Completed
Push — 1.11.x ( ca7787...41c0f2 )
by José
31:51
created

api.lib.php ➔ location()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 2
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use ChamiloSession as Session;
5
use Chamilo\CourseBundle\Entity\CItemProperty;
6
7
/**
8
 * This is a code library for Chamilo.
9
 * It is included by default in every Chamilo file (through including the global.inc.php)
10
 * This library is in process of being transferred to src/Chamilo/CoreBundle/Component/Utils/ChamiloApi.
11
 * Whenever a function is transferred to the ChamiloApi class, the places where it is used should include
12
 * the "use Chamilo\CoreBundle\Component\Utils\ChamiloApi;" statement.
13
 * @package chamilo.library
14
 */
15
16
/**
17
 * Constants declaration
18
 */
19
20
// PHP version requirement.
21
define('REQUIRED_PHP_VERSION', '5.4');
22
define('REQUIRED_MIN_MEMORY_LIMIT', '128');
23
define('REQUIRED_MIN_UPLOAD_MAX_FILESIZE', '10');
24
define('REQUIRED_MIN_POST_MAX_SIZE', '10');
25
26
// USER STATUS CONSTANTS
27
/** global status of a user: student */
28
define('STUDENT', 5);
29
/** global status of a user: course manager */
30
define('COURSEMANAGER', 1);
31
/** global status of a user: session admin */
32
define('SESSIONADMIN', 3);
33
/** global status of a user: human ressource manager */
34
define('DRH', 4);
35
/** global status of a user: human ressource manager */
36
define('ANONYMOUS', 6);
37
/** global status of a user: low security, necessary for inserting data from
38
 * the teacher through HTMLPurifier */
39
define('COURSEMANAGERLOWSECURITY', 10);
40
// Soft user status
41
define('PLATFORM_ADMIN', 11);
42
define('SESSION_COURSE_COACH', 12);
43
define('SESSION_GENERAL_COACH', 13);
44
define('COURSE_STUDENT', 14);   //student subscribed in a course
45
define('SESSION_STUDENT', 15);  //student subscribed in a session course
46
define('COURSE_TUTOR', 16); // student is tutor of a course (NOT in session)
47
define('STUDENT_BOSS', 17); // student is boss
48
define('INVITEE', 20);
49
50
// Table of status
51
$_status_list[COURSEMANAGER] = 'teacher';        // 1
52
$_status_list[SESSIONADMIN] = 'session_admin';  // 3
53
$_status_list[DRH] = 'drh';            // 4
54
$_status_list[STUDENT] = 'user';           // 5
55
$_status_list[ANONYMOUS] = 'anonymous';      // 6
56
$_status_list[INVITEE] = 'invited';        // 20
57
58
// COURSE VISIBILITY CONSTANTS
59
/** only visible for course admin */
60
define('COURSE_VISIBILITY_CLOSED', 0);
61
/** only visible for users registered in the course */
62
define('COURSE_VISIBILITY_REGISTERED', 1);
63
/** Open for all registered users on the platform */
64
define('COURSE_VISIBILITY_OPEN_PLATFORM', 2);
65
/** Open for the whole world */
66
define('COURSE_VISIBILITY_OPEN_WORLD', 3);
67
/** Invisible to all except admin */
68
define('COURSE_VISIBILITY_HIDDEN', 4);
69
70
define('COURSE_REQUEST_PENDING', 0);
71
define('COURSE_REQUEST_ACCEPTED', 1);
72
define('COURSE_REQUEST_REJECTED', 2);
73
define('DELETE_ACTION_ENABLED', false);
74
75
// EMAIL SENDING RECIPIENT CONSTANTS
76
define('SEND_EMAIL_EVERYONE', 1);
77
define('SEND_EMAIL_STUDENTS', 2);
78
define('SEND_EMAIL_TEACHERS', 3);
79
80
// SESSION VISIBILITY CONSTANTS
81
define('SESSION_VISIBLE_READ_ONLY', 1);
82
define('SESSION_VISIBLE', 2);
83
define('SESSION_INVISIBLE', 3); // not available
84
define('SESSION_AVAILABLE', 4);
85
86
define('SESSION_LINK_TARGET', '_self');
87
88
define('SUBSCRIBE_ALLOWED', 1);
89
define('SUBSCRIBE_NOT_ALLOWED', 0);
90
define('UNSUBSCRIBE_ALLOWED', 1);
91
define('UNSUBSCRIBE_NOT_ALLOWED', 0);
92
93
// SURVEY VISIBILITY CONSTANTS
94
define('SURVEY_VISIBLE_TUTOR', 0);
95
define('SURVEY_VISIBLE_TUTOR_STUDENT', 1);
96
define('SURVEY_VISIBLE_PUBLIC', 2);
97
98
// CONSTANTS defining all tools, using the english version
99
/* When you add a new tool you must add it into function api_get_tools_lists() too */
100
define('TOOL_DOCUMENT', 'document');
101
define('TOOL_LP_FINAL_ITEM', 'final_item');
102
define('TOOL_THUMBNAIL', 'thumbnail');
103
define('TOOL_HOTPOTATOES', 'hotpotatoes');
104
define('TOOL_CALENDAR_EVENT', 'calendar_event');
105
define('TOOL_LINK', 'link');
106
define('TOOL_LINK_CATEGORY', 'link_category');
107
define('TOOL_COURSE_DESCRIPTION', 'course_description');
108
define('TOOL_SEARCH', 'search');
109
define('TOOL_LEARNPATH', 'learnpath');
110
define('TOOL_AGENDA', 'agenda');
111
define('TOOL_ANNOUNCEMENT', 'announcement');
112
define('TOOL_FORUM', 'forum');
113
define('TOOL_FORUM_CATEGORY', 'forum_category');
114
define('TOOL_FORUM_THREAD', 'forum_thread');
115
define('TOOL_FORUM_POST', 'forum_post');
116
define('TOOL_FORUM_ATTACH', 'forum_attachment');
117
define('TOOL_FORUM_THREAD_QUALIFY', 'forum_thread_qualify');
118
define('TOOL_THREAD', 'thread');
119
define('TOOL_POST', 'post');
120
define('TOOL_DROPBOX', 'dropbox');
121
define('TOOL_QUIZ', 'quiz');
122
define('TOOL_TEST_CATEGORY', 'test_category');
123
define('TOOL_USER', 'user');
124
define('TOOL_GROUP', 'group');
125
define('TOOL_BLOGS', 'blog_management');
126
define('TOOL_CHAT', 'chat');
127
define('TOOL_STUDENTPUBLICATION', 'student_publication');
128
define('TOOL_TRACKING', 'tracking');
129
define('TOOL_HOMEPAGE_LINK', 'homepage_link');
130
define('TOOL_COURSE_SETTING', 'course_setting');
131
define('TOOL_BACKUP', 'backup');
132
define('TOOL_COPY_COURSE_CONTENT', 'copy_course_content');
133
define('TOOL_RECYCLE_COURSE', 'recycle_course');
134
define('TOOL_COURSE_HOMEPAGE', 'course_homepage');
135
define('TOOL_COURSE_RIGHTS_OVERVIEW', 'course_rights');
136
define('TOOL_UPLOAD', 'file_upload');
137
define('TOOL_COURSE_MAINTENANCE', 'course_maintenance');
138
define('TOOL_SURVEY', 'survey');
139
define('TOOL_WIKI', 'wiki');
140
define('TOOL_GLOSSARY', 'glossary');
141
define('TOOL_GRADEBOOK', 'gradebook');
142
define('TOOL_NOTEBOOK', 'notebook');
143
define('TOOL_ATTENDANCE', 'attendance');
144
define('TOOL_COURSE_PROGRESS', 'course_progress');
145
146
// CONSTANTS defining Chamilo interface sections
147
define('SECTION_CAMPUS', 'mycampus');
148
define('SECTION_COURSES', 'mycourses');
149
define('SECTION_CATALOG', 'catalog');
150
define('SECTION_MYPROFILE', 'myprofile');
151
define('SECTION_MYAGENDA', 'myagenda');
152
define('SECTION_COURSE_ADMIN', 'course_admin');
153
define('SECTION_PLATFORM_ADMIN', 'platform_admin');
154
define('SECTION_MYGRADEBOOK', 'mygradebook');
155
define('SECTION_TRACKING', 'session_my_space');
156
define('SECTION_SOCIAL', 'social-network');
157
define('SECTION_DASHBOARD', 'dashboard');
158
define('SECTION_REPORTS', 'reports');
159
define('SECTION_GLOBAL', 'global');
160
161
// CONSTANT name for local authentication source
162
define('PLATFORM_AUTH_SOURCE', 'platform');
163
define('CAS_AUTH_SOURCE', 'cas');
164
define('LDAP_AUTH_SOURCE', 'extldap');
165
166
// CONSTANT defining the default HotPotatoes files directory
167
define('DIR_HOTPOTATOES', '/HotPotatoes_files');
168
169
// event logs types
170
define('LOG_COURSE_DELETE', 'course_deleted');
171
define('LOG_COURSE_CREATE', 'course_created');
172
173
// @todo replace 'soc_gr' with social_group
174
define('LOG_GROUP_PORTAL_CREATED', 'soc_gr_created');
175
define('LOG_GROUP_PORTAL_UPDATED', 'soc_gr_updated');
176
define('LOG_GROUP_PORTAL_DELETED', 'soc_gr_deleted');
177
define('LOG_GROUP_PORTAL_USER_DELETE_ALL', 'soc_gr_delete_users');
178
179
define('LOG_GROUP_PORTAL_ID', 'soc_gr_portal_id');
180
define('LOG_GROUP_PORTAL_REL_USER_ARRAY', 'soc_gr_user_array');
181
182
define('LOG_GROUP_PORTAL_USER_SUBSCRIBED', 'soc_gr_u_subs');
183
define('LOG_GROUP_PORTAL_USER_UNSUBSCRIBED', 'soc_gr_u_unsubs');
184
define('LOG_GROUP_PORTAL_USER_UPDATE_ROLE', 'soc_gr_update_role');
185
186
define('LOG_USER_DELETE', 'user_deleted');
187
define('LOG_USER_CREATE', 'user_created');
188
define('LOG_USER_ENABLE', 'user_enable');
189
define('LOG_USER_DISABLE', 'user_disable');
190
define('LOG_USER_FIELD_CREATE', 'user_field_created');
191
define('LOG_USER_FIELD_DELETE', 'user_field_deleted');
192
define('LOG_SESSION_CREATE', 'session_created');
193
define('LOG_SESSION_DELETE', 'session_deleted');
194
define('LOG_SESSION_ADD_USER_COURSE', 'session_add_user_course');
195
define('LOG_SESSION_DELETE_USER_COURSE', 'session_delete_user_course');
196
define('LOG_SESSION_DELETE_USER', 'session_delete_user');
197
define('LOG_SESSION_ADD_COURSE', 'session_add_course');
198
define('LOG_SESSION_DELETE_COURSE', 'session_delete_course');
199
200
define('LOG_SESSION_CATEGORY_CREATE', 'session_cat_created'); //changed in 1.9.8
201
define('LOG_SESSION_CATEGORY_DELETE', 'session_cat_deleted'); //changed in 1.9.8
202
define('LOG_CONFIGURATION_SETTINGS_CHANGE', 'settings_changed');
203
define('LOG_PLATFORM_LANGUAGE_CHANGE', 'platform_lng_changed'); //changed in 1.9.8
204
define('LOG_SUBSCRIBE_USER_TO_COURSE', 'user_subscribed');
205
define('LOG_UNSUBSCRIBE_USER_FROM_COURSE', 'user_unsubscribed');
206
define('LOG_ATTEMPTED_FORCED_LOGIN', 'attempted_forced_login');
207
208
define('LOG_HOMEPAGE_CHANGED', 'homepage_changed');
209
210
define('LOG_PROMOTION_CREATE', 'promotion_created');
211
define('LOG_PROMOTION_DELETE', 'promotion_deleted');
212
define('LOG_CAREER_CREATE', 'career_created');
213
define('LOG_CAREER_DELETE', 'career_deleted');
214
215
define('LOG_USER_PERSONAL_DOC_DELETED', 'user_doc_deleted');
216
define('LOG_WIKI_ACCESS', 'wiki_page_view');
217
218
define('LOG_EXERCISE_RESULT_DELETE', 'exe_result_deleted');
219
define('LOG_LP_ATTEMPT_DELETE', 'lp_attempt_deleted');
220
define('LOG_QUESTION_RESULT_DELETE', 'qst_attempt_deleted');
221
222
define('LOG_MY_FOLDER_CREATE', 'my_folder_created');
223
define('LOG_MY_FOLDER_CHANGE', 'my_folder_changed');
224
define('LOG_MY_FOLDER_DELETE', 'my_folder_deleted');
225
define('LOG_MY_FOLDER_COPY', 'my_folder_copied');
226
define('LOG_MY_FOLDER_CUT', 'my_folder_cut');
227
define('LOG_MY_FOLDER_PASTE', 'my_folder_pasted');
228
define('LOG_MY_FOLDER_UPLOAD', 'my_folder_uploaded');
229
230
// Event logs data types (max 20 chars)
231
define('LOG_COURSE_CODE', 'course_code');
232
define('LOG_COURSE_ID', 'course_id');
233
define('LOG_USER_ID', 'user_id');
234
define('LOG_USER_OBJECT', 'user_object');
235
define('LOG_USER_FIELD_VARIABLE', 'user_field_variable');
236
define('LOG_SESSION_ID', 'session_id');
237
define('LOG_SESSION_CATEGORY_ID', 'session_category_id');
238
define('LOG_CONFIGURATION_SETTINGS_CATEGORY', 'settings_category');
239
define('LOG_CONFIGURATION_SETTINGS_VARIABLE', 'settings_variable');
240
define('LOG_PLATFORM_LANGUAGE', 'default_platform_language');
241
define('LOG_CAREER_ID', 'career_id');
242
define('LOG_PROMOTION_ID', 'promotion_id');
243
define('LOG_GRADEBOOK_LOCKED', 'gradebook_locked');
244
define('LOG_GRADEBOOK_UNLOCKED', 'gradebook_unlocked');
245
define('LOG_GRADEBOOK_ID', 'gradebook_id');
246
define('LOG_WIKI_PAGE_ID', 'wiki_page_id');
247
define('LOG_EXERCISE_ID', 'exercise_id');
248
define('LOG_EXERCISE_AND_USER_ID', 'exercise_and_user_id');
249
define('LOG_LP_ID', 'lp_id');
250
define('LOG_EXERCISE_ATTEMPT_QUESTION_ID', 'exercise_a_q_id');
251
252
define('LOG_WORK_DIR_DELETE', 'work_dir_delete');
253
define('LOG_WORK_FILE_DELETE', 'work_file_delete');
254
define('LOG_WORK_DATA', 'work_data_array');
255
256
define('LOG_MY_FOLDER_PATH', 'path');
257
define('LOG_MY_FOLDER_NEW_PATH', 'new_path');
258
259
define('USERNAME_PURIFIER', '/[^0-9A-Za-z_\.]/');
260
261
//used when login_is_email setting is true
262
define('USERNAME_PURIFIER_MAIL', '/[^0-9A-Za-z_\.@]/');
263
define('USERNAME_PURIFIER_SHALLOW', '/\s/');
264
265
// This constant is a result of Windows OS detection, it has a boolean value:
266
// true whether the server runs on Windows OS, false otherwise.
267
define('IS_WINDOWS_OS', api_is_windows_os());
268
269
// Checks for installed optional php-extensions.
270
define('INTL_INSTALLED', function_exists('intl_get_error_code'));   // intl extension (from PECL), it is installed by default as of PHP 5.3.0
271
define('ICONV_INSTALLED', function_exists('iconv'));                // iconv extension, for PHP5 on Windows it is installed by default.
272
define('MBSTRING_INSTALLED', function_exists('mb_strlen'));         // mbstring extension.
273
274
// Patterns for processing paths.                                   // Examples:
275
define('REPEATED_SLASHES_PURIFIER', '/\/{2,}/');                    // $path = preg_replace(REPEATED_SLASHES_PURIFIER, '/', $path);
276
define('VALID_WEB_PATH', '/https?:\/\/[^\/]*(\/.*)?/i');            // $is_valid_path = preg_match(VALID_WEB_PATH, $path);
277
define('VALID_WEB_SERVER_BASE', '/https?:\/\/[^\/]*/i');            // $new_path = preg_replace(VALID_WEB_SERVER_BASE, $new_base, $path);
278
279
// Constants for api_get_path() and api_get_path_type(), etc. - registered path types.
280
// basic (leaf elements)
281
define('REL_CODE_PATH', 'REL_CODE_PATH');
282
define('REL_COURSE_PATH', 'REL_COURSE_PATH');
283
define('REL_HOME_PATH', 'REL_HOME_PATH');
284
285
// Constants for api_get_path() and api_get_path_type(), etc. - registered path types.
286
define('WEB_PATH', 'WEB_PATH');
287
define('WEB_APP_PATH', 'WEB_APP_PATH');
288
define('SYS_PATH', 'SYS_PATH');
289
define('SYS_APP_PATH', 'SYS_APP_PATH');
290
define('SYS_UPLOAD_PATH', 'SYS_UPLOAD_PATH');
291
define('WEB_UPLOAD_PATH', 'WEB_UPLOAD_PATH');
292
293
define('REL_PATH', 'REL_PATH');
294
define('WEB_COURSE_PATH', 'WEB_COURSE_PATH');
295
define('SYS_COURSE_PATH', 'SYS_COURSE_PATH');
296
define('WEB_CODE_PATH', 'WEB_CODE_PATH');
297
define('SYS_CODE_PATH', 'SYS_CODE_PATH');
298
define('SYS_LANG_PATH', 'SYS_LANG_PATH');
299
define('WEB_IMG_PATH', 'WEB_IMG_PATH');
300
define('WEB_CSS_PATH', 'WEB_CSS_PATH');
301
define('WEB_PUBLIC_PATH', 'WEB_PUBLIC_PATH');
302
define('SYS_CSS_PATH', 'SYS_CSS_PATH');
303
define('SYS_PLUGIN_PATH', 'SYS_PLUGIN_PATH');
304
define('WEB_PLUGIN_PATH', 'WEB_PLUGIN_PATH');
305
define('SYS_ARCHIVE_PATH', 'SYS_ARCHIVE_PATH');
306
define('WEB_ARCHIVE_PATH', 'WEB_ARCHIVE_PATH');
307
define('SYS_INC_PATH', 'SYS_INC_PATH');
308
define('LIBRARY_PATH', 'LIBRARY_PATH');
309
define('CONFIGURATION_PATH', 'CONFIGURATION_PATH');
310
define('WEB_LIBRARY_PATH', 'WEB_LIBRARY_PATH');
311
define('WEB_LIBRARY_JS_PATH', 'WEB_LIBRARY_JS_PATH');
312
define('WEB_AJAX_PATH', 'WEB_AJAX_PATH');
313
define('SYS_TEST_PATH', 'SYS_TEST_PATH');
314
define('WEB_TEMPLATE_PATH', 'WEB_TEMPLATE_PATH');
315
define('SYS_TEMPLATE_PATH', 'SYS_TEMPLATE_PATH');
316
define('SYS_PUBLIC_PATH', 'SYS_PUBLIC_PATH');
317
define('SYS_HOME_PATH', 'SYS_HOME_PATH');
318
define('WEB_HOME_PATH', 'WEB_HOME_PATH');
319
define('WEB_FONTS_PATH', 'WEB_FONTS_PATH');
320
define('SYS_FONTS_PATH', 'SYS_FONTS_PATH');
321
322
define('SYS_DEFAULT_COURSE_DOCUMENT_PATH', 'SYS_DEFAULT_COURSE_DOCUMENT_PATH');
323
define('REL_DEFAULT_COURSE_DOCUMENT_PATH', 'REL_DEFAULT_COURSE_DOCUMENT_PATH');
324
define('WEB_DEFAULT_COURSE_DOCUMENT_PATH', 'WEB_DEFAULT_COURSE_DOCUMENT_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
define('GRADEBOOK_ITEM_LIMIT', 1000);
354
355
define('LINK_EXERCISE', 1);
356
define('LINK_DROPBOX', 2);
357
define('LINK_STUDENTPUBLICATION', 3);
358
define('LINK_LEARNPATH', 4);
359
define('LINK_FORUM_THREAD', 5);
360
//define('LINK_WORK',6);
361
define('LINK_ATTENDANCE', 7);
362
define('LINK_SURVEY', 8);
363
define('LINK_HOTPOTATOES', 9);
364
365
// Score display types constants
366
define('SCORE_DIV', 1);    // X / Y
367
define('SCORE_PERCENT', 2);    // XX %
368
define('SCORE_DIV_PERCENT', 3);    // X / Y (XX %)
369
define('SCORE_AVERAGE', 4);    // XX %
370
define('SCORE_DECIMAL', 5);    // 0.50  (X/Y)
371
define('SCORE_BAR', 6);    // Uses the Display::bar_progress function
372
define('SCORE_SIMPLE', 7);    // X
373
define('SCORE_IGNORE_SPLIT', 8);    //  ??
374
define('SCORE_DIV_PERCENT_WITH_CUSTOM', 9);    // X / Y (XX %) - Good!
375
define('SCORE_CUSTOM', 10);    // Good!
376
define('SCORE_DIV_SIMPLE_WITH_CUSTOM', 11);    // X - Good!
377
define('SCORE_DIV_SIMPLE_WITH_CUSTOM_LETTERS', 12);    // X - Good!
378
define('SCORE_ONLY_SCORE', 13);    // X - Good!
379
380
define('SCORE_BOTH', 1);
381
define('SCORE_ONLY_DEFAULT', 2);
382
define('SCORE_ONLY_CUSTOM', 3);
383
384
// From display.lib.php
385
386
define('MAX_LENGTH_BREADCRUMB', 100);
387
define('ICON_SIZE_ATOM', 8);
388
define('ICON_SIZE_TINY', 16);
389
define('ICON_SIZE_SMALL', 22);
390
define('ICON_SIZE_MEDIUM', 32);
391
define('ICON_SIZE_LARGE', 48);
392
define('ICON_SIZE_BIG', 64);
393
define('ICON_SIZE_HUGE', 128);
394
define('SHOW_TEXT_NEAR_ICONS', false);
395
396
// Session catalog
397
define('CATALOG_COURSES', 0);
398
define('CATALOG_SESSIONS', 1);
399
define('CATALOG_COURSES_SESSIONS', 2);
400
401
// Hook type events, pre-process and post-process.
402
// All means to be executed for both hook event types
403
define('HOOK_EVENT_TYPE_PRE', 0);
404
define('HOOK_EVENT_TYPE_POST', 1);
405
define('HOOK_EVENT_TYPE_ALL', 10);
406
407
define('CAREER_STATUS_ACTIVE', 1);
408
define('CAREER_STATUS_INACTIVE', 0);
409
410
define('PROMOTION_STATUS_ACTIVE', 1);
411
define('PROMOTION_STATUS_INACTIVE', 0);
412
413
// Group permissions
414
define('GROUP_PERMISSION_OPEN', '1');
415
define('GROUP_PERMISSION_CLOSED', '2');
416
417
// Group user permissions
418
define('GROUP_USER_PERMISSION_ADMIN', '1'); // the admin of a group
419
define('GROUP_USER_PERMISSION_READER', '2'); // a normal user
420
define('GROUP_USER_PERMISSION_PENDING_INVITATION', '3'); // When an admin/moderator invites a user
421
define('GROUP_USER_PERMISSION_PENDING_INVITATION_SENT_BY_USER', '4'); // an user joins a group
422
define('GROUP_USER_PERMISSION_MODERATOR', '5'); // a moderator
423
define('GROUP_USER_PERMISSION_ANONYMOUS', '6'); // an anonymous user
424
define('GROUP_USER_PERMISSION_HRM', '7'); // a human resources manager
425
426
define('GROUP_IMAGE_SIZE_ORIGINAL', 1);
427
define('GROUP_IMAGE_SIZE_BIG', 2);
428
define('GROUP_IMAGE_SIZE_MEDIUM', 3);
429
define('GROUP_IMAGE_SIZE_SMALL', 4);
430
define('GROUP_TITLE_LENGTH', 50);
431
432
// Exercise
433
// @todo move into a class
434
define('ALL_ON_ONE_PAGE', 1);
435
define('ONE_PER_PAGE', 2);
436
437
define('EXERCISE_FEEDBACK_TYPE_END', 0); //Feedback 		 - show score and expected answers
438
define('EXERCISE_FEEDBACK_TYPE_DIRECT', 1); //DirectFeedback - Do not show score nor answers
439
define('EXERCISE_FEEDBACK_TYPE_EXAM', 2); //NoFeedback 	 - Show score only
440
441
define('RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS', 0); //show score and expected answers
442
define('RESULT_DISABLE_NO_SCORE_AND_EXPECTED_ANSWERS', 1); //Do not show score nor answers
443
define('RESULT_DISABLE_SHOW_SCORE_ONLY', 2); //Show score only
444
define('RESULT_DISABLE_SHOW_FINAL_SCORE_ONLY_WITH_CATEGORIES', 3); //Show final score only with categories
445
define('RESULT_DISABLE_SHOW_SCORE_ATTEMPT_SHOW_ANSWERS_LAST_ATTEMPT', 4); //Show final score only with categories
446
447
define('EXERCISE_MAX_NAME_SIZE', 80);
448
449
// Question types (edit next array as well when adding values)
450
// @todo move into a class
451
define('UNIQUE_ANSWER', 1);
452
define('MULTIPLE_ANSWER', 2);
453
define('FILL_IN_BLANKS', 3);
454
define('MATCHING', 4);
455
define('FREE_ANSWER', 5);
456
define('HOT_SPOT', 6);
457
define('HOT_SPOT_ORDER', 7);
458
define('HOT_SPOT_DELINEATION', 8);
459
define('MULTIPLE_ANSWER_COMBINATION', 9);
460
define('UNIQUE_ANSWER_NO_OPTION', 10);
461
define('MULTIPLE_ANSWER_TRUE_FALSE', 11);
462
define('MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE', 12);
463
define('ORAL_EXPRESSION', 13);
464
define('GLOBAL_MULTIPLE_ANSWER', 14);
465
define('MEDIA_QUESTION', 15);
466
define('CALCULATED_ANSWER', 16);
467
define('UNIQUE_ANSWER_IMAGE', 17);
468
define('DRAGGABLE', 18);
469
define('MATCHING_DRAGGABLE', 19);
470
471
define('EXERCISE_CATEGORY_RANDOM_SHUFFLED', 1);
472
define('EXERCISE_CATEGORY_RANDOM_ORDERED', 2);
473
define('EXERCISE_CATEGORY_RANDOM_DISABLED', 0);
474
475
// Question selection type
476
define('EX_Q_SELECTION_ORDERED', 1);
477
define('EX_Q_SELECTION_RANDOM', 2);
478
define('EX_Q_SELECTION_CATEGORIES_ORDERED_QUESTIONS_ORDERED', 3);
479
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_ORDERED', 4);
480
define('EX_Q_SELECTION_CATEGORIES_ORDERED_QUESTIONS_RANDOM', 5);
481
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_RANDOM', 6);
482
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_ORDERED_NO_GROUPED', 7);
483
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_RANDOM_NO_GROUPED', 8);
484
define('EX_Q_SELECTION_CATEGORIES_ORDERED_BY_PARENT_QUESTIONS_ORDERED', 9);
485
define('EX_Q_SELECTION_CATEGORIES_ORDERED_BY_PARENT_QUESTIONS_RANDOM', 10);
486
487
// one big string with all question types, for the validator in pear/HTML/QuickForm/Rule/QuestionType
488
define('QUESTION_TYPES',
489
    UNIQUE_ANSWER.':'.
490
    MULTIPLE_ANSWER.':'.
491
    FILL_IN_BLANKS.':'.
492
    MATCHING.':'.
493
    FREE_ANSWER.':'.
494
    HOT_SPOT.':'.
495
    HOT_SPOT_ORDER.':'.
496
    HOT_SPOT_DELINEATION.':'.
497
    MULTIPLE_ANSWER_COMBINATION.':'.
498
    UNIQUE_ANSWER_NO_OPTION.':'.
499
    MULTIPLE_ANSWER_TRUE_FALSE.':'.
500
    MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE.':'.
501
    ORAL_EXPRESSION.':'.
502
    GLOBAL_MULTIPLE_ANSWER.':'.
503
    MEDIA_QUESTION.':'.
504
    CALCULATED_ANSWER.':'.
505
    UNIQUE_ANSWER_IMAGE.':'.
506
    DRAGGABLE.':'.
507
    MATCHING_DRAGGABLE
508
);
509
510
//Some alias used in the QTI exports
511
define('MCUA', 1);
512
define('TF', 1);
513
define('MCMA', 2);
514
define('FIB', 3);
515
516
// Skills
517
define('SKILL_TYPE_REQUIREMENT', 'required');
518
define('SKILL_TYPE_ACQUIRED', 'acquired');
519
define('SKILL_TYPE_BOTH', 'both');
520
521
// Message
522
define('MESSAGE_STATUS_NEW', '0');
523
define('MESSAGE_STATUS_UNREAD', '1');
524
//2 ??
525
define('MESSAGE_STATUS_DELETED', '3');
526
define('MESSAGE_STATUS_OUTBOX', '4');
527
define('MESSAGE_STATUS_INVITATION_PENDING', '5');
528
define('MESSAGE_STATUS_INVITATION_ACCEPTED', '6');
529
define('MESSAGE_STATUS_INVITATION_DENIED', '7');
530
define('MESSAGE_STATUS_WALL', '8');
531
define('MESSAGE_STATUS_WALL_DELETE', '9');
532
define('MESSAGE_STATUS_WALL_POST', '10');
533
// Images
534
define('IMAGE_WALL_SMALL_SIZE', 200);
535
define('IMAGE_WALL_MEDIUM_SIZE', 500);
536
define('IMAGE_WALL_BIG_SIZE', 2000);
537
define('IMAGE_WALL_SMALL', 'small');
538
define('IMAGE_WALL_MEDIUM', 'medium');
539
define('IMAGE_WALL_BIG', 'big');
540
541
// Social PLUGIN PLACES
542
define('SOCIAL_LEFT_PLUGIN', 1);
543
define('SOCIAL_CENTER_PLUGIN', 2);
544
define('SOCIAL_RIGHT_PLUGIN', 3);
545
define('CUT_GROUP_NAME', 50);
546
547
/**
548
 * FormValidator Filter
549
 */
550
define('NO_HTML', 1);
551
define('STUDENT_HTML', 2);
552
define('TEACHER_HTML', 3);
553
define('STUDENT_HTML_FULLPAGE', 4);
554
define('TEACHER_HTML_FULLPAGE', 5);
555
556
// Timeline
557
define('TIMELINE_STATUS_ACTIVE', '1');
558
define('TIMELINE_STATUS_INACTIVE', '2');
559
560
// Event email template class
561
define('EVENT_EMAIL_TEMPLATE_ACTIVE',  1);
562
define('EVENT_EMAIL_TEMPLATE_INACTIVE', 0);
563
564
// Course home
565
define('SHORTCUTS_HORIZONTAL', 0);
566
define('SHORTCUTS_VERTICAL', 1);
567
568
// Image class
569
define('IMAGE_PROCESSOR', 'gd'); // 'imagick' or 'gd' strings
570
571
// Course copy
572
define('FILE_SKIP', 1);
573
define('FILE_RENAME', 2);
574
define('FILE_OVERWRITE', 3);
575
define('UTF8_CONVERT', false); //false by default
576
577
define('DOCUMENT', 'file');
578
define('FOLDER', 'folder');
579
580
define('RESOURCE_ASSET', 'asset');
581
define('RESOURCE_DOCUMENT', 'document');
582
define('RESOURCE_GLOSSARY', 'glossary');
583
define('RESOURCE_EVENT', 'calendar_event');
584
define('RESOURCE_LINK', 'link');
585
define('RESOURCE_COURSEDESCRIPTION', 'course_description');
586
define('RESOURCE_LEARNPATH', 'learnpath');
587
define('RESOURCE_ANNOUNCEMENT', 'announcement');
588
define('RESOURCE_FORUM', 'forum');
589
define('RESOURCE_FORUMTOPIC', 'thread');
590
define('RESOURCE_FORUMPOST', 'post');
591
define('RESOURCE_QUIZ', 'quiz');
592
define('RESOURCE_TEST_CATEGORY', 'test_category');
593
define('RESOURCE_QUIZQUESTION', 'Exercise_Question');
594
define('RESOURCE_TOOL_INTRO', 'Tool introduction');
595
define('RESOURCE_LINKCATEGORY', 'Link_Category');
596
define('RESOURCE_FORUMCATEGORY', 'Forum_Category');
597
define('RESOURCE_SCORM', 'Scorm');
598
define('RESOURCE_SURVEY', 'survey');
599
define('RESOURCE_SURVEYQUESTION', 'survey_question');
600
define('RESOURCE_SURVEYINVITATION', 'survey_invitation');
601
define('RESOURCE_WIKI', 'wiki');
602
define('RESOURCE_THEMATIC', 'thematic');
603
define('RESOURCE_ATTENDANCE', 'attendance');
604
define('RESOURCE_WORK', 'work');
605
define('RESOURCE_SESSION_COURSE', 'session_course');
606
define('RESOURCE_GRADEBOOK', 'gradebook');
607
define('ADD_THEMATIC_PLAN', 6);
608
609
// Max online users to show per page (whoisonline)
610
define('MAX_ONLINE_USERS', 12);
611
612
// Make sure the CHAMILO_LOAD_WYSIWYG constant is defined
613
// To remove CKeditor libs from HTML, set this constant to true before loading
614
if (!defined('CHAMILO_LOAD_WYSIWYG')) {
615
    define('CHAMILO_LOAD_WYSIWYG', true);
616
}
617
618
/* Constants for course home */
619
define('TOOL_PUBLIC', 'Public');
620
define('TOOL_PUBLIC_BUT_HIDDEN', 'PublicButHide');
621
define('TOOL_COURSE_ADMIN', 'courseAdmin');
622
define('TOOL_PLATFORM_ADMIN', 'platformAdmin');
623
define('TOOL_AUTHORING', 'toolauthoring');
624
define('TOOL_INTERACTION', 'toolinteraction');
625
define('TOOL_COURSE_PLUGIN', 'toolcourseplugin'); //all plugins that can be enabled in courses
626
define('TOOL_ADMIN', 'tooladmin');
627
define('TOOL_ADMIN_PLATFORM', 'tooladminplatform');
628
define('TOOL_DRH', 'tool_drh');
629
define('TOOL_STUDENT_VIEW', 'toolstudentview');
630
define('TOOL_ADMIN_VISIBLE', 'tooladminvisible');
631
632
/**
633
 * Inclusion of internationalization libraries
634
 */
635
require_once __DIR__.'/internationalization.lib.php';
636
637
/**
638
 * Returns a path to a certain resource within the Chamilo area, specifyed through a parameter.
639
 * Also, this function provides conversion between path types, in this case the input path points inside the Chamilo area too.
640
 *
641
 * See $_configuration['course_folder'] in the configuration.php to alter the WEB_COURSE_PATH and SYS_COURSE_PATH parameters.
642
643
 * @param string $path (optional)   A path which type is to be converted. Also, it may be a defined constant for a path.
644
 * This parameter has meaning when $type parameter has one of the following values: TO_WEB, TO_SYS, TO_REL. Otherwise it is ignored.
645
 * @return string                   The requested path or the converted path.
646
 *
647
 *
648
 * Notes about the current behaviour model:
649
 * 1. Windows back-slashes are converted to slashes in the result.
650
 * 2. A semi-absolute web-path is detected by its leading slash. On Linux systems, absolute system paths start with
651
 * a slash too, so an additional check about presence of leading system server base is implemented. For example, the function is
652
 * able to distinguish type difference between /var/www/chamilo/courses/ (SYS) and /chamilo/courses/ (REL).
653
 * 3. The function api_get_path() returns only these three types of paths, which in some sense are absolute. The function has
654
 * no a mechanism for processing relative web/system paths, such as: lesson01.html, ./lesson01.html, ../css/my_styles.css.
655
 * It has not been identified as needed yet.
656
 * 4. Also, resolving the meta-symbols "." and ".." within paths has not been implemented, it is to be identified as needed.
657
 *
658
 * For examples go to: *
659
 * See main/admin/system_status.php?section=paths
660
 *
661
 * Vchamilo changes : allow using an alternate configuration
662
 * to get vchamilo  instance paths
663
*/
664
function api_get_path($path = '', $configuration = [])
665
{
666
    global $paths;
667
668
    // get proper configuration data if exists
669
    global $_configuration;
670
671
    $emptyConfigurationParam = false;
672
    if (empty($configuration)) {
673
        $configuration = (array)$_configuration;
674
        $emptyConfigurationParam = true;
675
    }
676
677
    $course_folder = 'courses/';
678
    static $root_web = '';
679
    $root_sys = $_configuration['root_sys'];
680
681
    // If no $root_web has been set so far *and* no custom config has been passed to the function
682
    // then re-use the previously-calculated (run-specific) $root_web and skip this complex calculation
683
    if (empty($root_web) || $emptyConfigurationParam === false || empty($configuration)) {
684
        // Resolve master hostname.
685
        if (!empty($configuration) && array_key_exists('root_web', $configuration)) {
686
            $root_web = $configuration['root_web'];
687
        } else {
688
            $root_web = '';
689
            // Try guess it from server.
690
            if (defined('SYSTEM_INSTALLATION') && SYSTEM_INSTALLATION) {
691
                if (($pos = strpos(($requested_page_rel = api_get_self()), 'main/install')) !== false) {
692
                    $root_rel = substr($requested_page_rel, 0, $pos);
693
                    // See http://www.mediawiki.org/wiki/Manual:$wgServer
694
                    $server_protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
695
                    $server_name =
696
                        isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME']
697
                            : (isset($_SERVER['HOSTNAME']) ? $_SERVER['HOSTNAME']
698
                            : (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST']
699
                                : (isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR']
700
                                    : 'localhost')));
701
                    if (isset($_SERVER['SERVER_PORT']) && !strpos($server_name, ':')
702
                        && (($server_protocol == 'http'
703
                                && $_SERVER['SERVER_PORT'] != 80) || ($server_protocol == 'https' && $_SERVER['SERVER_PORT'] != 443))
704
                    ) {
705
                        $server_name .= ":" . $_SERVER['SERVER_PORT'];
706
                    }
707
                    $root_web = $server_protocol . '://' . $server_name . $root_rel;
708
                    $root_sys = str_replace('\\', '/', realpath(__DIR__ . '/../../../')) . '/';
709
                }
710
                // Here we give up, so we don't touch anything.
711
            }
712
        }
713
    }
714
715
    if (isset($configuration['multiple_access_urls']) &&
716
        $configuration['multiple_access_urls']
717
    ) {
718
        // To avoid that the api_get_access_url() function fails since global.inc.php also calls the main_api.lib.php
719
        if (isset($configuration['access_url']) && !empty($configuration['access_url'])) {
720
            // We look into the DB the function api_get_access_url
721
            $urlInfo = api_get_access_url($configuration['access_url']);
722
            // Avoid default value
723
            $defaultValues = ['http://localhost/', 'https://localhost/'];
724
            if (!empty($urlInfo['url']) && !in_array($urlInfo['url'], $defaultValues)) {
725
                $root_web = $urlInfo['active'] == 1 ? $urlInfo['url'] : $configuration['root_web'];
726
            }
727
        }
728
    }
729
730
    $paths = [];
731
    // Initialise cache with default values.
732
    if (!array_key_exists($root_web, $paths)) {
733
        $paths[$root_web] = array(
734
            WEB_PATH => '',
735
            SYS_PATH => '',
736
            REL_PATH => '',
737
            WEB_COURSE_PATH => '',
738
            SYS_COURSE_PATH => '',
739
            REL_COURSE_PATH => '',
740
            WEB_CODE_PATH => 'main/',
741
            SYS_CODE_PATH => 'main/',
742
            REL_CODE_PATH => '/main/',
743
            SYS_LANG_PATH => 'lang/',
744
            WEB_IMG_PATH => 'img/',
745
            WEB_CSS_PATH => 'web/css/',
746
            SYS_CSS_PATH => 'app/Resources/public/css/',
747
            SYS_PLUGIN_PATH => 'plugin/',
748
            WEB_PLUGIN_PATH => 'plugin/',
749
            SYS_ARCHIVE_PATH => 'app/cache/',
750
            WEB_ARCHIVE_PATH => 'app/cache/',
751
            SYS_HOME_PATH => 'app/home/',
752
            WEB_HOME_PATH => 'app/home/',
753
            REL_HOME_PATH => 'app/home/',
754
            SYS_APP_PATH => 'app/',
755
            WEB_APP_PATH => 'app/',
756
            SYS_UPLOAD_PATH => 'app/upload/',
757
            SYS_INC_PATH => 'inc/',
758
            CONFIGURATION_PATH => 'app/config/',
759
            LIBRARY_PATH => 'inc/lib/',
760
            WEB_LIBRARY_PATH => 'inc/lib/',
761
            WEB_LIBRARY_JS_PATH => 'inc/lib/javascript/',
762
            WEB_AJAX_PATH => 'inc/ajax/',
763
            SYS_TEST_PATH => 'tests/',
764
            WEB_TEMPLATE_PATH => 'template/',
765
            SYS_TEMPLATE_PATH => 'template/',
766
            WEB_UPLOAD_PATH => 'app/upload/',
767
            WEB_PUBLIC_PATH => 'web/',
768
            SYS_PUBLIC_PATH => 'web/',
769
            WEB_FONTS_PATH => 'fonts/',
770
            SYS_FONTS_PATH => 'fonts/',
771
        );
772
    }
773
774
    $isInitialized = [];
775
    $course_folder = isset($configuration['course_folder']) ? $configuration['course_folder'] : $course_folder;
776
    $root_rel = isset($configuration['url_append']) ? $configuration['url_append'] : '';
777
778
    // Web server base and system server base.
779
    if (!array_key_exists($root_web, $isInitialized)) {
780
        // process absolute global roots
781
        if (!empty($configuration)) {
782
            $code_folder = 'main';
783
        } else {
784
            $code_folder = $paths[$root_web][REL_CODE_PATH];
785
        }
786
787
        // Support for the installation process.
788
        // Developers might use the function api_get_path() directly or indirectly (this is difficult to be traced), at the moment when
789
        // configuration has not been created yet. This is why this function should be upgraded to return correct results in this case.
790
791
        // Dealing with trailing slashes.
792
        $slashed_root_web = api_add_trailing_slash($root_web);
793
        $root_sys = api_add_trailing_slash($root_sys);
794
        $root_rel = api_add_trailing_slash($root_rel);
795
        $code_folder = api_add_trailing_slash($code_folder);
796
        $course_folder = api_add_trailing_slash($course_folder);
797
798
        // Initialization of a table that contains common-purpose paths.
799
        $paths[$root_web][REL_PATH] = $root_rel;
800
        $paths[$root_web][REL_COURSE_PATH] = $root_rel.$course_folder;
801
        $paths[$root_web][REL_DEFAULT_COURSE_DOCUMENT_PATH] = $paths[$root_web][REL_PATH].'main/default_course_document/';
802
803
        $paths[$root_web][WEB_PATH] = $slashed_root_web;
804
        $paths[$root_web][WEB_CODE_PATH] = $paths[$root_web][WEB_PATH].$code_folder;
805
        $paths[$root_web][WEB_COURSE_PATH] = $paths[$root_web][WEB_PATH].$course_folder;
806
        $paths[$root_web][WEB_DEFAULT_COURSE_DOCUMENT_PATH] = $paths[$root_web][WEB_CODE_PATH].'default_course_document/';
807
        $paths[$root_web][WEB_APP_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_APP_PATH];
808
        $paths[$root_web][WEB_PLUGIN_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_PLUGIN_PATH];
809
        $paths[$root_web][WEB_ARCHIVE_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_ARCHIVE_PATH];
810
811
        $paths[$root_web][WEB_CSS_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_CSS_PATH];
812
        $paths[$root_web][WEB_IMG_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_IMG_PATH];
813
        $paths[$root_web][WEB_LIBRARY_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_LIBRARY_PATH];
814
        $paths[$root_web][WEB_LIBRARY_JS_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_LIBRARY_JS_PATH];
815
        $paths[$root_web][WEB_AJAX_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_AJAX_PATH];
816
        $paths[$root_web][WEB_FONTS_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_FONTS_PATH];
817
        $paths[$root_web][WEB_TEMPLATE_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_TEMPLATE_PATH];
818
        $paths[$root_web][WEB_UPLOAD_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_UPLOAD_PATH];
819
        $paths[$root_web][WEB_PUBLIC_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_PUBLIC_PATH];
820
        $paths[$root_web][WEB_HOME_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][REL_HOME_PATH];
821
822
        $paths[$root_web][SYS_PATH] = $root_sys;
823
        $paths[$root_web][SYS_CODE_PATH] = $root_sys.$code_folder;
824
        $paths[$root_web][SYS_TEST_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_TEST_PATH];
825
        $paths[$root_web][SYS_TEMPLATE_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_TEMPLATE_PATH];
826
        $paths[$root_web][SYS_PUBLIC_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_PUBLIC_PATH];
827
        $paths[$root_web][SYS_CSS_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_CSS_PATH];
828
        $paths[$root_web][SYS_FONTS_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_FONTS_PATH];
829
        $paths[$root_web][SYS_ARCHIVE_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_ARCHIVE_PATH];
830
        $paths[$root_web][SYS_APP_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_APP_PATH];
831
        $paths[$root_web][SYS_COURSE_PATH] = $paths[$root_web][SYS_APP_PATH].$course_folder;
832
        $paths[$root_web][SYS_UPLOAD_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_UPLOAD_PATH];
833
        $paths[$root_web][SYS_LANG_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_LANG_PATH];
834
        $paths[$root_web][SYS_HOME_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_HOME_PATH];
835
        $paths[$root_web][SYS_PLUGIN_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_PLUGIN_PATH];
836
        $paths[$root_web][SYS_INC_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_INC_PATH];
837
838
        $paths[$root_web][LIBRARY_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][LIBRARY_PATH];
839
        $paths[$root_web][CONFIGURATION_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][CONFIGURATION_PATH];
840
841
        global $virtualChamilo;
842
        if (!empty($virtualChamilo)) {
843
            $paths[$root_web][SYS_ARCHIVE_PATH] = api_add_trailing_slash($virtualChamilo[SYS_ARCHIVE_PATH]);
844
            $paths[$root_web][SYS_HOME_PATH] = api_add_trailing_slash($virtualChamilo[SYS_HOME_PATH]);
845
            $paths[$root_web][SYS_COURSE_PATH] = api_add_trailing_slash($virtualChamilo[SYS_COURSE_PATH]);
846
            $paths[$root_web][SYS_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[SYS_UPLOAD_PATH]);
847
848
            $paths[$root_web][WEB_HOME_PATH] = api_add_trailing_slash($virtualChamilo[WEB_HOME_PATH]);
849
            $paths[$root_web][WEB_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[WEB_UPLOAD_PATH]);
850
            $paths[$root_web][WEB_ARCHIVE_PATH] = api_add_trailing_slash($virtualChamilo[WEB_ARCHIVE_PATH]);
851
            //$paths[$root_web][WEB_COURSE_PATH] = api_add_trailing_slash($virtualChamilo[WEB_COURSE_PATH]);
852
853
            // WEB_UPLOAD_PATH should be handle by apache htaccess in the vhost
854
855
            // RewriteEngine On
856
            // RewriteRule /app/upload/(.*)$ http://localhost/other/upload/my-chamilo111-net/$1 [QSA,L]
857
858
            //$paths[$root_web][WEB_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[WEB_UPLOAD_PATH]);
859
            //$paths[$root_web][REL_PATH] = $virtualChamilo[REL_PATH];
860
            //$paths[$root_web][REL_COURSE_PATH] = $virtualChamilo[REL_COURSE_PATH];
861
        }
862
863
        $isInitialized[$root_web] = true;
864
    }
865
866
    $path = trim($path);
867
868
    // Retrieving a common-purpose path.
869
    if (isset($paths[$root_web][$path])) {
870
        return $paths[$root_web][$path];
871
    }
872
873
    // Second purification.
874
875
    // Replacing Windows back slashes.
876
    $path = str_replace('\\', '/', $path);
877
    // Query strings sometimes mighth wrongly appear in non-URLs.
878
    // Let us check remove them from all types of paths.
879
    if (($pos = strpos($path, '?')) !== false) {
880
        $path = substr($path, 0, $pos);
881
    }
882
883
    // Detection of the input path type. Conversion to semi-absolute type ( /chamilo/main/inc/.... ).
884
885
    if (preg_match(VALID_WEB_PATH, $path)) {
886
        // A special case: When a URL points to the document download script directly, without
887
        // mod-rewrite translation, we have to translate it into an "ordinary" web path.
888
        // For example:
889
        // http://localhost/chamilo/main/document/download.php?doc_url=/image.png&cDir=/
890
        // becomes
891
        // http://localhost/chamilo/courses/TEST/document/image.png
892
        // TEST is a course directory name, so called "system course code".
893
        if (strpos($path, 'download.php') !== false) { // Fast detection first.
894
            $path = urldecode($path);
895
            if (preg_match('/(.*)main\/document\/download.php\?doc_url=\/(.*)&cDir=\/(.*)?/', $path, $matches)) {
896
                $sys_course_code =
897
                    isset($_SESSION['_course']['sysCode'])  // User is inside a course?
898
                        ? $_SESSION['_course']['sysCode']   // Yes, then use course's directory name.
899
                        : '{SYS_COURSE_CODE}';              // No, then use a fake code, it may be processed later.
900
                $path = $matches[1].'courses/'.$sys_course_code.'/document/'.str_replace('//', '/', $matches[3].'/'.$matches[2]);
901
            }
902
        }
903
        // Replacement of the present web server base with a slash '/'.
904
        $path = preg_replace(VALID_WEB_SERVER_BASE, '/', $path);
905
    }
906
907
    // Path now is semi-absolute. It is convenient at this moment repeated slashes to be removed.
908
    $path = preg_replace(REPEATED_SLASHES_PURIFIER, '/', $path);
909
910
    return $path;
911
}
912
913
/**
914
 * Gets a modified version of the path for the CDN, if defined in
915
 * configuration.php
916
 * @param string $web_path The path of the resource without CDN
917
 * @return string The path of the resource converted to CDN
918
 * @author Yannick Warnier <[email protected]>
919
 */
920
function api_get_cdn_path($web_path)
921
{
922
    global $_configuration;
923
    $web_root = api_get_path(WEB_PATH);
924
    $ext = substr($web_path, strrpos($web_path, '.'));
925
    if (isset($ext[2])) { // faster version of strlen to check if len>2
926
        // Check for CDN definitions
927
        if (!empty($_configuration['cdn_enable']) && !empty($ext)) {
928
            foreach ($_configuration['cdn'] as $host => $exts) {
929
                if (in_array($ext, $exts)) {
930
                    //Use host as defined in $_configuration['cdn'], without
931
                    // trailing slash
932
                    return str_replace($web_root,$host.'/',$web_path);
933
                }
934
            }
935
        }
936
    }
937
    return $web_path;
938
}
939
940
/**
941
 * @return bool Return true if CAS authentification is activated
942
 *
943
 */
944
function api_is_cas_activated() {
945
    return api_get_setting('cas_activate') == "true";
946
}
947
948
/**
949
 * @return bool     Return true if LDAP authentification is activated
950
 *
951
 */
952
function api_is_ldap_activated() {
953
    global $extAuthSource;
954
    return is_array($extAuthSource[LDAP_AUTH_SOURCE]);
955
}
956
957
/**
958
 * @return bool     Return true if Facebook authentification is activated
959
 *
960
 */
961
function api_is_facebook_auth_activated() {
962
    global $_configuration;
963
    return (isset($_configuration['facebook_auth']) && $_configuration['facebook_auth'] == 1);
964
}
965
966
/**
967
 * This function checks whether a given path points inside the system.
968
 * @param string $path      The path to be tested.
969
 * It should be full path, web-absolute (WEB), semi-absolute (REL) or system-absolyte (SYS).
970
 * @return bool             Returns true when the given path is inside the system, false otherwise.
971
 */
972
function api_is_internal_path($path) {
973
    $path = str_replace('\\', '/', trim($path));
974
    if (empty($path)) {
975
        return false;
976
    }
977
    if (strpos($path, api_remove_trailing_slash(api_get_path(WEB_PATH))) === 0) {
978
        return true;
979
    }
980
    if (strpos($path, api_remove_trailing_slash(api_get_path(SYS_PATH))) === 0) {
981
        return true;
982
    }
983
    $server_base_web = api_remove_trailing_slash(api_get_path(REL_PATH));
984
    $server_base_web = empty($server_base_web) ? '/' : $server_base_web;
985
    if (strpos($path, $server_base_web) === 0) {
986
        return true;
987
    }
988
    return false;
989
}
990
991
/**
992
 * Adds to a given path a trailing slash if it is necessary (adds "/" character at the end of the string).
993
 * @param string $path          The input path.
994
 * @return string               Returns the modified path.
995
 */
996
function api_add_trailing_slash($path) {
997
    return substr($path, -1) == '/' ? $path : $path.'/';
998
}
999
1000
/**
1001
 * Removes from a given path the trailing slash if it is necessary (removes "/" character from the end of the string).
1002
 * @param string $path          The input path.
1003
 * @return string               Returns the modified path.
1004
 */
1005
function api_remove_trailing_slash($path) {
1006
    return substr($path, -1) == '/' ? substr($path, 0, -1) : $path;
1007
}
1008
1009
/**
1010
 * Checks the RFC 3986 syntax of a given URL.
1011
 * @param string $url       The URL to be checked.
1012
 * @param bool $absolute    Whether the URL is absolute (beginning with a scheme such as "http:").
1013
 * @return string|false             Returns the URL if it is valid, FALSE otherwise.
1014
 * This function is an adaptation from the function valid_url(), Drupal CMS.
1015
 * @link http://drupal.org
1016
 * Note: The built-in function filter_var($urs, FILTER_VALIDATE_URL) has a bug for some versions of PHP.
1017
 * @link http://bugs.php.net/51192
1018
 */
1019
function api_valid_url($url, $absolute = false) {
1020
    if ($absolute) {
1021
        if (preg_match("
1022
            /^                                                      # Start at the beginning of the text
1023
            (?:ftp|https?|feed):\/\/                                # Look for ftp, http, https or feed schemes
1024
            (?:                                                     # Userinfo (optional) which is typically
1025
                (?:(?:[\w\.\-\+!$&'\(\)*\+,;=]|%[0-9a-f]{2})+:)*    # a username or a username and password
1026
                (?:[\w\.\-\+%!$&'\(\)*\+,;=]|%[0-9a-f]{2})+@        # combination
1027
            )?
1028
            (?:
1029
                (?:[a-z0-9\-\.]|%[0-9a-f]{2})+                      # A domain name or a IPv4 address
1030
                |(?:\[(?:[0-9a-f]{0,4}:)*(?:[0-9a-f]{0,4})\])       # or a well formed IPv6 address
1031
            )
1032
            (?::[0-9]+)?                                            # Server port number (optional)
1033
            (?:[\/|\?]
1034
                (?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2}) # The path and query (optional)
1035
            *)?
1036
            $/xi", $url)) {
1037
            return $url;
1038
        }
1039
        return false;
1040
    } else {
1041
        return preg_match("/^(?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2})+$/i", $url) ? $url : false;
1042
    }
1043
}
1044
1045
/**
1046
 * Checks whether a given string looks roughly like an email address.
1047
 *
1048
 * @param string $address   The e-mail address to be checked.
1049
 * @return mixed            Returns the e-mail if it is valid, FALSE otherwise.
1050
 */
1051
function api_valid_email($address)
1052
{
1053
    return filter_var($address, FILTER_VALIDATE_EMAIL);
1054
}
1055
1056
/* PROTECTION FUNCTIONS
1057
   Use these functions to protect your scripts. */
1058
1059
/**
1060
 * Function used to protect a course script.
1061
 * The function blocks access when
1062
 * - there is no $_SESSION["_course"] defined; or
1063
 * - $is_allowed_in_course is set to false (this depends on the course
1064
 * visibility and user status).
1065
 *
1066
 * This is only the first proposal, test and improve!
1067
 * @param boolean       Option to print headers when displaying error message. Default: false
1068
 * @param boolean       Whether session admins should be allowed or not.
1069
 * @return boolean      True if the user has access to the current course or is out of a course context, false otherwise
1070
 * @todo replace global variable
1071
 * @author Roan Embrechts
1072
 */
1073
function api_protect_course_script($print_headers = false, $allow_session_admins = false, $allow_drh = false)
1074
{
1075
    $is_allowed_in_course = api_is_allowed_in_course();
1076
1077
    $is_visible = false;
1078
    $course_info = api_get_course_info();
1079
1080
    if (empty($course_info)) {
1081
        api_not_allowed($print_headers);
1082
        return false;
1083
    }
1084
1085
    if (api_is_drh()) {
1086
        return true;
1087
    }
1088
1089
    if (api_is_platform_admin($allow_session_admins)) {
1090
        return true;
1091
    }
1092
1093
    if (isset($course_info) && isset($course_info['visibility'])) {
1094
        switch ($course_info['visibility']) {
1095
            default:
1096 View Code Duplication
            case COURSE_VISIBILITY_CLOSED:
1097
                // Completely closed: the course is only accessible to the teachers. - 0
1098
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1099
                    $is_visible = true;
1100
                }
1101
                break;
1102 View Code Duplication
            case COURSE_VISIBILITY_REGISTERED:
1103
                // Private - access authorized to course members only - 1
1104
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1105
                    $is_visible = true;
1106
                }
1107
                break;
1108 View Code Duplication
            case COURSE_VISIBILITY_OPEN_PLATFORM:
1109
                // Open - access allowed for users registered on the platform - 2
1110
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1111
                    $is_visible = true;
1112
                }
1113
                break;
1114
            case COURSE_VISIBILITY_OPEN_WORLD:
1115
                //Open - access allowed for the whole world - 3
1116
                $is_visible = true;
1117
                break;
1118
            case COURSE_VISIBILITY_HIDDEN:
1119
                //Completely closed: the course is only accessible to the teachers. - 0
1120
                if (api_is_platform_admin()) {
1121
                    $is_visible = true;
1122
                }
1123
                break;
1124
        }
1125
1126
        //If password is set and user is not registered to the course then the course is not visible
1127
        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...
1128
            isset($course_info['registration_code']) &&
1129
            !empty($course_info['registration_code'])
1130
        ) {
1131
            $is_visible = false;
1132
        }
1133
    }
1134
1135
    // Check session visibility
1136
    $session_id = api_get_session_id();
1137
1138
    if (!empty($session_id)) {
1139
        //$is_allowed_in_course was set in local.inc.php
1140
        if (!$is_allowed_in_course) {
1141
            $is_visible = false;
1142
        }
1143
    }
1144
1145
    if (!$is_visible) {
1146
        api_not_allowed($print_headers);
1147
        return false;
1148
    }
1149
    return true;
1150
}
1151
1152
/**
1153
 * Function used to protect an admin script.
1154
 *
1155
 * The function blocks access when the user has no platform admin rights
1156
 * with an error message printed on default output
1157
 * @param bool Whether to allow session admins as well
1158
 * @param bool Whether to allow HR directors as well
1159
 * @param string An optional message (already passed through get_lang)
1160
 * @return bool True if user is allowed, false otherwise.
1161
 * The function also outputs an error message in case not allowed
1162
 * @author Roan Embrechts (original author)
1163
 */
1164
function api_protect_admin_script($allow_sessions_admins = false, $allow_drh = false, $message = null)
1165
{
1166
    if (!api_is_platform_admin($allow_sessions_admins, $allow_drh)) {
1167
        api_not_allowed(true, $message);
1168
        return false;
1169
    }
1170
    return true;
1171
}
1172
1173
/**
1174
 * Function used to protect a teacher script.
1175
 * The function blocks access when the user has no teacher rights.
1176
 *
1177
 * @author Yoselyn Castillo
1178
 */
1179
function api_protect_teacher_script($allow_sessions_admins = false)
1180
{
1181
    if (!api_is_allowed_to_edit()) {
1182
        api_not_allowed(true);
1183
        return false;
1184
    }
1185
    return true;
1186
}
1187
1188
/**
1189
 * Function used to prevent anonymous users from accessing a script.
1190
 * @param bool|true $printHeaders
1191
 * @author Roan Embrechts
1192
 *
1193
 * @return bool
1194
 */
1195
function api_block_anonymous_users($printHeaders = true)
1196
{
1197
    $user = api_get_user_info();
1198 View Code Duplication
    if (!(isset($user['user_id']) && $user['user_id']) || api_is_anonymous($user['user_id'], true)) {
1199
        api_not_allowed($printHeaders);
1200
        return false;
1201
    }
1202
1203
    return true;
1204
}
1205
1206
/**
1207
 * @return array with the navigator name and version
1208
 */
1209
function api_get_navigator() {
1210
    $navigator = 'Unknown';
1211
    $version = 0;
1212
1213
    if (!isset($_SERVER['HTTP_USER_AGENT'])) {
1214
        return array('name' => 'Unknown', 'version' => '0.0.0');
1215
    }
1216
1217
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') !== false) {
1218
        $navigator = 'Opera';
1219
        list (, $version) = explode('Opera', $_SERVER['HTTP_USER_AGENT']);
1220 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {
1221
        $navigator = 'Internet Explorer';
1222
        list (, $version) = explode('MSIE', $_SERVER['HTTP_USER_AGENT']);
1223
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome') !== false) {
1224
        $navigator = 'Chrome';
1225
        list (, $version) = explode('Chrome', $_SERVER['HTTP_USER_AGENT']);
1226 View Code Duplication
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'safari') !== false) {
1227
        $navigator = 'Safari';
1228
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1229
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Gecko') !== false) {
1230
        $navigator = 'Mozilla';
1231
        list (, $version) = explode('; rv:', $_SERVER['HTTP_USER_AGENT']);
1232 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Netscape') !== false) {
1233
        $navigator = 'Netscape';
1234
        list (, $version) = explode('Netscape', $_SERVER['HTTP_USER_AGENT']);
1235
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Konqueror') !== false) {
1236
        $navigator = 'Konqueror';
1237
        list (, $version) = explode('Konqueror', $_SERVER['HTTP_USER_AGENT']);
1238 View Code Duplication
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'applewebkit') !== false) {
1239
        $navigator = 'AppleWebKit';
1240
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1241
    }
1242
    $version = str_replace('/', '', $version);
1243
    if (strpos($version, '.') === false) {
1244
        $version = number_format(doubleval($version), 1);
1245
    }
1246
    $return = array('name' => $navigator, 'version' => $version);
1247
    return $return;
1248
}
1249
1250
/**
1251
 * @return True if user self registration is allowed, false otherwise.
1252
 */
1253
function api_is_self_registration_allowed()
1254
{
1255
    return isset($GLOBALS['allowSelfReg']) ? $GLOBALS['allowSelfReg'] : false;
1256
}
1257
1258
/**
1259
 * This function returns the id of the user which is stored in the $_user array.
1260
 *
1261
 * example: The function can be used to check if a user is logged in
1262
 *          if (api_get_user_id())
1263
 * @return int the id of the current user, 0 if is empty
1264
 */
1265
function api_get_user_id()
1266
{
1267
    $userInfo = Session::read('_user');
1268
    if ($userInfo && isset($userInfo['user_id'])) {
1269
        return (int) $userInfo['user_id'];
1270
    }
1271
    return 0;
1272
}
1273
1274
/**
1275
 * Gets the list of courses a specific user is subscribed to
1276
 * @param int       User ID
1277
 * @param boolean   $fetch_session Whether to get session courses or not - NOT YET IMPLEMENTED
1278
 * @return array    Array of courses in the form [0]=>('code'=>xxx,'db'=>xxx,'dir'=>xxx,'status'=>d)
1279
 */
1280
function api_get_user_courses($userid, $fetch_session = true)
1281
{
1282
    // Get out if not integer
1283
    if ($userid != strval(intval($userid))) {
1284
        return array();
1285
    }
1286
1287
    $t_course = Database::get_main_table(TABLE_MAIN_COURSE);
1288
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1289
1290
    $sql = "SELECT cc.id as real_id, cc.code code, cc.directory dir, cu.status status
1291
            FROM    $t_course       cc,
1292
                    $t_course_user   cu
1293
            WHERE
1294
                cc.id = cu.c_id AND
1295
                cu.user_id = '".$userid."' AND
1296
                cu.relation_type<>".COURSE_RELATION_TYPE_RRHH." ";
1297
    $result = Database::query($sql);
1298
    if ($result === false) {
1299
        return array();
1300
    }
1301
1302
    $courses = array();
1303
    while ($row = Database::fetch_array($result)) {
1304
        // we only need the database name of the course
1305
        $courses[] = $row;
1306
    }
1307
1308
    return $courses;
1309
}
1310
1311
/**
1312
 * Formats user information into a standard array
1313
 * This function should be only used inside api_get_user_info()
1314
 *
1315
 * @param array Non-standard user array
1316
 * @param bool $add_password
1317
 * @param bool $loadAvatars turn off to improve performance
1318
 *
1319
 * @return array Standard user array
1320
 */
1321
function _api_format_user($user, $add_password = false, $loadAvatars = true)
1322
{
1323
    $result = array();
1324
1325
    $result['firstname'] = null;
1326
    $result['lastname'] = null;
1327
    if (isset($user['firstname']) && isset($user['lastname'])) { // with only lowercase
1328
        $result['firstname'] = $user['firstname'];
1329
        $result['lastname'] = $user['lastname'];
1330
    } elseif (isset($user['firstName']) && isset($user['lastName'])) { // with uppercase letters
1331
        $result['firstname'] = isset($user['firstName']) ? $user['firstName'] : null;
1332
        $result['lastname'] = isset($user['lastName']) ? $user['lastName'] : null;
1333
    }
1334
1335
    $result['complete_name'] = api_get_person_name($result['firstname'], $result['lastname']);
1336
    $result['complete_name_with_username'] = $result['complete_name'];
1337
1338
    if (!empty($user['username'])) {
1339
        $result['complete_name_with_username'] = $result['complete_name'].' ('.$user['username'].')';
1340
    }
1341
1342
    // Kept for historical reasons
1343
    $result['firstName'] = $result['firstname'];
1344
    $result['lastName'] = $result['lastname'];
1345
1346
    $attributes = array(
1347
        'phone',
1348
        'address',
1349
        'picture_uri',
1350
        'official_code',
1351
        'status',
1352
        'active',
1353
        'auth_source',
1354
        'username',
1355
        'theme',
1356
        'language',
1357
        'creator_id',
1358
        'registration_date',
1359
        'hr_dept_id',
1360
        'expiration_date',
1361
        'last_login'
1362
    );
1363
    if (api_get_setting('extended_profile') === 'true') {
1364
        $attributes[] = 'competences';
1365
        $attributes[] = 'diplomas';
1366
        $attributes[] = 'teach';
1367
        $attributes[] = 'openarea';
1368
    }
1369
1370
    foreach ($attributes as $attribute) {
1371
        $result[$attribute] = isset($user[$attribute]) ? $user[$attribute] : null;
1372
    }
1373
1374
    if (isset($user['email'])) {
1375
        $result['mail'] = isset($user['email']) ? $user['email'] : null;
1376
        $result['email'] = isset($user['email'])? $user['email'] : null;
1377
    } else {
1378
        $result['mail'] = isset($user['mail']) ? $user['mail'] : null;
1379
        $result['email'] = isset($user['mail'])? $user['mail'] : null;
1380
    }
1381
    $user_id = intval($user['user_id']);
1382
    // Maintain the user_id index for backwards compatibility
1383
    $result['user_id'] = $result['id'] = $user_id;
1384
1385
    // Getting user avatar.
1386
    if ($loadAvatars) {
1387
        $originalFile = UserManager::getUserPicture(
1388
            $user_id,
1389
            USER_IMAGE_SIZE_ORIGINAL,
1390
            null,
1391
            $result
1392
        );
1393
        $smallFile = UserManager::getUserPicture(
1394
            $user_id,
1395
            USER_IMAGE_SIZE_SMALL,
1396
            null,
1397
            $result
1398
        );
1399
        $mediumFile = UserManager::getUserPicture(
1400
            $user_id,
1401
            USER_IMAGE_SIZE_MEDIUM,
1402
            null,
1403
            $result
1404
        );
1405
1406
        $result['avatar'] = $originalFile;
1407
        $avatarString = explode('?', $originalFile);
1408
        $result['avatar_no_query'] = reset($avatarString);
1409
        $result['avatar_small'] = $smallFile;
1410
        $result['avatar_medium'] = $mediumFile;
1411
    }
1412
1413
    if (isset($user['user_is_online'])) {
1414
        $result['user_is_online'] = $user['user_is_online'] == true ? 1 : 0;
1415
    }
1416
    if (isset($user['user_is_online_in_chat'])) {
1417
        $result['user_is_online_in_chat'] = intval($user['user_is_online_in_chat']);
1418
    }
1419
1420
    if ($add_password) {
1421
        $result['password'] = $user['password'];
1422
    }
1423
1424
    if (isset($result['profile_completed'])) {
1425
        $result['profile_completed'] = $user['profile_completed'];
1426
    }
1427
1428
    $result['profile_url'] = api_get_path(WEB_CODE_PATH).'social/profile.php?u='.$user_id;
1429
1430
    if (isset($user['extra'])) {
1431
        $result['extra'] = $user['extra'];
1432
    }
1433
1434
    return $result;
1435
}
1436
1437
/**
1438
 * Finds all the information about a user.
1439
 * If no parameter is passed you find all the information about the current user.
1440
 * @param int  $user_id
1441
 * @param bool $checkIfUserOnline
1442
 * @param bool $showPassword
1443
 * @param bool $loadExtraData
1444
 * @param bool $loadOnlyVisibleExtraData Get the user extra fields that are visible
1445
 * @param bool $loadAvatars turn off to improve performance and if avatars are not needed.
1446
 * @return array $user_info user_id, lastname, firstname, username, email, etc
1447
 * @author Patrick Cool <[email protected]>
1448
 * @author Julio Montoya
1449
 * @version 21 September 2004
1450
 */
1451
function api_get_user_info(
1452
    $user_id = 0,
1453
    $checkIfUserOnline = false,
1454
    $showPassword = false,
1455
    $loadExtraData = false,
1456
    $loadOnlyVisibleExtraData = false,
1457
    $loadAvatars = true
1458
) {
1459
    $apcVar = null;
1460
    $user = false;
1461
    $cacheAvailable = api_get_configuration_value('apc');
1462
1463
    if (empty($user_id)) {
1464
        $userFromSession = Session::read('_user');
1465
1466
        if (isset($userFromSession)) {
1467
            if ($cacheAvailable === true) {
1468
                $apcVar = api_get_configuration_value('apc_prefix') . 'userinfo_' . $userFromSession['user_id'];
1469
                if (apcu_exists($apcVar)) {
1470
                    $user = apcu_fetch($apcVar);
1471
                } else {
1472
                    $user = _api_format_user($userFromSession, $showPassword, $loadAvatars);
1473
                    apcu_store($apcVar, $user, 60);
1474
                }
1475
            } else {
1476
                $user = _api_format_user($userFromSession, $showPassword, $loadAvatars);
1477
            }
1478
1479
            return $user;
1480
        }
1481
1482
        return false;
1483
    }
1484
1485
    // Make sure user_id is safe
1486
    $user_id = intval($user_id);
1487
1488
    // Re-use user information if not stale and already stored in APCu
1489 View Code Duplication
    if ($cacheAvailable === true) {
1490
        $apcVar = api_get_configuration_value('apc_prefix') . 'userinfo_' . $user_id;
1491
        if (apcu_exists($apcVar)) {
1492
            $user = apcu_fetch($apcVar);
1493
1494
            return $user;
1495
        }
1496
    }
1497
1498
    $sql = "SELECT * FROM " . Database:: get_main_table(TABLE_MAIN_USER) . "
1499
            WHERE id = $user_id";
1500
    $result = Database::query($sql);
1501
    if (Database::num_rows($result) > 0) {
1502
        $result_array = Database::fetch_array($result);
1503
        if ($checkIfUserOnline) {
1504
            $use_status_in_platform = user_is_online($user_id);
1505
            $result_array['user_is_online'] = $use_status_in_platform;
1506
            $user_online_in_chat = 0;
1507
1508
            if ($use_status_in_platform) {
1509
                $user_status = UserManager::get_extra_user_data_by_field(
1510
                    $user_id,
1511
                    'user_chat_status',
1512
                    false,
1513
                    true
1514
                );
1515
                if (@intval($user_status['user_chat_status']) == 1) {
1516
                    $user_online_in_chat = 1;
1517
                }
1518
            }
1519
            $result_array['user_is_online_in_chat'] = $user_online_in_chat;
1520
        }
1521
1522
        if ($loadExtraData) {
1523
            $fieldValue = new ExtraFieldValue('user');
1524
            $result_array['extra'] = $fieldValue->getAllValuesForAnItem(
1525
                $user_id,
1526
                $loadOnlyVisibleExtraData
1527
            );
1528
        }
1529
        $user = _api_format_user($result_array, $showPassword, $loadAvatars);
1530
    }
1531
    if (!empty($cacheAvailable)) {
1532
        apcu_store($apcVar, $user, 60);
1533
    }
1534
1535
    return $user;
1536
}
1537
1538
/**
1539
 * @param int $userId
1540
 * @return User
1541
 */
1542
function api_get_user_entity($userId)
1543
{
1544
    /** @var \Chamilo\UserBundle\Repository\UserRepository $repo */
1545
    $repo = Database::getManager()->getRepository('ChamiloUserBundle:User');
1546
1547
    return $repo->find($userId);
1548
}
1549
1550
/**
1551
 * Finds all the information about a user from username instead of user id
1552
 * @param string $username
1553
 * @return array $user_info array user_id, lastname, firstname, username, email
1554
 * @author Yannick Warnier <[email protected]>
1555
 */
1556 View Code Duplication
function api_get_user_info_from_username($username = '')
1557
{
1558
    if (empty($username)) {
1559
        return false;
1560
    }
1561
    $username = trim($username);
1562
1563
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1564
            WHERE username='".Database::escape_string($username)."'";
1565
    $result = Database::query($sql);
1566
    if (Database::num_rows($result) > 0) {
1567
        $result_array = Database::fetch_array($result);
1568
        return _api_format_user($result_array);
1569
    }
1570
    return false;
1571
}
1572
1573
/**
1574
 * Get first user with an email
1575
 * @param string $email
1576
 * @return array|bool
1577
 */
1578 View Code Duplication
function api_get_user_info_from_email($email = '')
1579
{
1580
    if (empty($email)) {
1581
        return false;
1582
    }
1583
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1584
            WHERE email ='".Database::escape_string($email)."' LIMIT 1";
1585
    $result = Database::query($sql);
1586
    if (Database::num_rows($result) > 0) {
1587
        $result_array = Database::fetch_array($result);
1588
        return _api_format_user($result_array);
1589
    }
1590
1591
    return false;
1592
}
1593
1594
/**
1595
 * @return string
1596
 */
1597
function api_get_course_id()
1598
{
1599
    return Session::read('_cid', null);
1600
}
1601
1602
/**
1603
 * Returns the current course id (integer)
1604
 * @param   string  $code   Optional course code
1605
 * @return int
1606
 */
1607
function api_get_course_int_id($code = null)
1608
{
1609 View Code Duplication
    if (!empty($code)) {
1610
        $code = Database::escape_string($code);
1611
        $row = Database::select(
1612
            'id',
1613
            Database::get_main_table(TABLE_MAIN_COURSE),
1614
            array('where'=> array('code = ?' => array($code))),
1615
            'first'
1616
        );
1617
1618
        if (is_array($row) && isset($row['id'])) {
1619
            return $row['id'];
1620
        } else {
1621
            return false;
1622
        }
1623
    }
1624
    return Session::read('_real_cid', 0);
1625
}
1626
1627
/**
1628
 * Returns the current course directory
1629
 *
1630
 * This function relies on api_get_course_info()
1631
 * @param string    The course code - optional (takes it from session if not given)
1632
 * @return string   The directory where the course is located inside the Chamilo "courses" directory
1633
 * @author Yannick Warnier <[email protected]>
1634
 */
1635
function api_get_course_path($course_code = null)
1636
{
1637
    $info = !empty($course_code) ? api_get_course_info($course_code) : api_get_course_info();
1638
    return $info['path'];
1639
}
1640
1641
/**
1642
 * Gets a course setting from the current course_setting table. Try always using integer values.
1643
 * @param string    The name of the setting we want from the table
1644
 * @param string    Optional: course code
1645
 * @param string $setting_name
1646
 * @return mixed    The value of that setting in that table. Return -1 if not found.
1647
 */
1648
function api_get_course_setting($setting_name, $course_code = null)
1649
{
1650
    $course_info = api_get_course_info($course_code);
1651
    $table = Database::get_course_table(TABLE_COURSE_SETTING);
1652
    $setting_name = Database::escape_string($setting_name);
1653
    if (!empty($course_info['real_id']) && !empty($setting_name)) {
1654
        $sql = "SELECT value FROM $table
1655
                WHERE c_id = {$course_info['real_id']} AND variable = '$setting_name'";
1656
        $res = Database::query($sql);
1657
        if (Database::num_rows($res) > 0) {
1658
            $row = Database::fetch_array($res);
1659
            return $row['value'];
1660
        }
1661
    }
1662
    return -1;
1663
}
1664
1665
/**
1666
 * Gets an anonymous user ID
1667
 *
1668
 * For some tools that need tracking, like the learnpath tool, it is necessary
1669
 * to have a usable user-id to enable some kind of tracking, even if not
1670
 * perfect. An anonymous ID is taken from the users table by looking for a
1671
 * status of "6" (anonymous).
1672
 * @return int  User ID of the anonymous user, or O if no anonymous user found
1673
 */
1674
function api_get_anonymous_id()
1675
{
1676
    $table = Database::get_main_table(TABLE_MAIN_USER);
1677
    $sql = "SELECT user_id FROM $table WHERE status = ".ANONYMOUS;
1678
    $res = Database::query($sql);
1679
    if (Database::num_rows($res) > 0) {
1680
        $row = Database::fetch_array($res);
1681
        return $row['user_id'];
1682
    }
1683
1684
    // No anonymous user was found.
1685
    return 0;
1686
}
1687
1688
/**
1689
 * @param string $courseCode
1690
 * @param int $sessionId
1691
 * @param int $groupId
1692
 * @return string
1693
 */
1694
function api_get_cidreq_params($courseCode, $sessionId = 0, $groupId = 0)
1695
{
1696
    $courseCode = !empty($courseCode) ? htmlspecialchars($courseCode) : '';
1697
    $sessionId = !empty($sessionId) ? (int) $sessionId : 0;
1698
    $groupId = !empty($groupId) ? (int) $groupId : 0;
1699
1700
    $url = 'cidReq='.$courseCode;
1701
    $url .= '&id_session='.$sessionId;
1702
    $url .= '&gidReq='.$groupId;
1703
1704
    return $url;
1705
}
1706
1707
/**
1708
 * Returns the current course url part including session, group, and gradebook params
1709
 *
1710
 * @param bool $addSessionId
1711
 * @param bool $addGroupId
1712
 * @param string $origin
1713
 *
1714
 * @return  string  Course & session references to add to a URL
1715
 *
1716
 */
1717
function api_get_cidreq($addSessionId = true, $addGroupId = true, $origin = '')
1718
{
1719
    $courseCode = api_get_course_id();
1720
    $url = empty($courseCode) ? '' : 'cidReq='.htmlspecialchars($courseCode);
1721
    $origin = empty($origin) ? api_get_origin() : Security::remove_XSS($origin);
1722
1723
    if ($addSessionId) {
1724
        if (!empty($url)) {
1725
            $url .= api_get_session_id() == 0 ? '&id_session=0' : '&id_session='.api_get_session_id();
1726
        }
1727
    }
1728
1729
    if ($addGroupId) {
1730
        if (!empty($url)) {
1731
            $url .= api_get_group_id() == 0 ? '&gidReq=0' : '&gidReq='.api_get_group_id();
1732
        }
1733
    }
1734
1735
    if (!empty($url)) {
1736
        $url .= '&gradebook='.intval(api_is_in_gradebook());
1737
        $url .= '&origin='.$origin;
1738
    }
1739
1740
    return $url;
1741
}
1742
1743
/**
1744
 * get gradebook in session
1745
 */
1746
function api_is_in_gradebook()
1747
{
1748
    return Session::read('in_gradebook', false);
1749
}
1750
1751
/**
1752
 * set gradebook session
1753
 */
1754
function api_set_in_gradebook()
1755
{
1756
    Session::write('in_gradebook', true);
1757
}
1758
1759
/**
1760
 * remove gradebook session
1761
 */
1762
function api_remove_in_gradebook()
1763
{
1764
    Session::erase('in_gradebook');
1765
}
1766
1767
/**
1768
 * Returns the current course info array see api_format_course_array()
1769
 * If the course_code is given, the returned array gives info about that
1770
 * particular course, if none given it gets the course info from the session.
1771
 *
1772
 * @param string $course_code
1773
 * @param bool $strict
1774
 *
1775
 * @return array
1776
 */
1777
function api_get_course_info($course_code = null, $strict = false)
1778
{
1779
    if (!empty($course_code)) {
1780
        $course_code = Database::escape_string($course_code);
1781
        $courseId = api_get_course_int_id($course_code);
1782
1783
        if (empty($courseId)) {
1784
            return array();
1785
        }
1786
1787
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1788
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1789
        $sql = "SELECT
1790
                    course.*,
1791
                    course_category.code faCode,
1792
                    course_category.name faName
1793
                FROM $course_table
1794
                LEFT JOIN $course_cat_table
1795
                ON course.category_code = course_category.code
1796
                WHERE course.id = $courseId";
1797
        $result = Database::query($sql);
1798
        $courseInfo = array();
1799
        if (Database::num_rows($result) > 0) {
1800
            $data = Database::fetch_array($result);
1801
            $courseInfo = api_format_course_array($data);
1802
        }
1803
1804
        return $courseInfo;
1805
    }
1806
1807
    global $_course;
1808
    if ($_course == '-1') {
1809
        $_course = array();
1810
    }
1811
1812
    return $_course;
1813
}
1814
1815
/**
1816
 * Returns the current course info array.
1817
1818
 * Now if the course_code is given, the returned array gives info about that
1819
 * particular course, not specially the current one.
1820
 * @param int $id Numeric ID of the course
1821
 * @return array The course info as an array formatted by api_format_course_array, including category.name
1822
 */
1823
function api_get_course_info_by_id($id = null)
1824
{
1825
    if (!empty($id)) {
1826
        $id = intval($id);
1827
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1828
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1829
        $sql = "SELECT
1830
                    course.*,
1831
                    course_category.code faCode,
1832
                    course_category.name faName
1833
                FROM $course_table
1834
                LEFT JOIN $course_cat_table
1835
                ON course.category_code =  course_category.code
1836
                WHERE course.id = $id";
1837
        $result = Database::query($sql);
1838
        $_course = array();
1839
        if (Database::num_rows($result) > 0) {
1840
            $course_data = Database::fetch_array($result);
1841
            $_course = api_format_course_array($course_data);
1842
        }
1843
        return $_course;
1844
    }
1845
1846
    global $_course;
1847
    if ($_course == '-1') $_course = array();
1848
    return $_course;
1849
}
1850
1851
/**
1852
 * Reformat the course array (output by api_get_course_info()) in order, mostly,
1853
 * to switch from 'code' to 'id' in the array. This is a legacy feature and is
1854
 * now possibly causing massive confusion as a new "id" field has been added to
1855
 * the course table in 1.9.0.
1856
 * @param $course_data
1857
 * @return array
1858
 * @todo eradicate the false "id"=code field of the $_course array and use the int id
1859
 */
1860
function api_format_course_array($course_data)
1861
{
1862
    if (empty($course_data)) {
1863
        return array();
1864
    }
1865
1866
    $_course = array();
1867
    $_course['id'] = $course_data['code'];
1868
    $_course['real_id'] = $course_data['id'];
1869
1870
    // Added
1871
    $_course['code'] = $course_data['code'];
1872
    $_course['name'] = $course_data['title'];
1873
    $_course['title'] = $course_data['title'];
1874
    $_course['official_code'] = $course_data['visual_code'];
1875
    $_course['visual_code'] = $course_data['visual_code'];
1876
    $_course['sysCode'] = $course_data['code'];
1877
    $_course['path'] = $course_data['directory']; // Use as key in path.
1878
    $_course['directory'] = $course_data['directory'];
1879
    $_course['creation_date'] = $course_data['creation_date'];
1880
    $_course['titular'] = $course_data['tutor_name'];
1881
    $_course['language'] = $course_data['course_language'];
1882
    $_course['extLink']['url'] = $course_data['department_url'];
1883
    $_course['extLink']['name'] = $course_data['department_name'];
1884
    $_course['categoryCode'] = $course_data['faCode'];
1885
    $_course['categoryName'] = $course_data['faName'];
1886
    $_course['visibility'] = $course_data['visibility'];
1887
    $_course['subscribe_allowed'] = $course_data['subscribe'];
1888
    $_course['subscribe'] = $course_data['subscribe'];
1889
    $_course['unsubscribe'] = $course_data['unsubscribe'];
1890
    $_course['course_language'] = $course_data['course_language'];
1891
    $_course['activate_legal'] = isset($course_data['activate_legal']) ? $course_data['activate_legal'] : false;
1892
    $_course['legal'] = $course_data['legal'];
1893
    $_course['show_score'] = $course_data['show_score']; //used in the work tool
1894
    $_course['department_name'] = $course_data['department_name'];
1895
    $_course['department_url'] = $course_data['department_url'];
1896
1897
    $courseSys = api_get_path(SYS_COURSE_PATH).$course_data['directory'];
1898
    $webCourseHome = api_get_path(WEB_COURSE_PATH).$course_data['directory'];
1899
1900
    // Course password
1901
    $_course['registration_code'] = !empty($course_data['registration_code']) ? sha1($course_data['registration_code']) : null;
1902
    $_course['disk_quota'] = $course_data['disk_quota'];
1903
    $_course['course_public_url'] = $webCourseHome.'/index.php';
1904
1905
    if (array_key_exists('add_teachers_to_sessions_courses', $course_data)) {
1906
        $_course['add_teachers_to_sessions_courses'] = $course_data['add_teachers_to_sessions_courses'];
1907
    }
1908
1909
    // Course image
1910
    $_course['course_image_source'] = '';
1911
    if (file_exists($courseSys.'/course-pic85x85.png')) {
1912
        $url_image = $webCourseHome.'/course-pic85x85.png';
1913
        $_course['course_image_source'] = $courseSys.'/course-pic85x85.png';
1914
    } else {
1915
        $url_image = Display::return_icon(
1916
            'course.png',
1917
            null,
1918
            null,
1919
            ICON_SIZE_BIG,
1920
            null,
1921
            true,
1922
            false
1923
        );
1924
    }
1925
    $_course['course_image'] = $url_image;
1926
1927
    // Course large image
1928
    $_course['course_image_large_source'] = '';
1929
    if (file_exists($courseSys.'/course-pic.png')) {
1930
        $url_image = $webCourseHome.'/course-pic.png';
1931
        $_course['course_image_large_source'] = $courseSys.'/course-pic.png';
1932
    } else {
1933
        $url_image = Display::returnIconPath('session_default.png');
1934
    }
1935
    $_course['course_image_large'] = $url_image;
1936
1937
    return $_course;
1938
}
1939
1940
/**
1941
 * Add a parameter to the existing URL. If this parameter already exists,
1942
 * just replace it with the new value
1943
 * @param   string  The URL
1944
 * @param   string  param=value string
1945
 * @param   boolean Whether to filter XSS or not
1946
 * @return  string  The URL with the added parameter
1947
 */
1948
function api_add_url_param($url, $param, $filter_xss = true) {
1949
    if (empty($param)) {
1950
        return $url;
1951
    }
1952
    if (strpos($url, '?') !== false) {
1953
        if ($param[0] != '&') {
1954
            $param = '&'.$param;
1955
        }
1956
        list (, $query_string) = explode('?', $url);
1957
        $param_list1 = explode('&', $param);
1958
        $param_list2 = explode('&', $query_string);
1959
        $param_list1_keys = $param_list1_vals = array();
1960
        foreach ($param_list1 as $key => $enreg) {
1961
            list ($param_list1_keys[$key], $param_list1_vals[$key]) = explode('=', $enreg);
1962
        }
1963
        $param_list1 = array ('keys' => $param_list1_keys, 'vals' => $param_list1_vals);
1964
        foreach ($param_list2 as $enreg) {
1965
            $enreg = explode('=', $enreg);
1966
            $key = array_search($enreg[0], $param_list1['keys']);
1967
            if (!is_null($key) && !is_bool($key)) {
1968
                $url = str_replace($enreg[0].'='.$enreg[1], $enreg[0].'='.$param_list1['vals'][$key], $url);
1969
                $param = str_replace('&'.$enreg[0].'='.$param_list1['vals'][$key], '', $param);
1970
            }
1971
        }
1972
        $url .= $param;
1973
    } else {
1974
        $url = $url.'?'.$param;
1975
    }
1976
    if ($filter_xss === true) {
1977
        $url = Security::remove_XSS(urldecode($url));
1978
    }
1979
    return $url;
1980
}
1981
1982
/**
1983
 * Returns a difficult to guess password.
1984
 * @param int $length the length of the password
1985
 * @return string the generated password
1986
 */
1987
function api_generate_password($length = 8)
1988
{
1989
    $characters = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
1990
    $numbers = '23456789';
1991
1992
    if ($length < 2) {
1993
        $length = 2;
1994
    }
1995
    $password = '';
1996
    for ($i = 0; $i < $length; $i ++) {
1997
        $password .= $characters[rand() % strlen($characters)];
1998
    }
1999
2000
    // At least 2 digits
2001
    for ($i = 0; $i < 2; $i ++) {
2002
        $password .= $numbers[rand() % strlen($numbers)];
2003
    }
2004
2005
    return $password;
2006
}
2007
2008
/**
2009
 * Checks a password to see wether it is OK to use.
2010
 * @param string $password
2011
 * @return boolean if the password is acceptable, false otherwise
2012
 * Notes about what a password "OK to use" is:
2013
 * 1. The password should be at least 5 characters long.
2014
 * 2. Only English letters (uppercase or lowercase, it doesn't matter) and digits are allowed.
2015
 * 3. The password should contain at least 3 letters.
2016
 * 4. It should contain at least 2 digits.
2017
 * 5. It should not contain 3 or more consequent (according to ASCII table) characters.
2018
 */
2019
function api_check_password($password) {
2020
    $password_length = api_strlen($password);
2021
    if ($password_length < 5) {
2022
        return false;
2023
    }
2024
    $password = api_strtolower($password);
2025
    $letters = 0;
2026
    $digits = 0;
2027
    $consequent_characters = 0;
2028
    $previous_character_code = 0;
2029
    for ($i = 0; $i < $password_length; $i ++) {
2030
        $current_character_code = api_ord(api_substr($password, $i, 1));
0 ignored issues
show
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...
2031
        if ($i && abs($current_character_code - $previous_character_code) <= 1) {
2032
            $consequent_characters ++;
2033
            if ($consequent_characters == 3) {
2034
                return false;
2035
            }
2036
        } else {
2037
            $consequent_characters = 1;
2038
        }
2039
        if ($current_character_code >= 97 && $current_character_code <= 122) {
2040
            $letters ++;
2041
        } elseif ($current_character_code >= 48 && $current_character_code <= 57) {
2042
            $digits ++;
2043
        } else {
2044
            return false;
2045
        }
2046
        $previous_character_code = $current_character_code;
2047
    }
2048
    return ($letters >= 3 && $digits >= 2);
2049
}
2050
2051
/**
2052
 * Clears the user ID from the session if it was the anonymous user. Generally
2053
 * used on out-of-tools pages to remove a user ID that could otherwise be used
2054
 * in the wrong context.
2055
 * This function is to be used in conjunction with the api_set_anonymous()
2056
 * function to simulate the user existence in case of an anonymous visit.
2057
 * @param bool      database check switch - passed to api_is_anonymous()
2058
 * @return bool     true if succesfully unregistered, false if not anonymous.
2059
 */
2060
function api_clear_anonymous($db_check = false)
2061
{
2062
    global $_user;
2063
    if (api_is_anonymous($_user['user_id'], $db_check)) {
2064
        unset($_user['user_id']);
2065
        Session::erase('_uid');
2066
        return true;
2067
    }
2068
    return false;
2069
}
2070
2071
/**
2072
 * Returns the status string corresponding to the status code
2073
 * @author Noel Dieschburg
2074
 * @param the int status code
2075
 */
2076
function get_status_from_code($status_code) {
2077
    switch ($status_code) {
2078
        case STUDENT:
2079
            return get_lang('Student', '');
2080
        case TEACHER:
2081
            return get_lang('Teacher', '');
2082
        case COURSEMANAGER:
2083
            return get_lang('Manager', '');
2084
        case SESSIONADMIN:
2085
            return get_lang('SessionsAdmin', '');
2086
        case DRH:
2087
            return get_lang('Drh', '');
2088
    }
2089
}
2090
2091
/**
2092
 * Sets the current user as anonymous if it hasn't been identified yet. This
2093
 * function should be used inside a tool only. The function api_clear_anonymous()
2094
 * acts in the opposite direction by clearing the anonymous user's data every
2095
 * time we get on a course homepage or on a neutral page (index, admin, my space)
2096
 * @return bool     true if set user as anonymous, false if user was already logged in or anonymous id could not be found
2097
 */
2098
function api_set_anonymous() {
2099
    global $_user;
2100
2101
    if (!empty($_user['user_id'])) {
2102
        return false;
2103
    }
2104
    $user_id = api_get_anonymous_id();
2105
    if ($user_id == 0) {
2106
        return false;
2107
    }
2108
    Session::erase('_user');
2109
    $_user['user_id'] = $user_id;
2110
    $_user['is_anonymous'] = true;
2111
    $GLOBALS['_user'] = $_user;
2112
    Session::write('_user', $_user);
2113
    return true;
2114
}
2115
2116
/* CONFIGURATION SETTINGS */
2117
2118
/**
2119
 * Gets the current Chamilo (not PHP/cookie) session ID
2120
 * @return  int     O if no active session, the session ID otherwise
2121
 */
2122
function api_get_session_id()
2123
{
2124
    return Session::read('id_session', 0);
2125
}
2126
2127
/**
2128
 * Gets the current Chamilo (not social network) group ID
2129
 * @return  int     O if no active session, the session ID otherwise
2130
 */
2131
function api_get_group_id()
2132
{
2133
    return Session::read('_gid', 0);
2134
}
2135
2136
/**
2137
 * Gets the current or given session name
2138
 * @param   int     Session ID (optional)
2139
 * @return  string  The session name, or null if unfound
2140
 */
2141
function api_get_session_name($session_id = 0) {
2142
    if (empty($session_id)) {
2143
        $session_id = api_get_session_id();
2144
        if (empty($session_id)) { return null; }
2145
    }
2146
    $t = Database::get_main_table(TABLE_MAIN_SESSION);
2147
    $s = "SELECT name FROM $t WHERE id = ".(int)$session_id;
2148
    $r = Database::query($s);
2149
    $c = Database::num_rows($r);
2150
    if ($c > 0) {
2151
        //technically, there can be only one, but anyway we take the first
2152
        $rec = Database::fetch_array($r);
2153
        return $rec['name'];
2154
    }
2155
    return null;
2156
}
2157
2158
/**
2159
 * Gets the session info by id
2160
 * @param int       Session ID
2161
 * @return array    information of the session
2162
 */
2163
function api_get_session_info($session_id)
2164
{
2165
    return SessionManager::fetch($session_id);
2166
}
2167
2168
/**
2169
 * Gets the session visibility by session id
2170
 * @param int $session_id
2171
 * @param int $courseId
2172
 * @param bool $ignore_visibility_for_admins
2173
 * @return int
2174
 *  0 = session still available,
2175
 *  SESSION_VISIBLE_READ_ONLY = 1,
2176
 *  SESSION_VISIBLE = 2,
2177
 *  SESSION_INVISIBLE = 3
2178
 */
2179
function api_get_session_visibility(
2180
    $session_id,
2181
    $courseId = null,
2182
    $ignore_visibility_for_admins = true
2183
) {
2184
    // Means that the session is still available.
2185
    $visibility = 0;
2186
2187
    if (api_is_platform_admin()) {
2188
        if ($ignore_visibility_for_admins) {
2189
            return SESSION_AVAILABLE;
2190
        }
2191
    }
2192
2193
    $now = time();
2194
    if (!empty($session_id)) {
2195
        $session_id = intval($session_id);
2196
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2197
2198
        $sql = "SELECT * FROM $tbl_session
2199
                WHERE id = $session_id ";
2200
2201
        $result = Database::query($sql);
2202
2203
        if (Database::num_rows($result) > 0) {
2204
            $row = Database::fetch_array($result, 'ASSOC');
2205
            $visibility = $original_visibility = $row['visibility'];
2206
2207
            // I don't care the session visibility.
2208
            if (empty($row['access_start_date']) && empty($row['access_end_date'])) {
2209
                // Session duration per student.
2210
                if (isset($row['duration']) && !empty($row['duration'])) {
2211
                    $duration = $row['duration'] * 24 * 60 * 60;
2212
2213
                    $courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser(
2214
                        $session_id,
2215
                        api_get_user_id()
2216
                    );
2217
2218
                    // If there is a session duration but there is no previous
2219
                    // access by the user, then the session is still available
2220
                    if (count($courseAccess) == 0) {
2221
                        return SESSION_AVAILABLE;
2222
                    }
2223
2224
                    $currentTime = time();
2225
                    $firstAccess = 0;
2226
                    if (isset($courseAccess['login_course_date'])) {
2227
                        $firstAccess = api_strtotime(
2228
                            $courseAccess['login_course_date'],
2229
                            'UTC'
2230
                        );
2231
                    }
2232
                    $userDurationData = SessionManager::getUserSession(
2233
                        api_get_user_id(),
2234
                        $session_id
2235
                    );
2236
                    $userDuration = 0;
2237
                    if (isset($userDurationData['duration'])) {
2238
                        $userDuration = intval($userDurationData['duration']) * 24 * 60 * 60;
2239
                    }
2240
2241
                    $totalDuration = $firstAccess + $duration + $userDuration;
2242
                    if ($totalDuration > $currentTime) {
2243
                        return SESSION_AVAILABLE;
2244
                    } else {
2245
                        return SESSION_INVISIBLE;
2246
                    }
2247
                }
2248
2249
                return SESSION_AVAILABLE;
2250
            } else {
2251
                // If start date was set.
2252
                if (!empty($row['access_start_date'])) {
2253
                    if ($now > api_strtotime($row['access_start_date'], 'UTC')) {
2254
                        $visibility = SESSION_AVAILABLE;
2255
                    } else {
2256
                        $visibility = SESSION_INVISIBLE;
2257
                    }
2258
                }
2259
2260
                // If the end date was set.
2261 View Code Duplication
                if (!empty($row['access_end_date'])) {
2262
                    // Only if date_start said that it was ok
2263
                    if ($visibility === SESSION_AVAILABLE) {
2264
                        if ($now < api_strtotime($row['access_end_date'], 'UTC')) {
2265
                            // Date still available
2266
                            $visibility = SESSION_AVAILABLE;
2267
                        } else {
2268
                            // Session ends
2269
                            $visibility = $row['visibility'];
2270
                        }
2271
                    }
2272
                }
2273
            }
2274
2275
            /* If I'm a coach the visibility can change in my favor depending in
2276
             the coach dates */
2277
            $isCoach = api_is_coach($session_id, $courseId);
2278
2279
            if ($isCoach) {
2280
                // Test end date.
2281 View Code Duplication
                if (!empty($row['coach_access_end_date'])) {
2282
                    $endDateCoach = api_strtotime($row['coach_access_end_date'], 'UTC');
2283
2284
                    if ($endDateCoach >= $now) {
2285
                        $visibility = SESSION_AVAILABLE;
2286
                    } else {
2287
                        $visibility = SESSION_INVISIBLE;
2288
                    }
2289
                }
2290
2291
                // Test start date.
2292 View Code Duplication
                if (!empty($row['coach_access_start_date'])) {
2293
                    $start = api_strtotime($row['coach_access_start_date'], 'UTC');
2294
                    if ($start < $now) {
2295
                        $visibility = SESSION_AVAILABLE;
2296
                    } else {
2297
                        $visibility = SESSION_INVISIBLE;
2298
                    }
2299
                }
2300
            }
2301
        } else {
2302
            $visibility = SESSION_INVISIBLE;
2303
        }
2304
    }
2305
    return $visibility;
2306
}
2307
2308
/**
2309
 * This function returns a (star) session icon if the session is not null and
2310
 * the user is not a student
2311
 * @param int   $session_id
2312
 * @param int   $status_id User status id - if 5 (student), will return empty
2313
 * @return string   Session icon
2314
 */
2315
function api_get_session_image($session_id, $status_id)
2316
{
2317
    $session_id = (int)$session_id;
2318
    $session_img = '';
2319
    if ((int)$status_id != 5) { //check whether is not a student
2320
        if ($session_id > 0) {
2321
            $session_img = "&nbsp;&nbsp;".Display::return_icon(
2322
                'star.png',
2323
                get_lang('SessionSpecificResource'),
2324
                array('align' => 'absmiddle'),
2325
                ICON_SIZE_SMALL
2326
            );
2327
        }
2328
    }
2329
    return $session_img;
2330
}
2331
2332
/**
2333
 * This function add an additional condition according to the session of the course
2334
 * @param int       $session_id session id
2335
 * @param bool      $and optional, true if more than one condition false if the only condition in the query
2336
 * @param bool      $with_base_content optional, true to accept content with session=0 as well, false for strict session condition
2337
 * @return string   condition of the session
2338
 */
2339
function api_get_session_condition(
2340
    $session_id,
2341
    $and = true,
2342
    $with_base_content = false,
2343
    $session_field = "session_id"
2344
) {
2345
    $session_id = intval($session_id);
2346
2347
    if (empty($session_field)) {
2348
        $session_field = "session_id";
2349
    }
2350
    // Condition to show resources by session
2351
    $condition_add = $and ? " AND " : " WHERE ";
2352
2353
    if ($with_base_content) {
2354
        $condition_session = $condition_add." ( $session_field = $session_id OR $session_field = 0 OR $session_field IS NULL) ";
2355
    } else {
2356
        if (empty($session_id)) {
2357
            $condition_session = $condition_add." ($session_field = $session_id OR $session_field IS NULL)";
2358
        } else {
2359
            $condition_session = $condition_add." $session_field = $session_id ";
2360
        }
2361
    }
2362
    return $condition_session;
2363
}
2364
2365
/**
2366
 * Returns the value of a setting from the web-adjustable admin config settings.
2367
 *
2368
 * WARNING true/false are stored as string, so when comparing you need to check e.g.
2369
 * if (api_get_setting('show_navigation_menu') == 'true') //CORRECT
2370
 * instead of
2371
 * if (api_get_setting('show_navigation_menu') == true) //INCORRECT
2372
 * @param string    $variable The variable name
2373
 * @param string    $key The subkey (sub-variable) if any. Defaults to NULL
2374
 * @return string
2375
 * @author René Haentjens
2376
 * @author Bart Mollet
2377
 */
2378
function api_get_setting($variable, $key = null)
2379
{
2380
    global $_setting;
2381 View Code Duplication
    if ($variable == 'header_extra_content') {
2382
        $filename = api_get_home_path().'header_extra_content.txt';
2383
        if (file_exists($filename)) {
2384
            $value = file_get_contents($filename);
2385
            return $value;
2386
        } else {
2387
            return '';
2388
        }
2389
    }
2390 View Code Duplication
    if ($variable == 'footer_extra_content') {
2391
        $filename = api_get_home_path().'footer_extra_content.txt';
2392
        if (file_exists($filename)) {
2393
            $value = file_get_contents($filename);
2394
            return $value;
2395
        } else {
2396
            return '';
2397
        }
2398
    }
2399
    $value = null;
2400
    if (is_null($key)) {
2401
        $value = ((isset($_setting[$variable]) && $_setting[$variable] != '') ? $_setting[$variable] : null);
2402
    } else {
2403
        if (isset($_setting[$variable][$key])) {
2404
            $value = $_setting[$variable][$key];
2405
        }
2406
    }
2407
2408
    return $value;
2409
}
2410
2411
/**
2412
 * @param string $plugin
2413
 * @param string $variable
2414
 * @return string
2415
 */
2416
function api_get_plugin_setting($plugin, $variable)
2417
{
2418
    $variableName = $plugin.'_'.$variable;
2419
    $result = api_get_setting($variableName);
2420
2421
    if (isset($result[$plugin])) {
2422
        return $result[$plugin];
2423
    }
2424
2425
    return null;
2426
}
2427
2428
/**
2429
 * Returns the value of a setting from the web-adjustable admin config settings.
2430
 **/
2431
function api_get_settings_params($params) {
2432
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2433
    $result = Database::select('*', $table, array('where' => $params));
2434
    return $result;
2435
}
2436
2437
function api_get_settings_params_simple($params) {
2438
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2439
    $result = Database::select('*', $table, array('where' => $params), 'one');
2440
    return $result;
2441
}
2442
2443
/**
2444
 * Returns the value of a setting from the web-adjustable admin config settings.
2445
 **/
2446
function api_delete_settings_params($params) {
2447
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2448
    $result = Database::delete($table, $params);
2449
    return $result;
2450
}
2451
2452
/**
2453
 * Returns an escaped version of $_SERVER['PHP_SELF'] to avoid XSS injection
2454
 * @return string   Escaped version of $_SERVER['PHP_SELF']
2455
 */
2456
function api_get_self() {
2457
    return htmlentities($_SERVER['PHP_SELF']);
2458
}
2459
2460
/* USER PERMISSIONS */
2461
2462
/**
2463
 * Checks whether current user is a platform administrator
2464
 * @param boolean $allowSessionAdmins Whether session admins should be considered admins or not
2465
 * @param boolean $allowDrh Whether HR directors should be considered admins or not
2466
 * @return boolean True if the user has platform admin rights,
2467
 * false otherwise.
2468
 * @see usermanager::is_admin(user_id) for a user-id specific function
2469
 */
2470
function api_is_platform_admin($allowSessionAdmins = false, $allowDrh = false)
2471
{
2472
    $isAdmin = Session::read('is_platformAdmin');
2473
    if ($isAdmin) {
2474
        return true;
2475
    }
2476
    $user = api_get_user_info();
2477
    return
2478
        isset($user['status']) &&
2479
        (
2480
            ($allowSessionAdmins && $user['status'] == SESSIONADMIN) ||
2481
            ($allowDrh && $user['status'] == DRH)
2482
        );
2483
}
2484
2485
/**
2486
 * Checks whether the user given as user id is in the admin table.
2487
 * @param int $user_id If none provided, will use current user
2488
 * @param int $url URL ID. If provided, also check if the user is active on given URL
2489
 * @return bool True if the user is admin, false otherwise
2490
 */
2491
function api_is_platform_admin_by_id($user_id = null, $url = null)
2492
{
2493
    $user_id = intval($user_id);
2494
    if (empty($user_id)) {
2495
        $user_id = api_get_user_id();
2496
    }
2497
    $admin_table = Database::get_main_table(TABLE_MAIN_ADMIN);
2498
    $sql = "SELECT * FROM $admin_table WHERE user_id = $user_id";
2499
    $res = Database::query($sql);
2500
    $is_admin = Database::num_rows($res) === 1;
2501
    if (!$is_admin || !isset($url)) {
2502
        return $is_admin;
2503
    }
2504
    // We get here only if $url is set
2505
    $url = intval($url);
2506
    $url_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
2507
    $sql = "SELECT * FROM $url_user_table
2508
            WHERE access_url_id = $url AND user_id = $user_id";
2509
    $res = Database::query($sql);
2510
    $is_on_url = Database::num_rows($res) === 1;
2511
2512
    return $is_on_url;
2513
}
2514
2515
/**
2516
 * Returns the user's numeric status ID from the users table
2517
 * @param int $user_id If none provided, will use current user
2518
 * @return int User's status (1 for teacher, 5 for student, etc)
2519
 */
2520 View Code Duplication
function api_get_user_status($user_id = null)
2521
{
2522
    $user_id = intval($user_id);
2523
    if (empty($user_id)) {
2524
        $user_id = api_get_user_id();
2525
    }
2526
    $table = Database::get_main_table(TABLE_MAIN_USER);
2527
    $sql = "SELECT status FROM $table WHERE user_id = $user_id ";
2528
    $result = Database::query($sql);
2529
    $status = null;
2530
    if (Database::num_rows($result)) {
2531
        $row = Database::fetch_array($result);
2532
        $status = $row['status'];
2533
    }
2534
    return $status;
2535
}
2536
2537
/**
2538
 * Checks whether current user is allowed to create courses
2539
 * @return boolean True if the user has course creation rights,
2540
 * false otherwise.
2541
 */
2542
function api_is_allowed_to_create_course()
2543
{
2544
    if (api_is_platform_admin()) {
2545
        return true;
2546
    }
2547
2548
    // Teachers can only create courses
2549
    if (api_is_teacher()) {
2550
        if (api_get_setting('allow_users_to_create_courses') === 'true') {
2551
            return true;
2552
        } else {
2553
            return false;
2554
        }
2555
    }
2556
2557
    return Session::read('is_allowedCreateCourse');
2558
}
2559
2560
/**
2561
 * Checks whether the current user is a course administrator
2562
 * @return boolean True if current user is a course administrator
2563
 */
2564
function api_is_course_admin() {
2565
    if (api_is_platform_admin()) {
2566
        return true;
2567
    }
2568
    return Session::read('is_courseAdmin');
2569
}
2570
2571
/**
2572
 * Checks whether the current user is a course coach
2573
 * @return bool     True if current user is a course coach
2574
 */
2575
function api_is_course_coach() {
2576
    return Session::read('is_courseCoach');
2577
}
2578
2579
/**
2580
 * Checks whether the current user is a course tutor
2581
 * @return bool     True if current user is a course tutor
2582
 */
2583
function api_is_course_tutor() {
2584
    return Session::read('is_courseTutor');
2585
}
2586
2587
/**
2588
 * @param int $user_id
2589
 * @param int $courseId
2590
 * @param int $session_id
2591
 * @return bool
2592
 */
2593
function api_is_course_session_coach($user_id, $courseId, $session_id)
2594
{
2595
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2596
    $session_rel_course_rel_user_table  = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2597
2598
    $user_id = intval($user_id);
2599
    $session_id = intval($session_id);
2600
    $courseId = intval($courseId);
2601
2602
    $sql = "SELECT DISTINCT session.id
2603
            FROM $session_table
2604
            INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2605
            ON session.id = session_rc_ru.session_id
2606
            WHERE
2607
                session_rc_ru.user_id = '".$user_id."'  AND
2608
                session_rc_ru.c_id = '$courseId' AND
2609
                session_rc_ru.status = 2 AND
2610
                session_rc_ru.session_id = '$session_id'";
2611
    $result = Database::query($sql);
2612
2613
    return Database::num_rows($result) > 0;
2614
}
2615
2616
/**
2617
 * Checks whether the current user is a course or session coach
2618
 * @param int $session_id
2619
 * @param int $courseId
2620
 * @param bool  Check whether we are in student view and, if we are, return false
2621
 * @return boolean True if current user is a course or session coach
2622
 */
2623
function api_is_coach($session_id = 0, $courseId = null, $check_student_view = true)
2624
{
2625
    $userId = api_get_user_id();
2626
2627
    if (!empty($session_id)) {
2628
        $session_id = intval($session_id);
2629
    } else {
2630
        $session_id = api_get_session_id();
2631
    }
2632
2633
    // The student preview was on
2634 View Code Duplication
    if ($check_student_view &&
2635
        isset($_SESSION['studentview']) && $_SESSION['studentview'] == "studentview"
2636
    ) {
2637
        return false;
2638
    }
2639
2640
    if (!empty($courseId)) {
2641
        $courseId = intval($courseId);
2642
    } else {
2643
        $courseId = api_get_course_int_id();
2644
    }
2645
2646
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2647
    $session_rel_course_rel_user_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2648
    $sessionIsCoach = null;
2649
2650
    if (!empty($courseId)) {
2651
        $sql = "SELECT DISTINCT s.id, name, access_start_date, access_end_date
2652
                FROM $session_table s
2653
                INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2654
                ON session_rc_ru.session_id = s.id AND session_rc_ru.user_id = '".$userId."'
2655
                WHERE
2656
                    session_rc_ru.c_id = '$courseId' AND
2657
                    session_rc_ru.status = 2 AND
2658
                    session_rc_ru.session_id = '$session_id'";
2659
        $result = Database::query($sql);
2660
        $sessionIsCoach = Database::store_result($result);
2661
    }
2662
2663
    if (!empty($session_id)) {
2664
        $sql = "SELECT DISTINCT id, name, access_start_date, access_end_date
2665
                FROM $session_table
2666
                WHERE session.id_coach = $userId AND id = $session_id
2667
                ORDER BY access_start_date, access_end_date, name";
2668
        $result = Database::query($sql);
2669
        if (!empty($sessionIsCoach)) {
2670
            $sessionIsCoach = array_merge($sessionIsCoach , Database::store_result($result));
2671
        } else {
2672
            $sessionIsCoach = Database::store_result($result);
2673
        }
2674
    }
2675
2676
    return (count($sessionIsCoach) > 0);
2677
}
2678
2679
/**
2680
 * Checks whether the current user is a session administrator
2681
 * @return boolean True if current user is a course administrator
2682
 */
2683
function api_is_session_admin()
2684
{
2685
    $user = api_get_user_info();
2686
    return isset($user['status']) && $user['status'] == SESSIONADMIN;
2687
}
2688
2689
/**
2690
 * Checks whether the current user is a human resources manager
2691
 * @return boolean True if current user is a human resources manager
2692
 */
2693
function api_is_drh()
2694
{
2695
    $user = api_get_user_info();
2696
    return isset($user['status']) && $user['status'] == DRH;
2697
}
2698
2699
/**
2700
 * Checks whether the current user is a student
2701
 * @return boolean True if current user is a human resources manager
2702
 */
2703
function api_is_student()
2704
{
2705
    $user = api_get_user_info();
2706
    return isset($user['status']) && $user['status'] == STUDENT;
2707
}
2708
2709
/**
2710
 * Checks whether the current user has the status 'teacher'
2711
 * @return boolean True if current user is a human resources manager
2712
 */
2713
function api_is_teacher()
2714
{
2715
    $user = api_get_user_info();
2716
    return isset($user['status']) && $user['status'] == COURSEMANAGER;
2717
}
2718
2719
/**
2720
 * Checks whether the current user is a invited user
2721
 * @return boolean
2722
 */
2723
function api_is_invitee()
2724
{
2725
    $user = api_get_user_info();
2726
2727
    return isset($user['status']) && $user['status'] == INVITEE;
2728
}
2729
2730
/**
2731
 * This function checks whether a session is assigned into a category
2732
 * @param int       - session id
2733
 * @param string    - category name
2734
 * @return bool     - true if is found, otherwise false
2735
 */
2736
function api_is_session_in_category($session_id, $category_name)
2737
{
2738
    $session_id = intval($session_id);
2739
    $category_name = Database::escape_string($category_name);
2740
2741
    $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2742
    $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
2743
2744
    $sql = "SELECT 1
2745
            FROM $tbl_session
2746
            WHERE $session_id IN (
2747
                SELECT s.id FROM $tbl_session s, $tbl_session_category sc
2748
                WHERE
2749
                  s.session_category_id = sc.id AND
2750
                  sc.name LIKE '%$category_name'
2751
            )";
2752
    $rs = Database::query($sql);
2753
2754
    if (Database::num_rows($rs) > 0) {
2755
        return true;
2756
    } else {
2757
        return false;
2758
    }
2759
}
2760
2761
/**
2762
 * Displays the title of a tool.
2763
 * Normal use: parameter is a string:
2764
 * api_display_tool_title("My Tool")
2765
 *
2766
 * Optionally, there can be a subtitle below
2767
 * the normal title, and / or a supra title above the normal title.
2768
 *
2769
 * e.g. supra title:
2770
 * group
2771
 * GROUP PROPERTIES
2772
 *
2773
 * e.g. subtitle:
2774
 * AGENDA
2775
 * calender & events tool
2776
 *
2777
 * @author Hugues Peeters <[email protected]>
2778
 * @param  mixed $title_element - it could either be a string or an array
2779
 *                               containing 'supraTitle', 'mainTitle',
2780
 *                               'subTitle'
2781
 * @return void
2782
 */
2783
function api_display_tool_title($title_element) {
2784
    if (is_string($title_element)) {
2785
        $tit = $title_element;
2786
        unset ($title_element);
2787
        $title_element['mainTitle'] = $tit;
2788
    }
2789
    echo '<h3>';
2790
    if (!empty($title_element['supraTitle'])) {
2791
        echo '<small>'.$title_element['supraTitle'].'</small><br />';
2792
    }
2793
    if (!empty($title_element['mainTitle'])) {
2794
        echo $title_element['mainTitle'];
2795
    }
2796
    if (!empty($title_element['subTitle'])) {
2797
        echo '<br /><small>'.$title_element['subTitle'].'</small>';
2798
    }
2799
    echo '</h3>';
2800
}
2801
2802
/**
2803
 * Displays options for switching between student view and course manager view
2804
 *
2805
 * Changes in version 1.2 (Patrick Cool)
2806
 * Student view switch now behaves as a real switch. It maintains its current state until the state
2807
 * is changed explicitly
2808
 *
2809
 * Changes in version 1.1 (Patrick Cool)
2810
 * student view now works correctly in subfolders of the document tool
2811
 * student view works correctly in the new links tool
2812
 *
2813
 * Example code for using this in your tools:
2814
 * //if ($is_courseAdmin && api_get_setting('student_view_enabled') == 'true') {
2815
 * //   display_tool_view_option($isStudentView);
2816
 * //}
2817
 * //and in later sections, use api_is_allowed_to_edit()
2818
 *
2819
 * @author Roan Embrechts
2820
 * @author Patrick Cool
2821
 * @author Julio Montoya, changes added in Chamilo
2822
 * @version 1.2
2823
 * @todo rewrite code so it is easier to understand
2824
 */
2825
function api_display_tool_view_option() {
2826
    if (api_get_setting('student_view_enabled') != 'true') {
2827
        return '';
2828
    }
2829
2830
    $sourceurl = '';
2831
    $is_framed = false;
2832
    // Exceptions apply for all multi-frames pages
2833
    if (strpos($_SERVER['REQUEST_URI'], 'chat/chat_banner.php') !== false) {
2834
        // The chat is a multiframe bit that doesn't work too well with the student_view, so do not show the link
2835
        return '';
2836
    }
2837
2838
    // Uncomment to remove student view link from document view page
2839
    if (strpos($_SERVER['REQUEST_URI'], 'lp/lp_header.php') !== false) {
2840
        if (empty($_GET['lp_id'])) {
2841
            return '';
2842
        }
2843
        $sourceurl = substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], '?'));
2844
        $sourceurl = str_replace('lp/lp_header.php', 'lp/lp_controller.php?'.api_get_cidreq().'&action=view&lp_id='.intval($_GET['lp_id']).'&isStudentView='.($_SESSION['studentview']=='studentview' ? 'false' : 'true'), $sourceurl);
2845
        //showinframes doesn't handle student view anyway...
2846
        //return '';
2847
        $is_framed = true;
2848
    }
2849
2850
    // Check whether the $_SERVER['REQUEST_URI'] contains already url parameters (thus a questionmark)
2851
    if (!$is_framed) {
2852
        if (strpos($_SERVER['REQUEST_URI'], '?') === false) {
2853
            $sourceurl = api_get_self().'?'.api_get_cidreq();
2854
        } else {
2855
            $sourceurl = $_SERVER['REQUEST_URI'];
2856
        }
2857
    }
2858
2859
    $output_string = '';
2860
    if (!empty($_SESSION['studentview'])) {
2861
        if ($_SESSION['studentview'] == 'studentview') {
2862
            // We have to remove the isStudentView=true from the $sourceurl
2863
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
2864
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
2865
            $output_string .= '<a class="btn btn-primary btn-sm" href="'.$sourceurl.'&isStudentView=false" target="_self">'.Display::returnFontAwesomeIcon('eye').' '.get_lang('SwitchToTeacherView').'</a>';
2866
        } elseif ($_SESSION['studentview'] == 'teacherview') {
2867
            // Switching to teacherview
2868
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
2869
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
2870
            $output_string .= '<a class="btn btn-default btn-sm" href="'.$sourceurl.'&isStudentView=true" target="_self">'.Display::returnFontAwesomeIcon('eye').' '.get_lang('SwitchToStudentView').'</a>';
2871
        }
2872
    } else {
2873
        $output_string .= '<a class="btn btn-default btn-sm" href="'.$sourceurl.'&isStudentView=true" target="_self">'.Display::returnFontAwesomeIcon('eye').' '.get_lang('SwitchToStudentView').'</a>';
2874
    }
2875
    $html = Display::tag('div', $output_string, array('class'=>'view-options'));
2876
    return $html;
2877
}
2878
2879
// TODO: This is for the permission section.
2880
/**
2881
 * Function that removes the need to directly use is_courseAdmin global in
2882
 * tool scripts. It returns true or false depending on the user's rights in
2883
 * this particular course.
2884
 * Optionally checking for tutor and coach roles here allows us to use the
2885
 * student_view feature altogether with these roles as well.
2886
 * @param bool  Whether to check if the user has the tutor role
2887
 * @param bool  Whether to check if the user has the coach role
2888
 * @param bool  Whether to check if the user has the session coach role
2889
 * @param bool  check the student view or not
2890
 *
2891
 * @author Roan Embrechts
2892
 * @author Patrick Cool
2893
 * @author Julio Montoya
2894
 * @version 1.1, February 2004
2895
 * @return boolean true: the user has the rights to edit, false: he does not
2896
 */
2897
2898
function api_is_allowed_to_edit(
2899
    $tutor = false,
2900
    $coach = false,
2901
    $session_coach = false,
2902
    $check_student_view = true
2903
) {
2904
    $my_session_id = api_get_session_id();
2905
    $is_allowed_coach_to_edit = api_is_coach(null, null, $check_student_view);
2906
    $session_visibility = api_get_session_visibility($my_session_id);
2907
2908
    // Admins can edit anything.
2909
    if (api_is_platform_admin(false)) {
2910
        //The student preview was on
2911 View Code Duplication
        if ($check_student_view &&
2912
            isset($_SESSION['studentview']) &&
2913
            $_SESSION['studentview'] == "studentview"
2914
        ) {
2915
            return false;
2916
        } else {
2917
            return true;
2918
        }
2919
    }
2920
2921
    $is_courseAdmin = api_is_course_admin();
2922
2923
    if (!$is_courseAdmin && $tutor) {
2924
        // If we also want to check if the user is a tutor...
2925
        $is_courseAdmin = $is_courseAdmin || api_is_course_tutor();
2926
    }
2927
2928
    if (!$is_courseAdmin && $coach) {
2929
        // If we also want to check if the user is a coach...';
2930
        // Check if session visibility is read only for coaches.
2931
        if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
2932
            $is_allowed_coach_to_edit = false;
2933
        }
2934
2935
        if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
2936
            // Check if coach is allowed to edit a course.
2937
            $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
2938
        }
2939
    }
2940
2941
    if (!$is_courseAdmin && $session_coach) {
2942
        $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
2943
    }
2944
2945
    // Check if the student_view is enabled, and if so, if it is activated.
2946
    if (api_get_setting('student_view_enabled') == 'true') {
2947
        if (!empty($my_session_id)) {
2948
            // Check if session visibility is read only for coaches.
2949
            if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
2950
                $is_allowed_coach_to_edit = false;
2951
            }
2952
2953
            if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
2954
                // Check if coach is allowed to edit a course.
2955
                $is_allowed = $is_allowed_coach_to_edit;
2956
            } else {
2957
                $is_allowed = false;
2958
            }
2959
            if ($check_student_view) {
2960
                $is_allowed = $is_allowed && $_SESSION['studentview'] != 'studentview';
2961
            }
2962
        } else {
2963
            if ($check_student_view) {
2964
                $is_allowed = $is_courseAdmin && $_SESSION['studentview'] != 'studentview';
2965
            } else {
2966
                $is_allowed = $is_courseAdmin;
2967
            }
2968
        }
2969
2970
        return $is_allowed;
2971
    } else {
2972
2973
        return $is_courseAdmin;
2974
    }
2975
}
2976
2977
/**
2978
 * Returns true if user is a course coach of at least one course in session
2979
 * @param int $sessionId
2980
 * @return bool
2981
 */
2982
function api_is_coach_of_course_in_session($sessionId)
2983
{
2984
    if (api_is_platform_admin()) {
2985
        return true;
2986
    }
2987
2988
    $userId = api_get_user_id();
2989
    $courseList = UserManager::get_courses_list_by_session(
2990
        $userId,
2991
        $sessionId
2992
    );
2993
2994
    // Session visibility.
2995
    $visibility = api_get_session_visibility(
2996
        $sessionId,
2997
        null,
2998
        false
2999
    );
3000
3001 View Code Duplication
    if ($visibility != SESSION_VISIBLE && !empty($courseList)) {
3002
        // Course Coach session visibility.
3003
        $blockedCourseCount = 0;
3004
        $closedVisibilityList = array(
3005
            COURSE_VISIBILITY_CLOSED,
3006
            COURSE_VISIBILITY_HIDDEN
3007
        );
3008
3009
        foreach ($courseList as $course) {
3010
            // Checking session visibility
3011
            $sessionCourseVisibility = api_get_session_visibility(
3012
                $sessionId,
3013
                $course['real_id'],
3014
                $ignore_visibility_for_admins
0 ignored issues
show
Bug introduced by
The variable $ignore_visibility_for_admins does not exist. Did you mean $visibility?

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

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

Loading history...
3015
            );
3016
3017
            $courseIsVisible = !in_array(
3018
                $course['visibility'],
3019
                $closedVisibilityList
3020
            );
3021
            if ($courseIsVisible === false || $sessionCourseVisibility == SESSION_INVISIBLE) {
3022
                $blockedCourseCount++;
3023
            }
3024
        }
3025
3026
        // If all courses are blocked then no show in the list.
3027
        if ($blockedCourseCount === count($courseList)) {
3028
            $visibility = SESSION_INVISIBLE;
3029
        } else {
3030
            $visibility = SESSION_VISIBLE;
3031
        }
3032
    }
3033
3034
    switch ($visibility) {
3035
        case SESSION_VISIBLE_READ_ONLY:
3036
        case SESSION_VISIBLE:
3037
        case SESSION_AVAILABLE:
3038
            return true;
3039
            break;
3040
        case SESSION_INVISIBLE:
3041
            return false;
3042
    }
3043
3044
    return false;
3045
}
3046
3047
/**
3048
* Checks if a student can edit contents in a session depending
3049
* on the session visibility
3050
* @param bool $tutor  Whether to check if the user has the tutor role
3051
* @param bool  $coach Whether to check if the user has the coach role
3052
* @return boolean true: the user has the rights to edit, false: he does not
3053
*/
3054
function api_is_allowed_to_session_edit($tutor = false, $coach = false)
3055
{
3056
    if (api_is_allowed_to_edit($tutor, $coach)) {
3057
        // If I'm a teacher, I will return true in order to not affect the normal behaviour of Chamilo tools.
3058
        return true;
3059
    } else {
3060
        $sessionId = api_get_session_id();
3061
3062
        if ($sessionId == 0) {
3063
            // I'm not in a session so i will return true to not affect the normal behaviour of Chamilo tools.
3064
            return true;
3065
        } else {
3066
            // I'm in a session and I'm a student
3067
3068
            // Get the session visibility
3069
            $session_visibility = api_get_session_visibility($sessionId);
3070
            // if 5 the session is still available
3071
3072
            //@todo We could load the session_rel_course_rel_user permission to increase the level of detail.
3073
            //echo api_get_user_id();
3074
            //echo api_get_course_id();
3075
3076
            switch ($session_visibility) {
3077
                case SESSION_VISIBLE_READ_ONLY: // 1
3078
                    return false;
3079
                case SESSION_VISIBLE:           // 2
3080
                    return true;
3081
                case SESSION_INVISIBLE:         // 3
3082
                    return false;
3083
                case SESSION_AVAILABLE:         //5
3084
                    return true;
3085
            }
3086
        }
3087
    }
3088
}
3089
3090
/**
3091
* Checks whether the user is allowed in a specific tool for a specific action
3092
* @param string $tool the tool we are checking if the user has a certain permission
3093
* @param string $action the action we are checking (add, edit, delete, move, visibility)
3094
* @author Patrick Cool <[email protected]>, Ghent University
3095
* @author Julio Montoya
3096
* @version 1.0
3097
*/
3098
function api_is_allowed($tool, $action, $task_id = 0)
3099
{
3100
    $_user = api_get_user_info();
3101
    $_course = api_get_course_info();
3102
3103
    if (api_is_course_admin()) {
3104
        return true;
3105
    }
3106
3107
    if (is_array($_course) and count($_course) > 0) {
3108
        require_once api_get_path(SYS_CODE_PATH).'permissions/permissions_functions.inc.php';
3109
3110
        // Getting the permissions of this user.
3111
        if ($task_id == 0) {
3112
            $user_permissions = get_permissions('user', $_user['user_id']);
3113
            $_SESSION['total_permissions'][$_course['code']] = $user_permissions;
3114
        }
3115
3116
        // Getting the permissions of the task.
3117
        if ($task_id != 0) {
3118
            $task_permissions = get_permissions('task', $task_id);
3119
            /* !!! */$_SESSION['total_permissions'][$_course['code']] = $task_permissions;
3120
        }
3121
        //print_r($_SESSION['total_permissions']);
3122
3123
        // Getting the permissions of the groups of the user
3124
        //$groups_of_user = GroupManager::get_group_ids($_course['db_name'], $_user['user_id']);
3125
3126
        //foreach($groups_of_user as $group)
3127
        //   $this_group_permissions = get_permissions('group', $group);
3128
3129
        // Getting the permissions of the courseroles of the user
3130
        $user_courserole_permissions = get_roles_permissions('user', $_user['user_id']);
3131
3132
        // Getting the permissions of the platformroles of the user
3133
        //$user_platformrole_permissions = get_roles_permissions('user', $_user['user_id'], ', platform');
3134
3135
        // Getting the permissions of the roles of the groups of the user
3136
        //foreach($groups_of_user as $group)
3137
        //    $this_group_courserole_permissions = get_roles_permissions('group', $group);
3138
3139
        // Getting the permissions of the platformroles of the groups of the user
3140
        //foreach($groups_of_user as $group)
3141
        //    $this_group_platformrole_permissions = get_roles_permissions('group', $group, 'platform');
3142
    }
3143
3144
    // If the permissions are limited, we have to map the extended ones to the limited ones.
3145
    if (api_get_setting('permissions') == 'limited') {
3146
        if ($action == 'Visibility') {
3147
            $action = 'Edit';
3148
        }
3149
        if ($action == 'Move') {
3150
            $action = 'Edit';
3151
        }
3152
    }
3153
3154
    // The session that contains all the permissions already exists for this course
3155
    // so there is no need to requery everything.
3156
    //my_print_r($_SESSION['total_permissions'][$_course['code']][$tool]);
3157
    if (is_array($_SESSION['total_permissions'][$_course['code']][$tool])) {
3158
        if (in_array($action, $_SESSION['total_permissions'][$_course['code']][$tool])) {
3159
            return true;
3160
        } else {
3161
            return false;
3162
        }
3163
    }
3164
}
3165
3166
/**
3167
 * Tells whether this user is an anonymous user
3168
 * @param int  $user_id      User ID (optional, will take session ID if not provided)
3169
 * @param bool $db_check     Whether to check in the database (true) or simply in
3170
 * the session (false) to see if the current user is the anonymous user
3171
 * @return bool     true if this user is anonymous, false otherwise
3172
 */
3173
function api_is_anonymous($user_id = null, $db_check = false)
3174
{
3175
    if (!isset($user_id)) {
3176
        $user_id = api_get_user_id();
3177
    }
3178
3179
    if ($db_check) {
3180
        $info = api_get_user_info($user_id);
3181
        if ($info['status'] == ANONYMOUS) {
3182
            return true;
3183
        }
3184
    }
3185
3186
    $_user = api_get_user_info();
3187
3188
    if (isset($_user['status']) && $_user['status'] == ANONYMOUS) {
3189
        //if ($_user['user_id'] == 0) {
3190
        // In some cases, api_set_anonymous doesn't seem to be triggered in local.inc.php. Make sure it is.
3191
        // Occurs in agenda for admin links - YW
3192
        global $use_anonymous;
3193
        if (isset($use_anonymous) && $use_anonymous) {
3194
            api_set_anonymous();
3195
        }
3196
3197
        return true;
3198
    }
3199
3200
    return (isset($_user['is_anonymous']) && $_user['is_anonymous'] === true) || $_user === false;
3201
}
3202
3203
/**
3204
 * Displays message "You are not allowed here..." and exits the entire script.
3205
 * @param bool   $print_headers    Whether or not to print headers (default = false -> does not print them)
3206
 * @param string $message
3207
 */
3208
function api_not_allowed($print_headers = false, $message = null)
3209
{
3210
    if (api_get_setting('sso_authentication') === 'true') {
3211
        global $osso;
3212
        if ($osso) {
3213
            $osso->logout();
3214
        }
3215
    }
3216
    $home_url = api_get_path(WEB_PATH);
3217
    $user_id = api_get_user_id();
3218
    $course = api_get_course_id();
3219
3220
    global $this_section;
3221
3222
    if (CustomPages::enabled() && !isset($user_id)) {
3223
        if (empty($user_id)) {
3224
            // Why the CustomPages::enabled() need to be to set the request_uri
3225
            $_SESSION['request_uri'] = $_SERVER['REQUEST_URI'];
3226
        }
3227
        CustomPages::display(CustomPages::INDEX_UNLOGGED);
3228
    }
3229
3230
    $origin = api_get_origin();
3231
3232
    $msg = null;
3233
    if (isset($message)) {
3234
        $msg = $message;
3235 View Code Duplication
    } else {
3236
        $msg = Display::return_message(
3237
            get_lang('NotAllowedClickBack').'<br/><br/><a href="'.$home_url.'">'.get_lang('ReturnToCourseHomepage').'</a>',
3238
            'error',
3239
            false
3240
        );
3241
    }
3242
3243
    $msg = Display::div($msg, array('align'=>'center'));
3244
3245
    $show_headers = 0;
3246
3247
    if ($print_headers && $origin != 'learnpath') {
3248
        $show_headers = 1;
3249
    }
3250
3251
    $tpl = new Template(null, $show_headers, $show_headers);
3252
    $tpl->assign('hide_login_link', 1);
3253
    $tpl->assign('content', $msg);
3254
3255
    if (($user_id != 0 && !api_is_anonymous()) &&
3256
        (!isset($course) || $course == -1) &&
3257
        empty($_GET['cidReq'])
3258
    ) {
3259
        // if the access is not authorized and there is some login information
3260
        // but the cidReq is not found, assume we are missing course data and send the user
3261
        // to the user_portal
3262
        $tpl->display_one_col_template();
3263
        exit;
3264
    }
3265
3266
    if (!empty($_SERVER['REQUEST_URI']) &&
3267
        (!empty($_GET['cidReq']) ||
3268
            $this_section == SECTION_MYPROFILE ||
3269
            $this_section == SECTION_PLATFORM_ADMIN
3270
        )
3271
    ) {
3272
        $courseCode = api_get_course_id();
3273
        // Only display form and return to the previous URL if there was a course ID included
3274
        if ($user_id != 0 && !api_is_anonymous()) {
3275
            //if there is a user ID, then the user is not allowed but the session is still there. Say so and exit
3276
            $tpl->assign('content', $msg);
3277
            $tpl->display_one_col_template();
3278
            exit;
3279
        }
3280
3281
        if (!is_null($courseCode)) {
3282
            api_set_firstpage_parameter($courseCode);
3283
        }
3284
3285
        // If the user has no user ID, then his session has expired
3286
        $action = api_get_self().'?'.Security::remove_XSS($_SERVER['QUERY_STRING']);
3287
        $action = str_replace('&amp;', '&', $action);
3288
        $form = new FormValidator(
3289
            'formLogin',
3290
            'post',
3291
            $action,
3292
            null,
3293
            array(),
3294
            FormValidator::LAYOUT_BOX_NO_LABEL
3295
        );
3296
        $form->addElement(
3297
            'text',
3298
            'login',
3299
            null,
3300
            array('placeholder' => get_lang('UserName'), 'autocapitalize' => 'none')
3301
        );
3302
        $form->addElement(
3303
            'password',
3304
            'password',
3305
            null,
3306
            array('placeholder' => get_lang('Password'), 'autocapitalize' => 'none')
3307
        );
3308
        $form->addButton('submitAuth', get_lang('LoginEnter'), '', 'primary');
3309
3310
        // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (above)
3311
        $content = Display::return_message(get_lang('NotAllowed'), 'error', false);
3312
3313
        if (!empty($courseCode)) {
3314
            $content .= '<h4>'.get_lang('LoginToGoToThisCourse').'</h4>';
3315
        }
3316
3317
        if (api_is_cas_activated()) {
3318
            $content .= Display::return_message(sprintf(get_lang('YouHaveAnInstitutionalAccount'), api_get_setting("Institution")), '', false);
3319
            $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'));
3320
            $content .= Display::return_message(get_lang('YouDontHaveAnInstitutionAccount'));
3321
            $content .= "<p style='text-align:center'><a href='#' onclick='$(this).parent().next().toggle()'>".get_lang('LoginWithExternalAccount')."</a></p>";
3322
            $content .= "<div style='display:none;'>";
3323
        }
3324
        $content .= '<div class="well">';
3325
        $content .= $form->returnForm();
3326
        $content .='</div>';
3327
        if (api_is_cas_activated()) {
3328
            $content .= "</div>";
3329
        }
3330
3331
        if (!empty($courseCode)) {
3332
            $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
3333
                get_lang('ReturnToCourseHomepage').'</a></p>';
3334
        } else {
3335
            $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
3336
                get_lang('BackHome').'</a></p>';
3337
        }
3338
3339
        $tpl->setLoginBodyClass();
3340
        $tpl->assign('content', $content);
3341
        $tpl->display_one_col_template();
3342
        exit;
3343
    }
3344
3345
    if ($user_id != 0 && !api_is_anonymous()) {
3346
        $tpl->display_one_col_template();
3347
        exit;
3348
    }
3349
3350
    $msg = null;
3351
3352
    // The session is over and we were not in a course,
3353
    // or we try to get directly to a private course without being logged
3354
    $courseId = api_get_course_int_id();
3355
    if (!empty($courseId)) {
3356
        api_set_firstpage_parameter(api_get_course_id());
3357
        $tpl->setLoginBodyClass();
3358
        $action = api_get_self().'?'.Security::remove_XSS($_SERVER['QUERY_STRING']);
3359
        $action = str_replace('&amp;', '&', $action);
3360
        $form = new FormValidator('formLogin', 'post', $action, null, array('class'=>'form-stacked'));
3361
        $form->addElement('text', 'login', null, array('autocapitalize' => 'none', 'placeholder' => get_lang('UserName'), 'class' => 'col-md-3'));
3362
        $form->addElement('password', 'password', null, array('placeholder' => get_lang('Password'), 'class' => 'col-md-3')); //new
3363
        $form->addButtonNext(get_lang('LoginEnter'), 'submitAuth');
3364
3365
        // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (bellow)
3366
        $msg = Display::return_message(get_lang('NotAllowed'), 'error', false);
3367
        $msg .= '<h4>'.get_lang('LoginToGoToThisCourse').'</h4>';
3368
        $casEnabled = api_is_cas_activated();
3369
        if ($casEnabled) {
3370
            $msg .= Display::return_message(sprintf(get_lang('YouHaveAnInstitutionalAccount'), api_get_setting("Institution")), '', false);
3371
            $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'));
3372
            $msg .= Display::return_message(get_lang('YouDontHaveAnInstitutionAccount'));
3373
            $msg .= "<p style='text-align:center'><a href='#' onclick='$(this).parent().next().toggle()'>".get_lang('LoginWithExternalAccount')."</a></p>";
3374
            $msg .= "<div style='display:none;'>";
3375
        }
3376
        $msg .= '<div class="well">';
3377
        $msg .= $form->returnForm();
3378
        $msg .='</div>';
3379
        if ($casEnabled) {
3380
            $msg .= "</div>";
3381
        }
3382 View Code Duplication
    } else {
3383
        // we were not in a course, return to home page
3384
        $msg = Display::return_message(
3385
            get_lang('NotAllowed').'<br/><br/><a href="'.$home_url.'">'.get_lang('BackHome').'</a><br />',
3386
            'error',
3387
            false
3388
        );
3389
    }
3390
3391
    $tpl->assign('content', $msg);
3392
    $tpl->display_one_col_template();
3393
    exit;
3394
}
3395
3396
/**
3397
 * Gets a UNIX timestamp from a database (MySQL) datetime format string
3398
 * @param $last_post_datetime standard output date in a sql query
3399
 * @return integer timestamp
3400
 * @author Toon Van Hoecke <[email protected]>
3401
 * @version October 2003
3402
 * @desc convert sql date to unix timestamp
3403
 */
3404
function convert_sql_date($last_post_datetime) {
3405
    list ($last_post_date, $last_post_time) = explode(' ', $last_post_datetime);
3406
    list ($year, $month, $day) = explode('-', $last_post_date);
3407
    list ($hour, $min, $sec) = explode(':', $last_post_time);
3408
    return mktime((int)$hour, (int)$min, (int)$sec, (int)$month, (int)$day, (int)$year);
3409
}
3410
3411
/**
3412
 * Gets item visibility from the item_property table
3413
 *
3414
 * Getting the visibility is done by getting the last updated visibility entry,
3415
 * using the largest session ID found if session 0 and another was found (meaning
3416
 * the only one that is actually from the session, in case there are results from
3417
 * session 0 *AND* session n).
3418
 * @param array     Course properties array (result of api_get_course_info())
3419
 * @param string    Tool (learnpath, document, etc)
3420
 * @param int       The item ID in the given tool
3421
 * @param int       The session ID (optional)
3422
 * @param string $tool
3423
 * @param integer $user_id
3424
 * @param string $type
3425
 * @return int      -1 on error, 0 if invisible, 1 if visible
3426
 */
3427
function api_get_item_visibility(
3428
    $_course,
3429
    $tool,
3430
    $id,
3431
    $session = 0,
3432
    $user_id = null,
3433
    $type = null,
3434
    $group_id = null
3435
) {
3436
    if (!is_array($_course) || count($_course) == 0 || empty($tool) || empty($id)) {
3437
        return -1;
3438
    }
3439
3440
    $tool = Database::escape_string($tool);
3441
    $id = intval($id);
3442
    $session = (int) $session;
3443
    $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
3444
    $course_id = intval($_course['real_id']);
3445
3446
    $userCondition = '';
3447
    if (!empty($user_id)) {
3448
        $user_id = intval($user_id);
3449
        $userCondition = " AND to_user_id = $user_id ";
3450
    }
3451
3452
    $typeCondition = '';
3453
    if (!empty($type)) {
3454
        $type = Database::escape_string($type);
3455
        $typeCondition = " AND lastedit_type = '$type' ";
3456
    }
3457
3458
    $groupCondition = '';
3459
    if (!empty($group_id)) {
3460
        $group_id = intval($group_id);
3461
        $groupCondition = " AND to_group_id = '$group_id' ";
3462
    }
3463
3464
    $sql = "SELECT visibility
3465
            FROM $TABLE_ITEMPROPERTY
3466
            WHERE
3467
                c_id = $course_id AND
3468
                tool = '$tool' AND
3469
                ref = $id AND
3470
                (session_id = $session OR session_id = 0 OR session_id IS NULL)
3471
                $userCondition $typeCondition $groupCondition
3472
            ORDER BY session_id DESC, lastedit_date DESC
3473
            LIMIT 1";
3474
3475
    $res = Database::query($sql);
3476
    if ($res === false || Database::num_rows($res) == 0) {
3477
        return -1;
3478
    }
3479
    $row = Database::fetch_array($res);
3480
3481
    return $row['visibility'];
3482
}
3483
3484
/**
3485
 * Delete a row in the c_item_property table
3486
 *
3487
 * @param array $courseInfo
3488
 * @param string $tool
3489
 * @param int $itemId
3490
 * @param int $userId
3491
 * @param int $groupId
3492
 * @param int $sessionId
3493
 * @return false|null
3494
 */
3495
function api_item_property_delete(
3496
    $courseInfo,
3497
    $tool,
3498
    $itemId,
3499
    $userId,
3500
    $groupId = 0,
3501
    $sessionId = 0
3502
) {
3503
    if (empty($courseInfo)) {
3504
        return false;
3505
    }
3506
3507
    $courseId = intval($courseInfo['real_id']);
3508
3509
    if (empty($courseId) || empty($tool) || empty($itemId)) {
3510
        return false;
3511
    }
3512
3513
    $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3514
    $tool = Database::escape_string($tool);
3515
    $itemId = intval($itemId);
3516
    $userId = intval($userId);
3517
    $groupId = intval($groupId);
3518
    $sessionId = intval($sessionId);
3519
3520
    $groupCondition = " AND to_group_id = $groupId ";
3521
    if (empty($groupId)) {
3522
        $groupCondition = " AND (to_group_id is NULL OR to_group_id = 0) ";
3523
    }
3524
3525
    $userCondition = " AND to_user_id = $userId ";
3526
    if (empty($userId)) {
3527
        $userCondition = " AND (to_user_id is NULL OR to_user_id = 0) ";
3528
    }
3529
    $sessionCondition = api_get_session_condition($sessionId, true, false, 'session_id');
3530
    $sql = "DELETE FROM $table
3531
            WHERE
3532
                c_id = $courseId AND
3533
                tool  = '$tool' AND
3534
                ref = $itemId
3535
                $sessionCondition
3536
                $userCondition
3537
                $groupCondition
3538
            ";
3539
3540
    Database::query($sql);
3541
}
3542
3543
/**
3544
 * Updates or adds item properties to the Item_propetry table
3545
 * Tool and lastedit_type are language independant strings (langvars->get_lang!)
3546
 *
3547
 * @param array $_course array with course properties
3548
 * @param string $tool tool id, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
3549
 * @param int $item_id id of the item itself, linked to key of every tool ('id', ...)
3550
 * @param string $last_edit_type add or update action
3551
 * (1) message to be translated (in trad4all) : e.g. DocumentAdded, DocumentUpdated;
3552
 * (2) "delete"
3553
 * (3) "visible"
3554
 * (4) "invisible"
3555
 * @param int $user_id id of the editing/adding user
3556
 * @param int $to_group_id group.iid
3557
 * @param int $to_user_id id of the intended user (always has priority over $to_group_id !), only relevant for $type (1)
3558
 * @param string $start_visible 0000-00-00 00:00:00 format
3559
 * @param string $end_visible 0000-00-00 00:00:00 format
3560
 * @param int $session_id The session ID, if any, otherwise will default to 0
3561
 * @return boolean False if update fails.
3562
 * @author Toon Van Hoecke <[email protected]>, Ghent University
3563
 * @version January 2005
3564
 * @desc update the item_properties table (if entry not exists, insert) of the course
3565
 */
3566
function api_item_property_update(
3567
    $_course,
3568
    $tool,
3569
    $item_id,
3570
    $last_edit_type,
3571
    $user_id,
3572
    $to_group_id = 0,
3573
    $to_user_id = null,
3574
    $start_visible = '',
3575
    $end_visible = '',
3576
    $session_id = 0
3577
) {
3578
    if (empty($_course)) {
3579
        return false;
3580
    }
3581
3582
    $course_id = $_course['real_id'];
3583
3584
    if (empty($course_id)) {
3585
        return false;
3586
    }
3587
3588
    $em = Database::getManager();
3589
3590
    // Definition of variables.
3591
    $tool = Database::escape_string($tool);
3592
    $item_id = intval($item_id);
3593
    $lastEditTypeNoFilter = $last_edit_type;
3594
    $last_edit_type = Database::escape_string($last_edit_type);
3595
    $user_id = intval($user_id);
3596
3597
    $startVisible = "NULL";
3598
    if (!empty($start_visible)) {
3599
        $start_visible = Database::escape_string($start_visible);
3600
        $startVisible = "'$start_visible'";
3601
    }
3602
3603
    $endVisible = "NULL";
3604
    if (!empty($end_visible)) {
3605
        $end_visible = Database::escape_string($end_visible);
3606
        $endVisible = "'$end_visible'";
3607
    }
3608
3609
    $to_filter = '';
3610
    $time = api_get_utc_datetime();
3611
3612
    if (!empty($session_id)) {
3613
        $session_id = intval($session_id);
3614
    } else {
3615
        $session_id = api_get_session_id();
3616
    }
3617
3618
    // Definition of tables.
3619
    $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
3620
3621
    if ($to_user_id <= 0) {
3622
        $to_user_id = null; // No to_user_id set
3623
    }
3624
3625
    if (!is_null($to_user_id)) {
3626
        // $to_user_id has more priority than $to_group_id
3627
        $to_user_id = intval($to_user_id);
3628
        $to_field = 'to_user_id';
3629
        $to_value = $to_user_id;
3630
    } else {
3631
        // $to_user_id is not set.
3632
        $to_field = 'to_group_id';
3633
        $to_value = $to_group_id;
3634
    }
3635
3636
    $toValueCondition = empty($to_value) ? "NULL" : "'$to_value'";
3637
3638
    // Set filters for $to_user_id and $to_group_id, with priority for $to_user_id
3639
    $condition_session = " AND session_id = $session_id ";
3640
    if (empty($session_id)) {
3641
        $condition_session = " AND (session_id = 0 OR session_id IS NULL) ";
3642
    }
3643
3644
    $filter = " c_id = $course_id AND tool = '$tool' AND ref = $item_id $condition_session ";
3645
3646
    // Check whether $to_user_id and $to_group_id are passed in the function call.
3647
    // If both are not passed (both are null) then it is a message for everybody and $to_group_id should be 0 !
3648
    if (is_null($to_user_id) && is_null($to_group_id)) {
3649
        $to_group_id = 0;
3650
    }
3651
3652
    if (!is_null($to_user_id)) {
3653
        // Set filter to intended user.
3654
        $to_filter = " AND to_user_id = $to_user_id $condition_session";
3655
    } else {
3656
        // Set filter to intended group.
3657
        if (($to_group_id != 0) && $to_group_id == strval(intval($to_group_id))) {
3658
            $to_filter = " AND to_group_id = $to_group_id $condition_session";
3659
        }
3660
    }
3661
3662
    // Adding filter if set.
3663
    $filter .= $to_filter;
3664
3665
    // Update if possible
3666
    $set_type = '';
3667
3668
    switch ($lastEditTypeNoFilter) {
3669 View Code Duplication
        case 'delete':
3670
            // delete = make item only visible for the platform admin.
3671
            $visibility = '2';
3672
            if (!empty($session_id)) {
3673
                // Check whether session id already exist into item_properties for updating visibility or add it.
3674
                $sql = "SELECT session_id FROM $tableItemProperty
3675
                        WHERE
3676
                            c_id = $course_id AND
3677
                            tool = '$tool' AND
3678
                            ref = $item_id AND
3679
                            session_id = $session_id";
3680
                $rs = Database::query($sql);
3681
                if (Database::num_rows($rs) > 0) {
3682
                    $sql = "UPDATE $tableItemProperty
3683
                            SET lastedit_type       = '".str_replace('_', '', ucwords($tool))."Deleted',
3684
                                lastedit_date       = '$time',
3685
                                lastedit_user_id    = $user_id,
3686
                                visibility          = $visibility,
3687
                                session_id          = $session_id $set_type
3688
                            WHERE $filter";
3689
                    $result = Database::query($sql);
3690
                } else {
3691
                    $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)
3692
                            VALUES ($course_id, '$tool',$item_id, '$time', $user_id, '$time', '$last_edit_type',$user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3693
                    $result = Database::query($sql);
3694
                    $id = Database::insert_id();
3695
                    if ($id) {
3696
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3697
                        Database::query($sql);
3698
                    }
3699
                }
3700
            } else {
3701
                $sql = "UPDATE $tableItemProperty
3702
                        SET
3703
                            lastedit_type='".str_replace('_', '', ucwords($tool))."Deleted',
3704
                            lastedit_date='$time',
3705
                            lastedit_user_id = $user_id,
3706
                            visibility = $visibility $set_type
3707
                        WHERE $filter";
3708
                $result = Database::query($sql);
3709
            }
3710
            break;
3711 View Code Duplication
        case 'visible' : // Change item to visible.
3712
            $visibility = '1';
3713
            if (!empty($session_id)) {
3714
                // Check whether session id already exist into item_properties for updating visibility or add it.
3715
                $sql = "SELECT session_id FROM $tableItemProperty
3716
                        WHERE
3717
                            c_id = $course_id AND
3718
                            tool = '$tool' AND
3719
                            ref = $item_id AND
3720
                            session_id = $session_id";
3721
                $rs = Database::query($sql);
3722
                if (Database::num_rows($rs) > 0) {
3723
                    $sql = "UPDATE $tableItemProperty
3724
                            SET
3725
                                lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
3726
                                lastedit_date='$time',
3727
                                lastedit_user_id = $user_id,
3728
                                visibility = $visibility,
3729
                                session_id = $session_id $set_type
3730
                            WHERE $filter";
3731
                    $result = Database::query($sql);
3732
                } else {
3733
                    $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)
3734
                            VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3735
                    $result = Database::query($sql);
3736
                    $id = Database::insert_id();
3737
                    if ($id) {
3738
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3739
                        Database::query($sql);
3740
                    }
3741
                }
3742
            } else {
3743
                $sql = "UPDATE $tableItemProperty
3744
                        SET
3745
                            lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
3746
                            lastedit_date='$time',
3747
                            lastedit_user_id = $user_id,
3748
                            visibility = $visibility $set_type
3749
                        WHERE $filter";
3750
                $result = Database::query($sql);
3751
            }
3752
            break;
3753 View Code Duplication
        case 'invisible' : // Change item to invisible.
3754
            $visibility = '0';
3755
            if (!empty($session_id)) {
3756
                // Check whether session id already exist into item_properties for updating visibility or add it
3757
                $sql = "SELECT session_id FROM $tableItemProperty
3758
                        WHERE
3759
                            c_id = $course_id AND
3760
                            tool = '$tool' AND
3761
                            ref = $item_id AND
3762
                            session_id = $session_id";
3763
                $rs = Database::query($sql);
3764
                if (Database::num_rows($rs) > 0) {
3765
                    $sql = "UPDATE $tableItemProperty
3766
                            SET
3767
                                lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
3768
                                lastedit_date = '$time',
3769
                                lastedit_user_id = $user_id,
3770
                                visibility = $visibility,
3771
                                session_id = $session_id $set_type
3772
                            WHERE $filter";
3773
                    $result = Database::query($sql);
3774
                } else {
3775
                    $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)
3776
                            VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3777
                    $result = Database::query($sql);
3778
                    $id = Database::insert_id();
3779
                    if ($id) {
3780
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3781
                        Database::query($sql);
3782
                    }
3783
                }
3784
            } else {
3785
                $sql = "UPDATE $tableItemProperty
3786
                        SET
3787
                            lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
3788
                            lastedit_date = '$time',
3789
                            lastedit_user_id = $user_id,
3790
                            visibility = $visibility $set_type
3791
                        WHERE $filter";
3792
                $result = Database::query($sql);
3793
            }
3794
            break;
3795
        default: // The item will be added or updated.
3796
            $set_type = ", lastedit_type = '$last_edit_type' ";
3797
            $visibility = '1';
3798
            //$filter .= $to_filter; already added
3799
            $sql = "UPDATE $tableItemProperty
3800
                    SET
3801
                      lastedit_date = '$time',
3802
                      lastedit_user_id = $user_id $set_type
3803
                    WHERE $filter";
3804
            $result = Database::query($sql);
3805
    }
3806
3807
    // Insert if no entries are found (can only happen in case of $last_edit_type switch is 'default').
3808
    if ($result == false || 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...
3809
        $objCourse = $em->find('ChamiloCoreBundle:Course', intval($course_id));
3810
        $objTime = new DateTime('now', new DateTimeZone('UTC'));
3811
        $objUser = $em->find('ChamiloUserBundle:User', intval($user_id));
3812
        $objGroup = $em->find('ChamiloCourseBundle:CGroupInfo', intval($to_group_id));
3813
        $objToUser = $em->find('ChamiloUserBundle:User', intval($to_user_id));
3814
        $objSession = $em->find('ChamiloCoreBundle:Session', intval($session_id));
3815
3816
        $startVisibleDate = !empty($start_visible) ? new DateTime($start_visible, new DateTimeZone('UTC')) : null;
3817
        $endVisibleDate = !empty($endVisibleDate) ? new DateTime($endVisibleDate, new DateTimeZone('UTC')) : null;
0 ignored issues
show
Bug introduced by
The variable $endVisibleDate seems only to be defined at a later point. As such the call to empty() seems to always evaluate to true.

This check marks calls to isset(...) or empty(...) that are found before the variable itself is defined. These will always have the same result.

This is likely the result of code being shifted around. Consider removing these calls.

Loading history...
3818
3819
        $cItemProperty = new CItemProperty($objCourse);
3820
        $cItemProperty
3821
            ->setTool($tool)
3822
            ->setRef($item_id)
3823
            ->setInsertDate($objTime)
3824
            ->setInsertUser($objUser)
3825
            ->setLasteditDate($objTime)
3826
            ->setLasteditType($last_edit_type)
3827
            ->setGroup($objGroup)
3828
            ->setToUser($objToUser)
3829
            ->setVisibility($visibility)
3830
            ->setStartVisible($startVisibleDate)
3831
            ->setEndVisible($endVisibleDate)
3832
            ->setSession($objSession);
3833
3834
        $em->persist($cItemProperty);
3835
        $em->flush();
3836
3837
        $id = $cItemProperty->getIid();
3838
3839
        if ($id) {
3840
            $cItemProperty->setId($id);
3841
            $em->merge($cItemProperty);
3842
            $em->flush();
3843
3844
            return false;
3845
        }
3846
    }
3847
3848
    return true;
3849
}
3850
3851
/**
3852
 * Gets item property by tool
3853
 * @param string    course code
3854
 * @param string    tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
3855
 * @param int       id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
3856
 * @param int $session_id
3857
 * @param string $tool
3858
 * @param string $course_code
3859
 * @return array All fields from c_item_property (all rows found) or empty array
3860
 */
3861 View Code Duplication
function api_get_item_property_by_tool($tool, $course_code, $session_id = null)
3862
{
3863
    $course_info = api_get_course_info($course_code);
3864
    $tool = Database::escape_string($tool);
3865
3866
    // Definition of tables.
3867
    $item_property_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3868
    $session_id = intval($session_id);
3869
    $session_condition = ' AND session_id = '.$session_id;
3870
    if (empty($session_id)) {
3871
        $session_condition = " AND (session_id = 0 OR session_id IS NULL) ";
3872
    }
3873
    $course_id = $course_info['real_id'];
3874
3875
    $sql = "SELECT * FROM $item_property_table
3876
            WHERE
3877
                c_id = $course_id AND
3878
                tool = '$tool'
3879
                $session_condition ";
3880
    $rs  = Database::query($sql);
3881
    $list = array();
3882
    if (Database::num_rows($rs) > 0) {
3883
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
3884
            $list[] = $row;
3885
        }
3886
    }
3887
    return $list;
3888
}
3889
3890
/**
3891
 * Gets item property by tool and user
3892
 * @param int $userId
3893
 * @param int $tool
3894
 * @param int $courseId
3895
 * @param int $session_id
3896
 * @return array
3897
 */
3898 View Code Duplication
function api_get_item_property_list_by_tool_by_user(
3899
    $userId,
3900
    $tool,
3901
    $courseId,
3902
    $session_id = 0
3903
) {
3904
    $userId = intval($userId);
3905
    $tool = Database::escape_string($tool);
3906
    $session_id = intval($session_id);
3907
    $courseId = intval($courseId);
3908
3909
    // Definition of tables.
3910
    $item_property_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3911
    $session_condition = ' AND session_id = '.$session_id;
3912
    if (empty($session_id)) {
3913
        $session_condition = " AND (session_id = 0 OR session_id IS NULL) ";
3914
    }
3915
    $sql = "SELECT * FROM $item_property_table
3916
            WHERE
3917
                insert_user_id = $userId AND
3918
                c_id = $courseId AND
3919
                tool = '$tool'
3920
                $session_condition ";
3921
3922
    $rs = Database::query($sql);
3923
    $list = array();
3924
    if (Database::num_rows($rs) > 0) {
3925
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
3926
            $list[] = $row;
3927
        }
3928
    }
3929
3930
    return $list;
3931
}
3932
3933
/**
3934
 * Gets item property id from tool of a course
3935
 * @param string $course_code course code
3936
 * @param string $tool tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
3937
 * @param int $ref id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
3938
 * @param int $sessionId Session ID (optional)
3939
 * @return int
3940
 */
3941
function api_get_item_property_id($course_code, $tool, $ref, $sessionId = 0)
3942
{
3943
    $course_info = api_get_course_info($course_code);
3944
    $tool = Database::escape_string($tool);
3945
    $ref = intval($ref);
3946
3947
    // Definition of tables.
3948
    $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
3949
    $course_id = $course_info['real_id'];
3950
    $sessionId = (int) $sessionId;
3951
    $sessionCondition = " AND session_id = $sessionId ";
3952
    if (empty($sessionId)) {
3953
        $sessionCondition = " AND (session_id = 0 OR session_id IS NULL) ";
3954
    }
3955
    $sql = "SELECT id FROM $tableItemProperty
3956
            WHERE
3957
                c_id = $course_id AND
3958
                tool = '$tool' AND
3959
                ref = $ref
3960
                $sessionCondition";
3961
    $rs  = Database::query($sql);
3962
    $item_property_id = '';
3963
    if (Database::num_rows($rs) > 0) {
3964
        $row = Database::fetch_array($rs);
3965
        $item_property_id = $row['id'];
3966
    }
3967
    return $item_property_id;
3968
}
3969
3970
/**
3971
 * Inserts a record in the track_e_item_property table (No update)
3972
 * @param string $tool
3973
 * @param int $ref
3974
 * @param string $title
3975
 * @param string $content
3976
 * @param int $progress
3977
 * @return bool|int
3978
 */
3979
function api_track_item_property_update($tool, $ref, $title, $content, $progress)
3980
{
3981
    $tbl_stats_item_property = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY);
3982
    $course_id = api_get_course_int_id(); //numeric
3983
    $course_code = api_get_course_id(); //alphanumeric
3984
    $item_property_id = api_get_item_property_id($course_code, $tool, $ref);
3985
    if (!empty($item_property_id)) {
3986
        $sql = "INSERT IGNORE INTO $tbl_stats_item_property SET
3987
                course_id           = '$course_id',
3988
                item_property_id    = '$item_property_id',
3989
                title               = '".Database::escape_string($title)."',
3990
                content             = '".Database::escape_string($content)."',
3991
                progress            = '".intval($progress)."',
3992
                lastedit_date       = '".api_get_utc_datetime()."',
3993
                lastedit_user_id    = '".api_get_user_id()."',
3994
                session_id          = '".api_get_session_id()."'";
3995
        $result = Database::query($sql);
3996
        $affected_rows = Database::affected_rows($result);
3997
3998
        return $affected_rows;
3999
    }
4000
4001
    return false;
4002
}
4003
4004
/**
4005
 * @param string $tool
4006
 * @param int $ref
4007
 * @return array|resource
4008
 */
4009 View Code Duplication
function api_get_track_item_property_history($tool, $ref)
4010
{
4011
    $tbl_stats_item_property = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY);
4012
    $course_id = api_get_course_int_id(); //numeric
4013
    $course_code = api_get_course_id(); //alphanumeric
4014
    $item_property_id = api_get_item_property_id($course_code, $tool, $ref);
4015
    $sql = "SELECT * FROM $tbl_stats_item_property
4016
            WHERE item_property_id = $item_property_id AND course_id = $course_id
4017
            ORDER BY lastedit_date DESC";
4018
    $result = Database::query($sql);
4019
    if ($result == false) {
4020
        $result = array();
4021
    } else {
4022
        $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...
4023
    }
4024
4025
    return $result;
4026
}
4027
4028
/**
4029
 * Gets item property data from tool of a course id
4030
 * @param int $course_id
4031
 * @param string $tool   tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
4032
 * @param int $ref id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
4033
 * @param int $session_id
4034
 * @param int $groupId
4035
 *
4036
 * @return array Array with all fields from c_item_property, empty array if not found or false if course could not be found
4037
 */
4038
function api_get_item_property_info($course_id, $tool, $ref, $session_id = 0, $groupId = 0)
4039
{
4040
    $courseInfo = api_get_course_info_by_id($course_id);
4041
4042
    if (empty($courseInfo)) {
4043
        return false;
4044
    }
4045
4046
    $tool = Database::escape_string($tool);
4047
    $ref = intval($ref);
4048
    $course_id = $courseInfo['real_id'];
4049
    $session_id = intval($session_id);
4050
4051
    $sessionCondition = " session_id = $session_id";
4052
    if (empty($session_id)) {
4053
        $sessionCondition = " (session_id = 0 OR session_id IS NULL) ";
4054
    }
4055
4056
    // Definition of tables.
4057
    $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
4058
4059
    $sql = "SELECT * FROM $table
4060
            WHERE
4061
                c_id = $course_id AND
4062
                tool = '$tool' AND
4063
                ref = $ref AND
4064
                $sessionCondition ";
4065
4066
    if (!empty($groupId)) {
4067
        $groupId = intval($groupId);
4068
        $sql .= " AND to_group_id = $groupId ";
4069
    }
4070
4071
    $rs  = Database::query($sql);
4072
    $row = array();
4073
    if (Database::num_rows($rs) > 0) {
4074
        $row = Database::fetch_array($rs,'ASSOC');
4075
    }
4076
4077
    return $row;
4078
}
4079
4080
/**
4081
 * Displays a combo box so the user can select his/her preferred language.
4082
 * @param string The desired name= value for the select
4083
 * @param bool Whether we use the JQuery Chozen library or not
4084
 * (in some cases, like the indexing language picker, it can alter the presentation)
4085
 * @return string
4086
 */
4087
function api_get_languages_combo($name = 'language')
4088
{
4089
    $ret = '';
4090
    $platformLanguage = api_get_setting('platformLanguage');
4091
4092
    // Retrieve a complete list of all the languages.
4093
    $language_list = api_get_languages();
4094
4095
    if (count($language_list['name']) < 2) {
4096
        return $ret;
4097
    }
4098
4099
    // The the current language of the user so that his/her language occurs as selected in the dropdown menu.
4100
    if (isset($_SESSION['user_language_choice'])) {
4101
        $default = $_SESSION['user_language_choice'];
4102
    } else {
4103
        $default = $platformLanguage;
4104
    }
4105
4106
    $languages  = $language_list['name'];
4107
    $folder     = $language_list['folder'];
4108
4109
    $ret .= '<select name="' . $name . '" id="language_chosen" class="selectpicker show-tick form-control">';
4110
    foreach ($languages as $key => $value) {
4111
        if ($folder[$key] == $default) {
4112
            $selected = ' selected="selected"';
4113
        } else {
4114
            $selected = '';
4115
        }
4116
        $ret .= sprintf('<option value=%s" %s>%s</option>', $folder[$key], $selected, $value);
4117
    }
4118
    $ret .= '</select>';
4119
    return $ret;
4120
}
4121
4122
/**
4123
 * Displays a form (drop down menu) so the user can select his/her preferred language.
4124
 * The form works with or without javascript
4125
 * @param  boolean Hide form if only one language available (defaults to false = show the box anyway)
4126
 * @return null|string Display the box directly
4127
 */
4128
function api_display_language_form($hide_if_no_choice = false)
4129
{
4130
    // Retrieve a complete list of all the languages.
4131
    $language_list = api_get_languages();
4132
    if (count($language_list['name']) <= 1 && $hide_if_no_choice) {
4133
        return; //don't show any form
4134
    }
4135
4136
    // The the current language of the user so that his/her language occurs as selected in the dropdown menu.
4137
    if (isset($_SESSION['user_language_choice'])) {
4138
        $user_selected_language = $_SESSION['user_language_choice'];
4139
    }
4140
    if (empty($user_selected_language)) {
4141
        $user_selected_language = api_get_setting('platformLanguage');
4142
    }
4143
4144
    $original_languages = $language_list['name'];
4145
    $folder = $language_list['folder']; // This line is probably no longer needed.
4146
    $html = '<script>    
4147
    $(document).ready(function() {
4148
        $("#language_list").change(function() {
4149
            jumpMenu("parent",this,0);
4150
        });
4151
    });
4152
4153
    function jumpMenu(targ,selObj,restore){ // v3.0
4154
        eval(targ+".location=\'"+selObj.options[selObj.selectedIndex].value+"\'");
4155
        if (restore) selObj.selectedIndex=0;
4156
    }
4157
    </script>';
4158
    $html .= '<form id="lang_form" name="lang_form" method="post" action="'.api_get_self().'">';
4159
    $html .= '<label style="display: none;" for="language_list">' . get_lang('Language') . '</label>';
4160
    $html .=  '<select id="language_list" class="selectpicker show-tick form-control" name="language_list" >';
4161
4162
    foreach ($original_languages as $key => $value) {
4163
        if ($folder[$key] == $user_selected_language) {
4164
            $option_end = ' selected="selected" >';
4165
        } else {
4166
            $option_end = '>';
4167
        }
4168
        $html .=  '<option value="'.api_get_self().'?language='.$folder[$key].'"'.$option_end;
4169
        //echo substr($value, 0, 16); // Cut string to keep 800x600 aspect.
4170
        $html .=  $value.'</option>';
4171
    }
4172
    $html .=  '</select>';
4173
    $html .=  '<noscript><input type="submit" name="user_select_language" value="'.get_lang('Ok').'" /></noscript>';
4174
    $html .=  '</form>';
4175
    return $html;
4176
}
4177
4178
/**
4179
 * Returns a list of all the languages that are made available by the admin.
4180
 * @return array An array with all languages. Structure of the array is
4181
 *  array['name'] = An array with the name of every language
4182
 *  array['folder'] = An array with the corresponding names of the language-folders in the filesystem
4183
 */
4184
function api_get_languages() {
4185
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4186
    $sql = "SELECT * FROM $tbl_language WHERE available='1' 
4187
            ORDER BY original_name ASC";
4188
    $result = Database::query($sql);
4189
    $language_list = array();
4190
    while ($row = Database::fetch_array($result)) {
4191
        $language_list['name'][] = $row['original_name'];
4192
        $language_list['folder'][] = $row['dokeos_folder'];
4193
    }
4194
    return $language_list;
4195
}
4196
4197
/**
4198
 * Returns a list of all the languages that are made available by the admin.
4199
 * @return array
4200
 */
4201
function api_get_languages_to_array() {
4202
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4203
    $sql = "SELECT * FROM $tbl_language WHERE available='1' ORDER BY original_name ASC";
4204
    $result = Database::query($sql);
4205
    $languages = array();
4206
    while ($row = Database::fetch_array($result)) {
4207
        $languages[$row['dokeos_folder']] = $row['original_name'];
4208
    }
4209
    return $languages;
4210
}
4211
4212
/**
4213
 * Returns the id (the database id) of a language
4214
 * @param   string  language name (the corresponding name of the language-folder in the filesystem)
4215
 * @return  int     id of the language
4216
 */
4217
function api_get_language_id($language)
4218
{
4219
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4220
    if (empty($language)) {
4221
        return null;
4222
    }
4223
    $language = Database::escape_string($language);
4224
    $sql = "SELECT id FROM $tbl_language
4225
            WHERE dokeos_folder = '$language' LIMIT 1";
4226
    $result = Database::query($sql);
4227
    $row = Database::fetch_array($result);
4228
    return $row['id'];
4229
}
4230
4231
/**
4232
 * Gets language of the requested type for the current user. Types are :
4233
 * user_profil_lang : profile language of current user
4234
 * user_select_lang : language selected by user at login
4235
 * course_lang : language of the current course
4236
 * platform_lang : default platform language
4237
 * @param string $lang_type
4238
 * @return string
4239
 **/
4240
function api_get_language_from_type($lang_type)
4241
{
4242
    $return = false;
4243
    switch ($lang_type) {
4244
        case 'platform_lang':
4245
            $temp_lang = api_get_setting('platformLanguage');
4246
            if (!empty($temp_lang))
4247
                $return = $temp_lang;
4248
            break;
4249
        case 'user_profil_lang':
4250
            $_user = api_get_user_info();
4251
4252
            if (isset($_user['language']) && !empty($_user['language']))
4253
                $return = $_user['language'];
4254
            break;
4255
        case 'user_selected_lang':
4256
            if (isset($_SESSION['user_language_choice']) && !empty($_SESSION['user_language_choice']))
4257
                $return = $_SESSION['user_language_choice'];
4258
            break;
4259
        case 'course_lang':
4260
            global $_course;
4261
            $cidReq = null;
4262
            if (empty($_course)) {
4263
4264
                // Code modified because the local.inc.php file it's declarated after this work
4265
                // causing the function api_get_course_info() returns a null value
4266
                $cidReq = isset($_GET["cidReq"]) ? Database::escape_string($_GET["cidReq"]) : null;
4267
                $cDir = (!empty($_GET['cDir']) ? $_GET['cDir'] : null);
4268
                if (empty($cidReq) && !empty($cDir)) {
4269
                    $c = CourseManager::get_course_id_from_path($cDir);
4270
                    if ($c) {
4271
                        $cidReq = $c;
4272
                    }
4273
                }
4274
            }
4275
            $_course = api_get_course_info($cidReq);
4276
            if (isset($_course['language']) && !empty($_course['language'])) {
4277
                $return = $_course['language'];
4278
                $showCourseInUserLanguage = api_get_course_setting('show_course_in_user_language');
4279
                if ($showCourseInUserLanguage == 1) {
4280
                    $userInfo = api_get_user_info();
4281
                    if (isset($userInfo['language'])) {
4282
                        $return = $userInfo['language'];
4283
                    }
4284
                }
4285
            }
4286
            break;
4287
        default:
4288
            $return = false;
4289
        break;
4290
    }
4291
4292
    return $return;
4293
}
4294
4295
/**
4296
 * Get the language information by its id
4297
 * @param int $languageId
4298
 * @return array
4299
 */
4300
function api_get_language_info($languageId) {
4301
    $language = Database::getManager()
4302
        ->find('ChamiloCoreBundle:Language', intval($languageId));
4303
4304
    if (!$language) {
4305
        return [];
4306
    }
4307
4308
    return [
4309
        'id' => $language->getId(),
4310
        'original_name' => $language->getOriginalName(),
4311
        'english_name' => $language->getEnglishName(),
4312
        'isocode' => $language->getIsocode(),
4313
        'dokeos_folder' => $language->getDokeosFolder(),
4314
        'available' => $language->getAvailable(),
4315
        'parent_id' => $language->getParent() ? $language->getParent()->getId() : null
4316
    ];
4317
}
4318
4319
/**
4320
 * Returns the name of the visual (CSS) theme to be applied on the current page.
4321
 * The returned name depends on the platform, course or user -wide settings.
4322
 * @return string   The visual theme's name, it is the name of a folder inside .../chamilo/main/css/
4323
 */
4324
function api_get_visual_theme()
4325
{
4326
    static $visual_theme;
4327
    if (!isset($visual_theme)) {
4328
4329
        $platform_theme = api_get_setting('stylesheets');
4330
4331
        // Platform's theme.
4332
        $visual_theme = $platform_theme;
4333
4334
        if (api_get_setting('user_selected_theme') == 'true') {
4335
            $user_info = api_get_user_info();
4336
            if (isset($user_info['theme'])) {
4337
                $user_theme = $user_info['theme'];
4338
4339
                if (!empty($user_theme)) {
4340
                    $visual_theme = $user_theme;
4341
                    // User's theme.
4342
                }
4343
            }
4344
        }
4345
4346
        $course_id = api_get_course_id();
4347
4348
        if (!empty($course_id) && $course_id != -1) {
4349
            if (api_get_setting('allow_course_theme') == 'true') {
4350
                $course_theme = api_get_course_setting('course_theme');
4351
4352
                if (!empty($course_theme) && $course_theme != -1) {
4353
                    if (!empty($course_theme)) {
4354
                        // Course's theme.
4355
                        $visual_theme = $course_theme;
4356
                    }
4357
                }
4358
4359
                $allow_lp_theme = api_get_course_setting('allow_learning_path_theme');
4360
                if ($allow_lp_theme == 1) {
4361
                    global $lp_theme_css, $lp_theme_config;
4362
                    // These variables come from the file lp_controller.php.
4363
                    if (!$lp_theme_config) {
4364
                        if (!empty($lp_theme_css)) {
4365
                            // LP's theme.
4366
                            $visual_theme = $lp_theme_css;
4367
                        }
4368
                    }
4369
                }
4370
            }
4371
        }
4372
4373
        if (empty($visual_theme)) {
4374
            $visual_theme = 'chamilo';
4375
        }
4376
4377
        global $lp_theme_log;
4378
        if ($lp_theme_log) {
4379
            $visual_theme = $platform_theme;
4380
        }
4381
    }
4382
4383
    return $visual_theme;
4384
}
4385
4386
/**
4387
 * Returns a list of CSS themes currently available in the CSS folder
4388
 * @return array        List of themes directories from the css folder
4389
 * Note: Directory names (names of themes) in the file system should contain ASCII-characters only.
4390
 */
4391
function api_get_themes() {
4392
    $cssdir = api_get_path(SYS_CSS_PATH) . 'themes/';
4393
    $list_dir = array();
4394
    $list_name = array();
4395
4396
    if (is_dir($cssdir)) {
4397
        $themes = @scandir($cssdir);
4398
4399
        if (is_array($themes)) {
4400
            if ($themes !== false) {
4401
                sort($themes);
4402
4403
                foreach ($themes as & $theme) {
4404
                    if (substr($theme, 0, 1) == '.') {
4405
                        continue;
4406
                    } else {
4407
                        if (is_dir($cssdir.$theme)) {
4408
                            $list_dir[] = $theme;
4409
                            $list_name[] = ucwords(str_replace('_', ' ', $theme));
4410
                        }
4411
                    }
4412
                }
4413
            }
4414
        }
4415
    }
4416
4417
    return array($list_dir, $list_name);
4418
}
4419
4420
/**
4421
 * Find the largest sort value in a given user_course_category
4422
 * This function is used when we are moving a course to a different category
4423
 * and also when a user subscribes to courses (the new course is added at the end of the main category
4424
 * @author Patrick Cool <[email protected]>, Ghent University
4425
 * @param int $user_course_category the id of the user_course_category
4426
 * @param integer $user_id
4427
 * @return int the value of the highest sort of the user_course_category
4428
 */
4429
function api_max_sort_value($user_course_category, $user_id)
4430
{
4431
    $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4432
    $sql = "SELECT max(sort) as max_sort FROM $tbl_course_user
4433
            WHERE
4434
                user_id='".intval($user_id)."' AND
4435
                relation_type<>".COURSE_RELATION_TYPE_RRHH." AND
4436
                user_course_cat='".intval($user_course_category)."'";
4437
    $result_max = Database::query($sql);
4438
    if (Database::num_rows($result_max) == 1) {
4439
        $row_max = Database::fetch_array($result_max);
4440
        return $row_max['max_sort'];
4441
    }
4442
    return 0;
4443
}
4444
4445
/**
4446
 * Determines the number of plugins installed for a given location
4447
 */
4448
function api_number_of_plugins($location) {
4449
    global $_plugins;
4450
    return isset($_plugins[$location]) && is_array($_plugins[$location]) ? count($_plugins[$location]) : 0;
4451
}
4452
4453
/**
4454
 * Transforms a number of seconds in hh:mm:ss format
4455
 * @author Julian Prud'homme
4456
 * @param integer the number of seconds
4457
 * @return string the formated time
4458
 */
4459
function api_time_to_hms($seconds)
4460
{
4461
    // $seconds = -1 means that we have wrong data in the db.
4462
    if ($seconds == -1) {
4463
        return
4464
            get_lang('Unknown').
4465
            Display::return_icon(
4466
                'info2.gif',
4467
                get_lang('WrongDatasForTimeSpentOnThePlatform'),
4468
                array('align' => 'absmiddle', 'hspace' => '3px')
4469
            );
4470
    }
4471
4472
    // How many hours ?
4473
    $hours = floor($seconds / 3600);
4474
4475
    // How many minutes ?
4476
    $min = floor(($seconds - ($hours * 3600)) / 60);
4477
4478
    // How many seconds
4479
    $sec = floor($seconds - ($hours * 3600) - ($min * 60));
4480
4481
    if ($sec < 10) {
4482
        $sec = "0$sec";
4483
    }
4484
4485
    if ($min < 10) {
4486
        $min = "0$min";
4487
    }
4488
4489
    return "$hours:$min:$sec";
4490
}
4491
4492
/* FILE SYSTEM RELATED FUNCTIONS */
4493
4494
/**
4495
 * Returns the permissions to be assigned to every newly created directory by the web-server.
4496
 * The return value is based on the platform administrator's setting
4497
 * "Administration > Configuration settings > Security > Permissions for new directories".
4498
 * @return int  Returns the permissions in the format "Owner-Group-Others, Read-Write-Execute", as an integer value.
4499
 */
4500 View Code Duplication
function api_get_permissions_for_new_directories() {
4501
    static $permissions;
4502
    if (!isset($permissions)) {
4503
        $permissions = trim(api_get_setting('permissions_for_new_directories'));
4504
        // The default value 0777 is according to that in the platform administration panel after fresh system installation.
4505
        $permissions = octdec(!empty($permissions) ? $permissions : '0777');
4506
    }
4507
    return $permissions;
4508
}
4509
4510
/**
4511
 * Returns the permissions to be assigned to every newly created directory by the web-server.
4512
 * The return value is based on the platform administrator's setting
4513
 * "Administration > Configuration settings > Security > Permissions for new files".
4514
 * @return int Returns the permissions in the format
4515
 * "Owner-Group-Others, Read-Write-Execute", as an integer value.
4516
 */
4517 View Code Duplication
function api_get_permissions_for_new_files() {
4518
    static $permissions;
4519
    if (!isset($permissions)) {
4520
        $permissions = trim(api_get_setting('permissions_for_new_files'));
4521
        // The default value 0666 is according to that in the platform
4522
        // administration panel after fresh system installation.
4523
        $permissions = octdec(!empty($permissions) ? $permissions : '0666');
4524
    }
4525
    return $permissions;
4526
}
4527
4528
/**
4529
 * Deletes a file, or a folder and its contents
4530
 *
4531
 * @author      Aidan Lister <[email protected]>
4532
 * @version     1.0.3
4533
 * @param       string   $dirname    Directory to delete
4534
 * @param       bool     Deletes only the content or not
4535
 * @param       bool     $strict if one folder/file fails stop the loop
4536
 * @return      bool     Returns TRUE on success, FALSE on failure
4537
 * @link http://aidanlister.com/2004/04/recursively-deleting-a-folder-in-php/
4538
 * @author      Yannick Warnier, adaptation for the Chamilo LMS, April, 2008
4539
 * @author      Ivan Tcholakov, a sanity check about Directory class creation has been added, September, 2009
4540
 */
4541
function rmdirr($dirname, $delete_only_content_in_folder = false, $strict = false) {
4542
    $res = true;
4543
4544
    // A sanity check.
4545
    if (!file_exists($dirname)) {
4546
        return false;
4547
    }
4548
    $php_errormsg = '';
4549
    // Simple delete for a file.
4550
    if (is_file($dirname) || is_link($dirname)) {
4551
        $res = unlink($dirname);
4552 View Code Duplication
        if ($res === false) {
4553
            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);
4554
        }
4555
        return $res;
4556
    }
4557
4558
    // Loop through the folder.
4559
    $dir = dir($dirname);
4560
    // A sanity check.
4561
    $is_object_dir = is_object($dir);
4562 View Code Duplication
    if ($is_object_dir) {
4563
        while (false !== $entry = $dir->read()) {
4564
            // Skip pointers.
4565
            if ($entry == '.' || $entry == '..') {
4566
                continue;
4567
            }
4568
4569
            // Recurse.
4570
            if ($strict) {
4571
                $result = rmdirr("$dirname/$entry");
4572
                if ($result == false) {
4573
                    $res = false;
4574
                    break;
4575
                }
4576
            } else {
4577
                rmdirr("$dirname/$entry");
4578
            }
4579
        }
4580
    }
4581
4582
    // Clean up.
4583
    if ($is_object_dir) {
4584
        $dir->close();
4585
    }
4586
4587
    if ($delete_only_content_in_folder == false) {
4588
        $res = rmdir($dirname);
4589 View Code Duplication
        if ($res === false) {
4590
            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);
4591
        }
4592
    }
4593
    return $res;
4594
}
4595
4596
// TODO: This function is to be simplified. File access modes to be implemented.
4597
/**
4598
 * function adapted from a php.net comment
4599
 * copy recursively a folder
4600
 * @param the source folder
4601
 * @param the dest folder
4602
 * @param an array of excluded file_name (without extension)
4603
 * @param copied_files the returned array of copied files
4604
 * @param string $source
4605
 * @param string $dest
4606
 */
4607
function copyr($source, $dest, $exclude = array(), $copied_files = array()) {
4608
    if (empty($dest)) { return false; }
4609
    // Simple copy for a file
4610
    if (is_file($source)) {
4611
        $path_info = pathinfo($source);
4612
        if (!in_array($path_info['filename'], $exclude)) {
4613
            copy($source, $dest);
4614
        }
4615
        return true;
4616
    } elseif (!is_dir($source)) {
4617
        //then source is not a dir nor a file, return
4618
        return false;
4619
    }
4620
4621
    // Make destination directory.
4622
    if (!is_dir($dest)) {
4623
        mkdir($dest, api_get_permissions_for_new_directories());
4624
    }
4625
4626
    // Loop through the folder.
4627
    $dir = dir($source);
4628
    while (false !== $entry = $dir->read()) {
4629
        // Skip pointers
4630
        if ($entry == '.' || $entry == '..') {
4631
            continue;
4632
        }
4633
4634
        // Deep copy directories.
4635
        if ($dest !== "$source/$entry") {
4636
            $files = copyr("$source/$entry", "$dest/$entry", $exclude, $copied_files);
4637
        }
4638
    }
4639
    // Clean up.
4640
    $dir->close();
4641
    return true;
4642
}
4643
4644
// TODO: Using DIRECTORY_SEPARATOR is not recommended, this is an obsolete approach. Documentation header to be added here.
4645
/**
4646
 * @param string $pathname
4647
 * @param string $base_path_document
4648
 * @param integer $session_id
4649
 */
4650
function copy_folder_course_session(
4651
    $pathname,
4652
    $base_path_document,
4653
    $session_id,
4654
    $course_info,
4655
    $document,
4656
    $source_course_id
4657
) {
4658
    $table = Database :: get_course_table(TABLE_DOCUMENT);
4659
    $session_id = intval($session_id);
4660
    $source_course_id = intval($source_course_id);
4661
4662
    // Check whether directory already exists.
4663
    if (is_dir($pathname) || empty($pathname)) {
4664
        return true;
4665
    }
4666
4667
    // Ensure that a file with the same name does not already exist.
4668
    if (is_file($pathname)) {
4669
        trigger_error('copy_folder_course_session(): File exists', E_USER_WARNING);
4670
        return false;
4671
    }
4672
4673
    $course_id = $course_info['real_id'];
4674
4675
    $folders = explode(DIRECTORY_SEPARATOR,str_replace($base_path_document.DIRECTORY_SEPARATOR,'',$pathname));
4676
4677
    $new_pathname = $base_path_document;
4678
    $path = '';
4679
4680
    foreach ($folders as $folder) {
4681
        $new_pathname .= DIRECTORY_SEPARATOR.$folder;
4682
        $path .= DIRECTORY_SEPARATOR.$folder;
4683
4684
        if (!file_exists($new_pathname)) {
4685
            $path = Database::escape_string($path);
4686
4687
            $sql = "SELECT * FROM $table
4688
                    WHERE
4689
                        c_id = $source_course_id AND
4690
                        path = '$path' AND
4691
                        filetype = 'folder' AND
4692
                        session_id = '$session_id'";
4693
            $rs1  = Database::query($sql);
4694
            $num_rows = Database::num_rows($rs1);
4695
4696
            if ($num_rows == 0) {
4697
                mkdir($new_pathname, api_get_permissions_for_new_directories());
4698
4699
                // Insert new folder with destination session_id.
4700
                $params = [
4701
                    'c_id' => $course_id,
4702
                    'path' => $path,
4703
                    'comment' => $document->comment,
4704
                    'title' => basename($new_pathname),
4705
                    'filetype' => 'folder',
4706
                    'size' => '0',
4707
                    'session_id' => $session_id
4708
                ];
4709
                $document_id = Database::insert($table, $params);
4710 View Code Duplication
                if ($document_id) {
4711
4712
                    $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
4713
                    Database::query($sql);
4714
4715
                    api_item_property_update(
4716
                        $course_info,
4717
                        TOOL_DOCUMENT,
4718
                        $document_id,
4719
                        'FolderCreated',
4720
                        api_get_user_id(),
4721
                        0,
4722
                        0,
4723
                        null,
4724
                        null,
4725
                        $session_id
4726
                    );
4727
                }
4728
            }
4729
        }
4730
4731
    } // en foreach
4732
}
4733
4734
// TODO: chmodr() is a better name. Some corrections are needed. Documentation header to be added here.
4735
/**
4736
 * @param string $path
4737
 */
4738
function api_chmod_R($path, $filemode) {
4739
    if (!is_dir($path)) {
4740
        return chmod($path, $filemode);
4741
    }
4742
4743
    $handler = opendir($path);
4744
    while ($file = readdir($handler)) {
4745
        if ($file != '.' && $file != '..') {
4746
            $fullpath = "$path/$file";
4747
            if (!is_dir($fullpath)) {
4748
                if (!chmod($fullpath, $filemode)) {
4749
                    return false;
4750
                }
4751
            } else {
4752
                if (!api_chmod_R($fullpath, $filemode)) {
4753
                    return false;
4754
                }
4755
            }
4756
        }
4757
    }
4758
4759
    closedir($handler);
4760
    return chmod($path, $filemode);
4761
}
4762
4763
4764
// TODO: Where the following function has been copy/pased from? There is no information about author and license. Style, coding conventions...
4765
/**
4766
 * Parse info file format. (e.g: file.info)
4767
 *
4768
 * Files should use an ini-like format to specify values.
4769
 * White-space generally doesn't matter, except inside values.
4770
 * e.g.
4771
 *
4772
 * @verbatim
4773
 *   key = value
4774
 *   key = "value"
4775
 *   key = 'value'
4776
 *   key = "multi-line
4777
 *
4778
 *   value"
4779
 *   key = 'multi-line
4780
 *
4781
 *   value'
4782
 *   key
4783
 *   =
4784
 *   'value'
4785
 * @endverbatim
4786
 *
4787
 * Arrays are created using a GET-like syntax:
4788
 *
4789
 * @verbatim
4790
 *   key[] = "numeric array"
4791
 *   key[index] = "associative array"
4792
 *   key[index][] = "nested numeric array"
4793
 *   key[index][index] = "nested associative array"
4794
 * @endverbatim
4795
 *
4796
 * PHP constants are substituted in, but only when used as the entire value:
4797
 *
4798
 * Comments should start with a semi-colon at the beginning of a line.
4799
 *
4800
 * This function is NOT for placing arbitrary module-specific settings. Use
4801
 * variable_get() and variable_set() for that.
4802
 *
4803
 * Information stored in the module.info file:
4804
 * - name: The real name of the module for display purposes.
4805
 * - description: A brief description of the module.
4806
 * - dependencies: An array of shortnames of other modules this module depends on.
4807
 * - package: The name of the package of modules this module belongs to.
4808
 *
4809
 * Example of .info file:
4810
 * <code>
4811
 * @verbatim
4812
 *   name = Forum
4813
 *   description = Enables threaded discussions about general topics.
4814
 *   dependencies[] = taxonomy
4815
 *   dependencies[] = comment
4816
 *   package = Core - optional
4817
 *   version = VERSION
4818
 * @endverbatim
4819
 * </code>
4820
 * @param string $filename
4821
 *   The file we are parsing. Accepts file with relative or absolute path.
4822
 * @return
4823
 *   The info array.
4824
 */
4825
function api_parse_info_file($filename) {
4826
    $info = array();
4827
4828
    if (!file_exists($filename)) {
4829
        return $info;
4830
    }
4831
4832
    $data = file_get_contents($filename);
4833
    if (preg_match_all('
4834
        @^\s*                           # Start at the beginning of a line, ignoring leading whitespace
4835
        ((?:
4836
          [^=;\[\]]|                    # Key names cannot contain equal signs, semi-colons or square brackets,
4837
          \[[^\[\]]*\]                  # unless they are balanced and not nested
4838
        )+?)
4839
        \s*=\s*                         # Key/value pairs are separated by equal signs (ignoring white-space)
4840
        (?:
4841
          ("(?:[^"]|(?<=\\\\)")*")|     # Double-quoted string, which may contain slash-escaped quotes/slashes
4842
          (\'(?:[^\']|(?<=\\\\)\')*\')| # Single-quoted string, which may contain slash-escaped quotes/slashes
4843
          ([^\r\n]*?)                   # Non-quoted string
4844
        )\s*$                           # Stop at the next end of a line, ignoring trailing whitespace
4845
        @msx', $data, $matches, PREG_SET_ORDER)) {
4846
        $key = $value1 = $value2 = $value3 = '';
4847
        foreach ($matches as $match) {
4848
            // Fetch the key and value string.
4849
            $i = 0;
4850
            foreach (array('key', 'value1', 'value2', 'value3') as $var) {
4851
                $$var = isset($match[++$i]) ? $match[$i] : '';
4852
            }
4853
            $value = stripslashes(substr($value1, 1, -1)) . stripslashes(substr($value2, 1, -1)) . $value3;
4854
4855
            // Parse array syntax.
4856
            $keys = preg_split('/\]?\[/', rtrim($key, ']'));
4857
            $last = array_pop($keys);
4858
            $parent = &$info;
4859
4860
            // Create nested arrays.
4861
            foreach ($keys as $key) {
4862
                if ($key == '') {
4863
                    $key = count($parent);
4864
                }
4865
                if (!isset($parent[$key]) || !is_array($parent[$key])) {
4866
                    $parent[$key] = array();
4867
                }
4868
                $parent = &$parent[$key];
4869
            }
4870
4871
            // Handle PHP constants.
4872
            if (defined($value)) {
4873
                $value = constant($value);
4874
            }
4875
4876
            // Insert actual value.
4877
            if ($last == '') {
4878
                $last = count($parent);
4879
            }
4880
            $parent[$last] = $value;
4881
        }
4882
    }
4883
    return $info;
4884
}
4885
4886
/**
4887
 * Gets Chamilo version from the configuration files
4888
 * @return string   A string of type "1.8.4", or an empty string if the version could not be found
4889
 */
4890
function api_get_version()
4891
{
4892
    return (string) api_get_configuration_value('system_version');
4893
}
4894
4895
/**
4896
 * Gets the software name (the name/brand of the Chamilo-based customized system)
4897
 * @return string
4898
 */
4899
function api_get_software_name() {
4900
    $name = api_get_configuration_value('software_name');
4901
    if (!empty($name)) {
4902
        return $name;
4903
    } else {
4904
        return 'Chamilo';
4905
    }
4906
}
4907
4908
/**
4909
 * Checks whether status given in parameter exists in the platform
4910
 * @param mixed the status (can be either int either string)
4911
 * @return boolean if the status exists, else returns false
4912
 */
4913
function api_status_exists($status_asked) {
4914
    global $_status_list;
4915
    return in_array($status_asked, $_status_list) ? true : isset($_status_list[$status_asked]);
4916
}
4917
4918
/**
4919
 * Checks whether status given in parameter exists in the platform. The function
4920
 * returns the status ID or false if it does not exist, but given the fact there
4921
 * is no "0" status, the return value can be checked against
4922
 * if(api_status_key()) to know if it exists.
4923
 * @param   mixed   The status (can be either int or string)
4924
 * @return  mixed   Status ID if exists, false otherwise
4925
 */
4926
function api_status_key($status) {
4927
    global $_status_list;
4928
    return isset($_status_list[$status]) ? $status : array_search($status, $_status_list);
4929
}
4930
4931
/**
4932
 * Gets the status langvars list
4933
 * @return string[] the list of status with their translations
4934
 */
4935
function api_get_status_langvars() {
4936
    return array(
4937
        COURSEMANAGER   => get_lang('Teacher', ''),
4938
        SESSIONADMIN    => get_lang('SessionsAdmin', ''),
4939
        DRH             => get_lang('Drh', ''),
4940
        STUDENT         => get_lang('Student', ''),
4941
        ANONYMOUS       => get_lang('Anonymous', ''),
4942
        STUDENT_BOSS    => get_lang('RoleStudentBoss', ''),
4943
        INVITEE         => get_lang('Invited'),
4944
    );
4945
}
4946
4947
/**
4948
* The function that retrieves all the possible settings for a certain config setting
4949
* @author Patrick Cool <[email protected]>, Ghent University
4950
*/
4951 View Code Duplication
function api_get_settings_options($var) {
4952
    $table_settings_options = Database :: get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
4953
    $var = Database::escape_string($var);
4954
    $sql = "SELECT * FROM $table_settings_options
4955
            WHERE variable = '$var'
4956
            ORDER BY id";
4957
    $result = Database::query($sql);
4958
    $settings_options_array = array();
4959
    while ($row = Database::fetch_array($result, 'ASSOC')) {
4960
        $settings_options_array[] = $row;
4961
    }
4962
    return $settings_options_array;
4963
}
4964
4965
/**
4966
 * @param array $params
4967
 */
4968
function api_set_setting_option($params) {
4969
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
4970 View Code Duplication
    if (empty($params['id'])) {
4971
        Database::insert($table, $params);
4972
    } else {
4973
        Database::update($table, $params, array('id = ? '=> $params['id']));
4974
    }
4975
}
4976
4977
/**
4978
 * @param array $params
4979
 */
4980
function api_set_setting_simple($params) {
4981
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
4982
    $url_id = api_get_current_access_url_id();
4983
4984 View Code Duplication
    if (empty($params['id'])) {
4985
        $params['access_url'] = $url_id;
4986
        Database::insert($table, $params);
4987
    } else {
4988
        Database::update($table, $params, array('id = ? '=> array($params['id'])));
4989
    }
4990
}
4991
4992
/**
4993
 * @param int $id
4994
 */
4995
function api_delete_setting_option($id) {
4996
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
4997
    if (!empty($id)) {
4998
        Database::delete($table, array('id = ? '=> $id));
4999
    }
5000
}
5001
5002
/**
5003
 * Sets a platform configuration setting to a given value
5004
 * @param string    The variable we want to update
5005
 * @param string    The value we want to record
5006
 * @param string    The sub-variable if any (in most cases, this will remain null)
5007
 * @param string    The category if any (in most cases, this will remain null)
5008
 * @param int       The access_url for which this parameter is valid
5009
 * @param string $cat
5010
 */
5011
function api_set_setting($var, $value, $subvar = null, $cat = null, $access_url = 1)
5012
{
5013
    if (empty($var)) {
5014
        return false;
5015
    }
5016
    $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5017
    $var = Database::escape_string($var);
5018
    $value = Database::escape_string($value);
5019
    $access_url = (int)$access_url;
5020
    if (empty($access_url)) { $access_url = 1; }
5021
    $select = "SELECT id FROM $t_settings WHERE variable = '$var' ";
5022
    if (!empty($subvar)) {
5023
        $subvar = Database::escape_string($subvar);
5024
        $select .= " AND subkey = '$subvar'";
5025
    }
5026
    if (!empty($cat)) {
5027
        $cat = Database::escape_string($cat);
5028
        $select .= " AND category = '$cat'";
5029
    }
5030
    if ($access_url > 1) {
5031
        $select .= " AND access_url = $access_url";
5032
    } else {
5033
        $select .= " AND access_url = 1 ";
5034
    }
5035
    $res = Database::query($select);
5036
    if (Database::num_rows($res) > 0) {
5037
        // Found item for this access_url.
5038
        $row = Database::fetch_array($res);
5039
        $sql = "UPDATE $t_settings SET selected_value = '$value'
5040
                WHERE id = ".$row['id'];
5041
        Database::query($sql);
5042
    } else {
5043
        // Item not found for this access_url, we have to check if it exist with access_url = 1
5044
        $select = "SELECT * FROM $t_settings
5045
                   WHERE variable = '$var' AND access_url = 1 ";
5046
        // Just in case
5047
        if ($access_url == 1) {
5048
            if (!empty($subvar)) {
5049
                $select .= " AND subkey = '$subvar'";
5050
            }
5051
            if (!empty($cat)) {
5052
                $select .= " AND category = '$cat'";
5053
            }
5054
            $res = Database::query($select);
5055
            if (Database::num_rows($res) > 0) {
5056
                // We have a setting for access_url 1, but none for the current one, so create one.
5057
                $row = Database::fetch_array($res);
5058
                $insert = "INSERT INTO $t_settings (variable, subkey, type,category, selected_value, title, comment, scope, subkeytext, access_url)
5059
                        VALUES
5060
                        ('".$row['variable']."',".(!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL")."," .
5061
                        "'".$row['type']."','".$row['category']."'," .
5062
                        "'$value','".$row['title']."'," .
5063
                        "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".(!empty($row['scope']) ? "'".$row['scope']."'" : "NULL")."," .
5064
                        "".(!empty($row['subkeytext'])?"'".$row['subkeytext']."'":"NULL").",$access_url)";
5065
                Database::query($insert);
5066
            } else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

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

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
5067
                // Such a setting does not exist.
5068
                //error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all', 0);
5069
            }
5070
        } else {
5071
            // Other access url.
5072
            if (!empty($subvar)) {
5073
                $select .= " AND subkey = '$subvar'";
5074
            }
5075
            if (!empty($cat)) {
5076
                $select .= " AND category = '$cat'";
5077
            }
5078
            $res = Database::query($select);
5079
5080
            if (Database::num_rows($res) > 0) {
5081
                // We have a setting for access_url 1, but none for the current one, so create one.
5082
                $row = Database::fetch_array($res);
5083
                if ($row['access_url_changeable'] == 1) {
5084
                    $insert = "INSERT INTO $t_settings (variable,subkey, type,category, selected_value,title, comment,scope, subkeytext,access_url, access_url_changeable) VALUES
5085
                            ('".$row['variable']."',".
5086
                            (!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL")."," .
5087
                            "'".$row['type']."','".$row['category']."'," .
5088
                            "'$value','".$row['title']."'," .
5089
                            "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".
5090
                            (!empty($row['scope']) ? "'".$row['scope']."'" : "NULL")."," .
5091
                            "".(!empty($row['subkeytext']) ? "'".$row['subkeytext']."'" : "NULL").",$access_url,".$row['access_url_changeable'].")";
5092
                    Database::query($insert);
5093
                }
5094
            } else { // Such a setting does not exist.
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

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

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
5095
                //error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all. The access_url is: '.$access_url.' ',0);
5096
            }
5097
        }
5098
    }
5099
}
5100
5101
/**
5102
 * Sets a whole category of settings to one specific value
5103
 * @param string    Category
5104
 * @param string    Value
5105
 * @param int       Access URL. Optional. Defaults to 1
5106
 * @param array     Optional array of filters on field type
5107
 * @param string $category
5108
 * @param string $value
5109
 */
5110
function api_set_settings_category($category, $value = null, $access_url = 1, $fieldtype = array())
5111
{
5112
    if (empty($category)) {
5113
        return false;
5114
    }
5115
    $category = Database::escape_string($category);
5116
    $t_s = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5117
    $access_url = (int) $access_url;
5118
    if (empty($access_url)) { $access_url = 1; }
5119
    if (isset($value)) {
5120
        $value = Database::escape_string($value);
5121
        $sql = "UPDATE $t_s SET selected_value = '$value'
5122
                WHERE category = '$category' AND access_url = $access_url";
5123 View Code Duplication
        if (is_array($fieldtype) && count($fieldtype)>0) {
5124
            $sql .= " AND ( ";
5125
            $i = 0;
5126
            foreach ($fieldtype as $type){
5127
                if ($i > 0) {
5128
                    $sql .= ' OR ';
5129
                }
5130
                $type = Database::escape_string($type);
5131
                $sql .= " type='".$type."' ";
5132
                $i++;
5133
            }
5134
            $sql .= ")";
5135
        }
5136
        $res = Database::query($sql);
5137
        return $res !== false;
5138
    } else {
5139
        $sql = "UPDATE $t_s SET selected_value = NULL
5140
                WHERE category = '$category' AND access_url = $access_url";
5141 View Code Duplication
        if (is_array($fieldtype) && count($fieldtype)>0) {
5142
            $sql .= " AND ( ";
5143
            $i = 0;
5144
            foreach ($fieldtype as $type){
5145
                if ($i > 0) {
5146
                    $sql .= ' OR ';
5147
                }
5148
                $type = Database::escape_string($type);
5149
                $sql .= " type='".$type."' ";
5150
                $i++;
5151
            }
5152
            $sql .= ")";
5153
        }
5154
        $res = Database::query($sql);
5155
        return $res !== false;
5156
    }
5157
}
5158
5159
/**
5160
 * Gets all available access urls in an array (as in the database)
5161
 * @return array    An array of database records
5162
 */
5163
function api_get_access_urls($from = 0, $to = 1000000, $order = 'url', $direction = 'ASC')
5164
{
5165
    $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5166
    $from = (int) $from;
5167
    $to = (int) $to;
5168
    $order = Database::escape_string($order, null, false);
5169
    $direction = Database::escape_string($direction, null, false);
5170
    $sql = "SELECT id, url, description, active, created_by, tms
5171
            FROM $table
5172
            ORDER BY $order $direction
5173
            LIMIT $to OFFSET $from";
5174
    $res = Database::query($sql);
5175
    return Database::store_result($res);
5176
}
5177
5178
/**
5179
 * Gets the access url info in an array
5180
 * @param int $id Id of the access url
5181
 * @param bool $returnDefault Set to false if you want the real URL if URL 1 is still 'http://localhost/'
5182
 * @return array All the info (url, description, active, created_by, tms)
5183
 * from the access_url table
5184
 * @author Julio Montoya
5185
 */
5186
function api_get_access_url($id, $returnDefault = true)
5187
{
5188
    static $staticResult;
5189
    $id = intval($id);
5190
5191
    if (isset($staticResult[$id])) {
5192
        $result = $staticResult[$id];
5193
    } else {
5194
        // Calling the Database:: library dont work this is handmade.
5195
        $table_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5196
        $sql = "SELECT url, description, active, created_by, tms
5197
                FROM $table_access_url WHERE id = '$id' ";
5198
        $res = Database::query($sql);
5199
        $result = @Database::fetch_array($res);
5200
        $staticResult[$id] = $result;
5201
    }
5202
5203
    // If the result url is 'http://localhost/' (the default) and the root_web
5204
    // (=current url) is different, and the $id is = 1 (which might mean
5205
    // api_get_current_access_url_id() returned 1 by default), then return the
5206
    // root_web setting instead of the current URL
5207
    // This is provided as an option to avoid breaking the storage of URL-specific
5208
    // homepages in home/localhost/
5209
    if ($id === 1 && $returnDefault === false) {
5210
        $currentUrl = api_get_current_access_url_id();
5211
        // only do this if we are on the main URL (=1), otherwise we could get
5212
        // information on another URL instead of the one asked as parameter
5213
        if ($currentUrl === 1) {
5214
            $rootWeb = api_get_path(WEB_PATH);
5215
            $default = 'http://localhost/';
5216
            if ($result['url'] === $default && $rootWeb != $default) {
5217
                $result['url'] = $rootWeb;
5218
            }
5219
        }
5220
    }
5221
5222
    return $result;
5223
}
5224
5225
/**
5226
 * Gets all the current settings for a specific access url
5227
 * @param string    The category, if any, that we want to get
5228
 * @param string    Whether we want a simple list (display a category) or
5229
 * a grouped list (group by variable as in settings.php default). Values: 'list' or 'group'
5230
 * @param int       Access URL's ID. Optional. Uses 1 by default, which is the unique URL
5231
 * @return array    Array of database results for the current settings of the current access URL
5232
 */
5233
function &api_get_settings($cat = null, $ordering = 'list', $access_url = 1, $url_changeable = 0)
5234
{
5235
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5236
    $access_url = (int) $access_url;
5237
    $where_condition = '';
5238
    if ($url_changeable == 1) {
5239
        $where_condition = " AND access_url_changeable= '1' ";
5240
    }
5241
    if (empty($access_url) || $access_url == -1) {
5242
        $access_url = 1;
5243
    }
5244
    $sql = "SELECT * FROM $table
5245
            WHERE access_url = $access_url  $where_condition ";
5246
5247
    if (!empty($cat)) {
5248
        $cat = Database::escape_string($cat);
5249
        $sql .= " AND category='$cat' ";
5250
    }
5251
    if ($ordering == 'group') {
5252
        $sql .= " ORDER BY id ASC";
5253
    } else {
5254
        $sql .= " ORDER BY 1,2 ASC";
5255
    }
5256
    $result = Database::query($sql);
5257
    $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...
5258
5259
    return $result;
5260
}
5261
5262
/**
5263
 * Sets a platform configuration setting to a given value
5264
 * @param string    The value we want to record
5265
 * @param string    The variable name we want to insert
5266
 * @param string    The subkey for the variable we want to insert
5267
 * @param string    The type for the variable we want to insert
5268
 * @param string    The category for the variable we want to insert
5269
 * @param string    The title
5270
 * @param string    The comment
5271
 * @param string    The scope
5272
 * @param string    The subkey text
5273
 * @param int       The access_url for which this parameter is valid
5274
 * @param int       The changeability of this setting for non-master urls
5275
 * @param string $val
5276
 * @param string $var
5277
 * @param string $sk
5278
 * @param string $c
5279
 * @return boolean  true on success, false on failure
5280
 */
5281
function api_add_setting(
5282
    $val,
5283
    $var,
5284
    $sk = null,
5285
    $type = 'textfield',
5286
    $c = null,
5287
    $title = '',
5288
    $com = '',
5289
    $sc = null,
5290
    $skt = null,
5291
    $a = 1,
5292
    $v = 0
5293
) {
5294
    if (empty($var) || !isset($val)) { return false; }
5295
    $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5296
    $var = Database::escape_string($var);
5297
    $val = Database::escape_string($val);
5298
    $a = (int) $a;
5299
    if (empty($a)) { $a = 1; }
5300
    // Check if this variable doesn't exist already
5301
    $select = "SELECT id FROM $t_settings WHERE variable = '$var' ";
5302
    if (!empty($sk)) {
5303
        $sk = Database::escape_string($sk);
5304
        $select .= " AND subkey = '$sk'";
5305
    }
5306
    if ($a > 1) {
5307
        $select .= " AND access_url = $a";
5308
    } else {
5309
        $select .= " AND access_url = 1 ";
5310
    }
5311
    $res = Database::query($select);
5312
    if (Database::num_rows($res) > 0) { // Found item for this access_url.
5313
        $row = Database::fetch_array($res);
5314
        Database::update(
5315
            $t_settings,
5316
            array('selected_value' => $val),
5317
            array('id = ?' => array($row['id']))
5318
        );
5319
        return $row['id'];
5320
    }
5321
5322
    // Item not found for this access_url, we have to check if the whole thing is missing
5323
    // (in which case we ignore the insert) or if there *is* a record but just for access_url = 1
5324
    $insert = "INSERT INTO $t_settings " .
5325
                "(variable,selected_value," .
5326
                "type,category," .
5327
                "subkey,title," .
5328
                "comment,scope," .
5329
                "subkeytext,access_url,access_url_changeable)" .
5330
                " VALUES ('$var','$val',";
5331
    if (isset($type)) {
5332
        $type = Database::escape_string($type);
5333
        $insert .= "'$type',";
5334
    } else {
5335
        $insert .= "NULL,";
5336
    }
5337
    if (isset($c)) { // Category
5338
        $c = Database::escape_string($c);
5339
        $insert .= "'$c',";
5340
    } else {
5341
        $insert .= "NULL,";
5342
    }
5343
    if (isset($sk)) { // Subkey
5344
        $sk = Database::escape_string($sk);
5345
        $insert .= "'$sk',";
5346
    } else {
5347
        $insert .= "NULL,";
5348
    }
5349
    if (isset($title)) { // Title
5350
        $title = Database::escape_string($title);
5351
        $insert .= "'$title',";
5352
    } else {
5353
        $insert .= "NULL,";
5354
    }
5355
    if (isset($com)) { // Comment
5356
        $com = Database::escape_string($com);
5357
        $insert .= "'$com',";
5358
    } else {
5359
        $insert .= "NULL,";
5360
    }
5361
    if (isset($sc)) { // Scope
5362
        $sc = Database::escape_string($sc);
5363
        $insert .= "'$sc',";
5364
    } else {
5365
        $insert .= "NULL,";
5366
    }
5367
    if (isset($skt)) { // Subkey text
5368
        $skt = Database::escape_string($skt);
5369
        $insert .= "'$skt',";
5370
    } else {
5371
        $insert .= "NULL,";
5372
    }
5373
    $insert .= "$a,$v)";
5374
    $res = Database::query($insert);
5375
    return $res;
5376
}
5377
5378
/**
5379
 * Checks wether a user can or can't view the contents of a course.
5380
 * @deprecated use CourseManager::is_user_subscribed_in_course
5381
 * @param   int $userid     User id or NULL to get it from $_SESSION
5382
 * @param   int $cid        Course id to check whether the user is allowed.
5383
 * @return  bool
5384
 */
5385
function api_is_course_visible_for_user($userid = null, $cid = null) {
5386
    if ($userid === null) {
5387
        $userid = api_get_user_id();
5388
    }
5389
    if (empty($userid) || strval(intval($userid)) != $userid) {
5390
        if (api_is_anonymous()) {
5391
            $userid = api_get_anonymous_id();
5392
        } else {
5393
            return false;
5394
        }
5395
    }
5396
    $cid = Database::escape_string($cid);
5397
5398
    $courseInfo = api_get_course_info($cid);
5399
    $courseId = $courseInfo['real_id'];
5400
5401
    global $is_platformAdmin;
5402
5403
    $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
5404
    $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
5405
5406
    $sql = "SELECT
5407
                $course_table.category_code,
5408
                $course_table.visibility,
5409
                $course_table.code,
5410
                $course_cat_table.code
5411
            FROM $course_table
5412
            LEFT JOIN $course_cat_table
5413
                ON $course_table.category_code = $course_cat_table.code
5414
            WHERE
5415
                $course_table.code = '$cid'
5416
            LIMIT 1";
5417
5418
    $result = Database::query($sql);
5419
5420
    if (Database::num_rows($result) > 0) {
5421
        $visibility = Database::fetch_array($result);
5422
        $visibility = $visibility['visibility'];
5423
    } else {
5424
        $visibility = 0;
5425
    }
5426
    // Shortcut permissions in case the visibility is "open to the world".
5427
    if ($visibility === COURSE_VISIBILITY_OPEN_WORLD) {
5428
        return true;
5429
    }
5430
5431
    $tbl_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
5432
5433
    $sql = "SELECT
5434
                is_tutor, status
5435
            FROM $tbl_course_user
5436
            WHERE
5437
                user_id  = '$userid' AND
5438
                relation_type <> '".COURSE_RELATION_TYPE_RRHH."' AND
5439
                c_id = $courseId
5440
            LIMIT 1";
5441
5442
    $result = Database::query($sql);
5443
5444
    if (Database::num_rows($result) > 0) {
5445
        // This user has got a recorded state for this course.
5446
        $cuData = Database::fetch_array($result);
5447
        $is_courseMember = true;
5448
        $is_courseTutor = ($cuData['is_tutor'] == 1);
5449
        $is_courseAdmin = ($cuData['status'] == 1);
5450
    }
5451
5452
    if (!$is_courseAdmin) {
5453
        // This user has no status related to this course.
5454
        // Is it the session coach or the session admin?
5455
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
5456
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
5457
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
5458
5459
        $sql = "SELECT
5460
                    session.id_coach, session_admin_id, session.id
5461
                FROM
5462
                    $tbl_session as session
5463
                INNER JOIN $tbl_session_course
5464
                    ON session_rel_course.session_id = session.id
5465
                    AND session_rel_course.c_id = '$courseId'
5466
                LIMIT 1";
5467
5468
        $result = Database::query($sql);
5469
        $row = Database::store_result($result);
5470
5471
        if ($row[0]['id_coach'] == $userid) {
5472
            $is_courseMember = true;
5473
            $is_courseTutor = true;
5474
            $is_courseAdmin = false;
5475
            $is_courseCoach = true;
5476
            $is_sessionAdmin = false;
5477
        }
5478
        elseif ($row[0]['session_admin_id'] == $userid) {
5479
            $is_courseMember = false;
5480
            $is_courseTutor = false;
5481
            $is_courseAdmin = false;
5482
            $is_courseCoach = false;
5483
            $is_sessionAdmin = true;
5484
        } else {
5485
            // Check if the current user is the course coach.
5486
            $sql = "SELECT 1
5487
                    FROM $tbl_session_course
5488
                    WHERE session_rel_course.c_id = '$courseId'
5489
                    AND session_rel_course.id_coach = '$userid'
5490
                    LIMIT 1";
5491
5492
            $result = Database::query($sql);
5493
5494
            //if ($row = Database::fetch_array($result)) {
5495
            if (Database::num_rows($result) > 0 ) {
5496
                $is_courseMember = true;
5497
                $is_courseTutor = true;
5498
                $is_courseCoach = true;
5499
                $is_sessionAdmin = false;
5500
5501
                $tbl_user = Database :: get_main_table(TABLE_MAIN_USER);
5502
5503
                $sql = "SELECT status FROM $tbl_user
5504
                        WHERE user_id = $userid
5505
                        LIMIT 1";
5506
5507
                $result = Database::query($sql);
5508
5509
                if (Database::result($result, 0, 0) == 1) {
5510
                    $is_courseAdmin = true;
5511
                } else {
5512
                    $is_courseAdmin = false;
5513
                }
5514
            } else {
5515
                // Check if the user is a student is this session.
5516
                $sql = "SELECT  id
5517
                        FROM $tbl_session_course_user
5518
                        WHERE
5519
                            user_id  = '$userid' AND
5520
                            c_id = '$courseId'
5521
                        LIMIT 1";
5522
5523
                if (Database::num_rows($result) > 0) {
5524
                    // This user haa got a recorded state for this course.
5525
                    while ($row = Database::fetch_array($result)) {
5526
                        $is_courseMember = true;
5527
                        $is_courseTutor = false;
5528
                        $is_courseAdmin = false;
5529
                        $is_sessionAdmin = false;
5530
                    }
5531
                }
5532
            }
5533
        }
5534
    }
5535
5536
    switch ($visibility) {
5537
        case COURSE_VISIBILITY_OPEN_WORLD:
5538
            return true;
5539
        case COURSE_VISIBILITY_OPEN_PLATFORM:
5540
            return isset($userid);
5541
        case COURSE_VISIBILITY_REGISTERED:
5542
        case COURSE_VISIBILITY_CLOSED:
5543
            return $is_platformAdmin || $is_courseMember || $is_courseAdmin;
5544
        case COURSE_VISIBILITY_HIDDEN:
5545
            return $is_platformAdmin;
5546
    }
5547
5548
    return false;
5549
}
5550
5551
/**
5552
 * Returns whether an element (forum, message, survey ...) belongs to a session or not
5553
 * @param String the tool of the element
5554
 * @param int the element id in database
5555
 * @param int the session_id to compare with element session id
5556
 * @param string $tool
5557
 * @return boolean true if the element is in the session, false else
5558
 */
5559
function api_is_element_in_the_session($tool, $element_id, $session_id = null) {
5560
    if (is_null($session_id)) {
5561
        $session_id = api_get_session_id();
5562
    }
5563
5564
    // Get information to build query depending of the tool.
5565
    switch ($tool) {
5566
        case TOOL_SURVEY :
5567
            $table_tool = Database::get_course_table(TABLE_SURVEY);
5568
            $key_field = 'survey_id';
5569
            break;
5570
        case TOOL_ANNOUNCEMENT :
5571
            $table_tool = Database::get_course_table(TABLE_ANNOUNCEMENT);
5572
            $key_field = 'id';
5573
            break;
5574
        case TOOL_AGENDA :
5575
            $table_tool = Database::get_course_table(TABLE_AGENDA);
5576
            $key_field = 'id';
5577
            break;
5578
        case TOOL_GROUP :
5579
            $table_tool = Database::get_course_table(TABLE_GROUP);
5580
            $key_field = 'id';
5581
            break;
5582
        default:
5583
            return false;
5584
    }
5585
    $course_id = api_get_course_int_id();
5586
5587
    $sql = "SELECT session_id FROM $table_tool 
5588
            WHERE c_id = $course_id AND $key_field =  ".intval($element_id);
5589
    $rs = Database::query($sql);
5590
    if ($element_session_id = Database::result($rs, 0, 0)) {
5591
        if ($element_session_id == intval($session_id)) {
5592
            // The element belongs to the session.
5593
            return true;
5594
        }
5595
    }
5596
    return false;
5597
}
5598
5599
/**
5600
 * Replaces "forbidden" characters in a filename string.
5601
 *
5602
 * @param string $filename
5603
 * @param bool $treat_spaces_as_hyphens
5604
 *
5605
 * @return string
5606
 */
5607
function api_replace_dangerous_char($filename, $treat_spaces_as_hyphens = true)
5608
{
5609
    return URLify::filter(
5610
        $filename,
5611
        250,
5612
        '',
5613
        true,
5614
        true,
5615
        false,
5616
        false,
5617
        $treat_spaces_as_hyphens
5618
    );
5619
}
5620
5621
/**
5622
 * Fixes the $_SERVER['REQUEST_URI'] that is empty in IIS6.
5623
 * @author Ivan Tcholakov, 28-JUN-2006.
5624
 */
5625
function api_request_uri() {
5626
    if (!empty($_SERVER['REQUEST_URI'])) {
5627
        return $_SERVER['REQUEST_URI'];
5628
    }
5629
    $uri = $_SERVER['SCRIPT_NAME'];
5630
    if (!empty($_SERVER['QUERY_STRING'])) {
5631
        $uri .= '?'.$_SERVER['QUERY_STRING'];
5632
    }
5633
    $_SERVER['REQUEST_URI'] = $uri;
5634
    return $uri;
5635
}
5636
5637
5638
/** Gets the current access_url id of the Chamilo Platform
5639
 * @author Julio Montoya <[email protected]>
5640
 * @return int access_url_id of the current Chamilo Installation
5641
 */
5642
function api_get_current_access_url_id() {
5643
    $access_url_table = Database :: get_main_table(TABLE_MAIN_ACCESS_URL);
5644
    $path = Database::escape_string(api_get_path(WEB_PATH));
5645
    $sql = "SELECT id FROM $access_url_table WHERE url = '".$path."'";
5646
    $result = Database::query($sql);
5647
    if (Database::num_rows($result) > 0) {
5648
        $access_url_id = Database::result($result, 0, 0);
5649
        return $access_url_id;
5650
    }
5651
    //if the url in WEB_PATH was not found, it can only mean that there is
5652
    // either a configuration problem or the first URL has not been defined yet
5653
    // (by default it is http://localhost/). Thus the more sensible thing we can
5654
    // do is return 1 (the main URL) as the user cannot hack this value anyway
5655
    return 1;
5656
}
5657
5658
/**
5659
 * Gets the registered urls from a given user id
5660
 * @author Julio Montoya <[email protected]>
5661
 * @return int user id
5662
 */
5663
function api_get_access_url_from_user($user_id) {
5664
    $user_id = intval($user_id);
5665
    $table_url_rel_user = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
5666
    $table_url          = Database :: get_main_table(TABLE_MAIN_ACCESS_URL);
5667
    $sql = "SELECT access_url_id
5668
            FROM $table_url_rel_user url_rel_user
5669
            INNER JOIN $table_url u
5670
            ON (url_rel_user.access_url_id = u.id)
5671
            WHERE user_id = ".intval($user_id);
5672
    $result = Database::query($sql);
5673
    $list = array();
5674
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5675
        $list[] = $row['access_url_id'];
5676
    }
5677
    return $list;
5678
}
5679
5680
/**
5681
 * Gets the status of a user in a course
5682
 * @param int       $user_id
5683
 * @param int    $courseId
5684
 * @return int      user status
5685
 */
5686
function api_get_status_of_user_in_course($user_id, $courseId)
5687
{
5688
    $tbl_rel_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
5689
    if (!empty($user_id) && !empty($courseId)) {
5690
        $user_id = intval($user_id);
5691
        $courseId = intval($courseId);
5692
        $sql = 'SELECT status
5693
                FROM '.$tbl_rel_course_user.'
5694
                WHERE user_id='.$user_id.' AND c_id = '.$courseId;
5695
        $result = Database::query($sql);
5696
        $row_status = Database::fetch_array($result, 'ASSOC');
5697
        return $row_status['status'];
5698
    } else {
5699
        return 0;
5700
    }
5701
}
5702
5703
/**
5704
 * Checks whether the curent user is in a group or not.
5705
 *
5706
 * @param string        The group id - optional (takes it from session if not given)
5707
 * @param string        The course code - optional (no additional check by course if course code is not given)
5708
 * @return boolean
5709
 * @author Ivan Tcholakov
5710
 */
5711
function api_is_in_group($groupIdParam = null, $courseCodeParam = null)
5712
{
5713
    if (!empty($courseCodeParam)) {
5714
        $courseCode = api_get_course_id();
5715
        if (!empty($courseCode)) {
5716
            if ($courseCodeParam != $courseCode) {
5717
                return false;
5718
            }
5719
        } else {
5720
            return false;
5721
        }
5722
    }
5723
5724
    $groupId = api_get_group_id();
5725
5726
    if (isset($groupId) && $groupId != '') {
5727
        if (!empty($groupIdParam)) {
5728
            return $groupIdParam == $groupId;
5729
        } else {
5730
            return true;
5731
        }
5732
    }
5733
5734
    return false;
5735
}
5736
5737
/**
5738
 * Checks whether a secret key is valid
5739
 * @param string $original_key_secret  - secret key from (webservice) client
5740
 * @param string $security_key - security key from Chamilo
5741
 * @return boolean - true if secret key is valid, false otherwise
5742
 */
5743
function api_is_valid_secret_key($original_key_secret, $security_key) {
5744
    return $original_key_secret == sha1($security_key);
5745
}
5746
5747
/**
5748
 * Checks whether a user is into course
5749
 * @param int $course_id - the course id
5750
 * @param int $user_id - the user id
5751
 */
5752
function api_is_user_of_course($course_id, $user_id) {
5753
    $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5754
    $sql = 'SELECT user_id FROM '.$tbl_course_rel_user.'
5755
            WHERE
5756
                c_id ="'.intval($course_id).'" AND
5757
                user_id = "'.intval($user_id).'" AND
5758
                relation_type <> '.COURSE_RELATION_TYPE_RRHH.' ';
5759
    $result = Database::query($sql);
5760
    return Database::num_rows($result) == 1;
5761
}
5762
5763
/**
5764
 * Checks whether the server's operating system is Windows (TM).
5765
 * @return boolean - true if the operating system is Windows, false otherwise
5766
 */
5767
function api_is_windows_os() {
5768
    if (function_exists('php_uname')) {
5769
        // php_uname() exists as of PHP 4.0.2, according to the documentation.
5770
        // We expect that this function will always work for Chamilo 1.8.x.
5771
        $os = php_uname();
5772
    }
5773
    // The following methods are not needed, but let them stay, just in case.
5774
    elseif (isset($_ENV['OS'])) {
5775
        // Sometimes $_ENV['OS'] may not be present (bugs?)
5776
        $os = $_ENV['OS'];
5777
    }
5778
    elseif (defined('PHP_OS')) {
5779
        // PHP_OS means on which OS PHP was compiled, this is why
5780
        // using PHP_OS is the last choice for detection.
5781
        $os = PHP_OS;
5782
    } else {
5783
        return false;
5784
    }
5785
    return strtolower(substr((string)$os, 0, 3 )) == 'win';
5786
}
5787
5788
/**
5789
 * This function informs whether the sent request is XMLHttpRequest
5790
 */
5791
function api_is_xml_http_request() {
5792
    return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
5793
}
5794
5795
/**
5796
 * This wrapper function has been implemented for avoiding some known problems about the function getimagesize().
5797
 * @link http://php.net/manual/en/function.getimagesize.php
5798
 * @link http://www.dokeos.com/forum/viewtopic.php?t=12345
5799
 * @link http://www.dokeos.com/forum/viewtopic.php?t=16355
5800
 * @return integer
5801
 */
5802
function api_getimagesize($path) {
5803
    $image = new Image($path);
5804
    return $image->get_image_size();
5805
}
5806
5807
/**
5808
 * This function resizes an image, with preserving its proportions (or aspect ratio).
5809
 * @author Ivan Tcholakov, MAY-2009.
5810
 * @param int $image            System path or URL of the image
5811
 * @param int $target_width     Targeted width
5812
 * @param int $target_height    Targeted height
5813
 * @return array                Calculated new width and height
5814
 */
5815
function api_resize_image($image, $target_width, $target_height) {
5816
    $image_properties = api_getimagesize($image);
5817
    return api_calculate_image_size($image_properties['width'], $image_properties['height'], $target_width, $target_height);
5818
}
5819
5820
/**
5821
 * This function calculates new image size, with preserving image's proportions (or aspect ratio).
5822
 * @author Ivan Tcholakov, MAY-2009.
5823
 * @author The initial idea has been taken from code by Patrick Cool, MAY-2004.
5824
 * @param int $image_width      Initial width
5825
 * @param int $image_height     Initial height
5826
 * @param int $target_width     Targeted width
5827
 * @param int $target_height    Targeted height
5828
 * @return array                Calculated new width and height
5829
 */
5830
function api_calculate_image_size($image_width, $image_height, $target_width, $target_height) {
5831
    // Only maths is here.
5832
    $result = array('width' => $image_width, 'height' => $image_height);
5833
    if ($image_width <= 0 || $image_height <= 0) {
5834
        return $result;
5835
    }
5836
    $resize_factor_width = $target_width / $image_width;
5837
    $resize_factor_height = $target_height / $image_height;
5838
    $delta_width = $target_width - $image_width * $resize_factor_height;
5839
    $delta_height = $target_height - $image_height * $resize_factor_width;
5840
    if ($delta_width > $delta_height) {
5841
        $result['width'] = ceil($image_width * $resize_factor_height);
5842
        $result['height'] = ceil($image_height * $resize_factor_height);
5843
    }
5844
    elseif ($delta_width < $delta_height) {
5845
        $result['width'] = ceil($image_width * $resize_factor_width);
5846
        $result['height'] = ceil($image_height * $resize_factor_width);
5847
    }
5848
    else {
5849
        $result['width'] = ceil($target_width);
5850
        $result['height'] = ceil($target_height);
5851
    }
5852
    return $result;
5853
}
5854
5855
/**
5856
 * Returns a list of Chamilo's tools or
5857
 * checks whether a given identificator is a valid Chamilo's tool.
5858
 * @author Isaac flores paz
5859
 * @param string The tool name to filter
5860
 * @return mixed Filtered string or array
5861
 */
5862
function api_get_tools_lists($my_tool = null) {
5863
    $tools_list = array(
5864
        TOOL_DOCUMENT,
5865
        TOOL_THUMBNAIL,
5866
        TOOL_HOTPOTATOES,
5867
        TOOL_CALENDAR_EVENT,
5868
        TOOL_LINK,
5869
        TOOL_COURSE_DESCRIPTION,
5870
        TOOL_SEARCH,
5871
        TOOL_LEARNPATH,
5872
        TOOL_ANNOUNCEMENT,
5873
        TOOL_FORUM,
5874
        TOOL_THREAD,
5875
        TOOL_POST,
5876
        TOOL_DROPBOX,
5877
        TOOL_QUIZ,
5878
        TOOL_USER,
5879
        TOOL_GROUP,
5880
        TOOL_BLOGS,
5881
        TOOL_CHAT,
5882
        TOOL_STUDENTPUBLICATION,
5883
        TOOL_TRACKING,
5884
        TOOL_HOMEPAGE_LINK,
5885
        TOOL_COURSE_SETTING,
5886
        TOOL_BACKUP,
5887
        TOOL_COPY_COURSE_CONTENT,
5888
        TOOL_RECYCLE_COURSE,
5889
        TOOL_COURSE_HOMEPAGE,
5890
        TOOL_COURSE_RIGHTS_OVERVIEW,
5891
        TOOL_UPLOAD,
5892
        TOOL_COURSE_MAINTENANCE,
5893
        TOOL_SURVEY,
5894
        TOOL_WIKI,
5895
        TOOL_GLOSSARY,
5896
        TOOL_GRADEBOOK,
5897
        TOOL_NOTEBOOK,
5898
        TOOL_ATTENDANCE,
5899
        TOOL_COURSE_PROGRESS,
5900
    );
5901
    if (empty($my_tool)) {
5902
        return $tools_list;
5903
    }
5904
    return in_array($my_tool, $tools_list) ? $my_tool : '';
5905
}
5906
5907
/**
5908
 * Checks whether we already approved the last version term and condition
5909
 * @param int user id
5910
 * @return bool true if we pass false otherwise
5911
 */
5912
function api_check_term_condition($user_id)
5913
{
5914
    if (api_get_setting('allow_terms_conditions') == 'true') {
5915
        //check if exists terms and conditions
5916
        if (LegalManager::count() == 0) {
5917
5918
            return true;
5919
        }
5920
5921
        $extraFieldValue = new ExtraFieldValue('user');
5922
        $data = $extraFieldValue->get_values_by_handler_and_field_variable(
5923
            $user_id,
5924
            'legal_accept'
5925
        );
5926
5927
        if (!empty($data) && isset($data['value'])) {
5928
            $rowv = $data['value'];
5929
            $user_conditions = explode(':', $rowv);
5930
            $version = $user_conditions[0];
5931
            $lang_id = $user_conditions[1];
5932
            $real_version = LegalManager::get_last_version($lang_id);
5933
5934
            return $version >= $real_version;
5935
        }
5936
        return false;
5937
    }
5938
    return false;
5939
}
5940
5941
/**
5942
 * Gets all information of a tool into course
5943
 * @param int The tool id
5944
 * @return array
5945
 */
5946
function api_get_tool_information($tool_id) {
5947
    $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
5948
    $course_id = api_get_course_int_id();
5949
    $sql = "SELECT * FROM $t_tool WHERE c_id = $course_id AND id = ".intval($tool_id);
5950
    $rs  = Database::query($sql);
5951
    return Database::fetch_array($rs);
5952
}
5953
5954
/**
5955
 * Gets all information of a tool into course
5956
 * @param int The tool id
5957
 * @return array
5958
 */
5959 View Code Duplication
function api_get_tool_information_by_name($name) {
5960
    $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
5961
    $course_id = api_get_course_int_id();
5962
    $sql = "SELECT * FROM $t_tool
5963
            WHERE c_id = $course_id  AND name = '".Database::escape_string($name)."' ";
5964
    $rs  = Database::query($sql);
5965
    return Database::fetch_array($rs, 'ASSOC');
5966
}
5967
5968
/**
5969
 * Function used to protect a "global" admin script.
5970
 * The function blocks access when the user has no global platform admin rights.
5971
 * Global admins are the admins that are registered in the main.admin table
5972
 * AND the users who have access to the "principal" portal.
5973
 * That means that there is a record in the main.access_url_rel_user table
5974
 * with his user id and the access_url_id=1
5975
 *
5976
 * @author Julio Montoya
5977
 * @param integer $user_id
5978
 */
5979
function api_is_global_platform_admin($user_id = null)
5980
{
5981
    $user_id = intval($user_id);
5982
    if (empty($user_id)) {
5983
        $user_id = api_get_user_id();
5984
    }
5985
    if (api_is_platform_admin_by_id($user_id)) {
5986
        $urlList = api_get_access_url_from_user($user_id);
5987
        // The admin is registered in the first "main" site with access_url_id = 1
5988
        if (in_array(1, $urlList)) {
5989
            return true;
5990
        } else {
5991
            return false;
5992
        }
5993
    }
5994
    return false;
5995
}
5996
5997
/**
5998
 * @param int $admin_id_to_check
5999
 * @param int  $my_user_id
6000
 * @param bool $allow_session_admin
6001
 * @return bool
6002
 */
6003
function api_global_admin_can_edit_admin($admin_id_to_check, $my_user_id = null, $allow_session_admin = false)
6004
{
6005
    if (empty($my_user_id)) {
6006
        $my_user_id = api_get_user_id();
6007
    }
6008
6009
    $iam_a_global_admin = api_is_global_platform_admin($my_user_id);
6010
    $user_is_global_admin = api_is_global_platform_admin($admin_id_to_check);
6011
6012
    if ($iam_a_global_admin) {
6013
        // Global admin can edit everything
6014
        return true;
6015
    } else {
6016
        // If i'm a simple admin
6017
        $is_platform_admin = api_is_platform_admin_by_id($my_user_id);
6018
6019
        if ($allow_session_admin) {
6020
            $is_platform_admin = api_is_platform_admin_by_id($my_user_id) || (api_get_user_status($my_user_id) == SESSIONADMIN);
6021
        }
6022
6023
        if ($is_platform_admin) {
6024
            if ($user_is_global_admin) {
6025
                return false;
6026
            } else {
6027
                return true;
6028
            }
6029
        } else {
6030
            return false;
6031
        }
6032
    }
6033
}
6034
6035
/**
6036
 * @param int $admin_id_to_check
6037
 * @param int  $my_user_id
6038
 * @param bool $allow_session_admin
6039
 * @return boolean|null
6040
 */
6041
function api_protect_super_admin($admin_id_to_check, $my_user_id = null, $allow_session_admin = false)
6042
{
6043
    if (api_global_admin_can_edit_admin($admin_id_to_check, $my_user_id, $allow_session_admin)) {
6044
        return true;
6045
    } else {
6046
        api_not_allowed();
6047
    }
6048
}
6049
6050
/**
6051
 * Function used to protect a global admin script.
6052
 * The function blocks access when the user has no global platform admin rights.
6053
 * See also the api_is_global_platform_admin() function wich defines who's a "global" admin
6054
 *
6055
 * @author Julio Montoya
6056
 */
6057
function api_protect_global_admin_script() {
6058
    if (!api_is_global_platform_admin()) {
6059
        api_not_allowed();
6060
        return false;
6061
    }
6062
    return true;
6063
}
6064
6065
/**
6066
 * Get active template
6067
 * @param string    theme type (optional: default)
6068
 * @param string    path absolute(abs) or relative(rel) (optional:rel)
6069
 * @return string   actived template path
6070
 */
6071
function api_get_template($path_type = 'rel') {
6072
    $path_types = array('rel', 'abs');
6073
    $template_path = '';
6074
    if (in_array($path_type, $path_types)) {
6075
        if ($path_type == 'rel') {
6076
            $template_path = api_get_path(SYS_TEMPLATE_PATH);
6077
        } else {
6078
            $template_path = api_get_path(WEB_TEMPLATE_PATH);
6079
        }
6080
    }
6081
    $actived_theme = 'default';
6082
    if (api_get_setting('active_template')) {
6083
        $actived_theme = api_get_setting('active_template');
6084
    }
6085
    $actived_theme_path = $template_path.$actived_theme.DIRECTORY_SEPARATOR;
6086
    return $actived_theme_path;
6087
}
6088
6089
/**
6090
 * Check browser support for type files
6091
 * This function check if the users browser support a file format or
6092
 * return the current browser and major ver when $format=check_browser
6093
 * @param string $format
6094
 *
6095
 * @return bool or return text array if $format=check_browser
6096
 * @author Juan Carlos Raña Trabado
6097
 */
6098
function api_browser_support($format = '')
6099
{
6100
    $browser = new Browser();
6101
    $current_browser = $browser->getBrowser();
6102
    $a_versiontemp = explode('.', $browser->getVersion());
6103
    $current_majorver = $a_versiontemp[0];
6104
6105
    static $result;
6106
6107
    if (isset($result[$format])) {
6108
        return $result[$format];
6109
    }
6110
6111
    // Native svg support
6112
    if ($format == 'svg') {
6113
        if (($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6114
            ($current_browser == 'Firefox' && $current_majorver > 1) ||
6115
            ($current_browser == 'Safari' && $current_majorver >= 4) ||
6116
            ($current_browser == 'Chrome' && $current_majorver >= 1) ||
6117
            ($current_browser == 'Opera' && $current_majorver >= 9)
6118
        ) {
6119
            $result[$format] = true;
6120
            return true;
6121
        } else {
6122
            $result[$format] = false;
6123
            return false;
6124
        }
6125
    } elseif ($format == 'pdf') {
6126
        //native pdf support
6127
        if ($current_browser == 'Chrome' && $current_majorver >= 6) {
6128
            $result[$format] = true;
6129
            return true;
6130
        } else {
6131
            $result[$format] = false;
6132
            return false;
6133
        }
6134
    } elseif ($format == 'tif' || $format == 'tiff') {
6135
        //native tif support
6136
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6137
            $result[$format] = true;
6138
            return true;
6139
        } else {
6140
            $result[$format] = false;
6141
            return false;
6142
        }
6143
    } elseif ($format == 'ogg' || $format == 'ogx' || $format == 'ogv' || $format == 'oga') {
6144
        //native ogg, ogv,oga support
6145
        if (($current_browser == 'Firefox' && $current_majorver >= 3) ||
6146
            ($current_browser == 'Chrome' && $current_majorver >= 3) ||
6147
            ($current_browser == 'Opera' && $current_majorver >= 9)) {
6148
            $result[$format] = true;
6149
            return true;
6150
        } else {
6151
            $result[$format] = false;
6152
            return false;
6153
        }
6154
    } elseif ($format == 'mpg' || $format == 'mpeg') {
6155
        //native mpg support
6156
        if (($current_browser == 'Safari' && $current_majorver >= 5)) {
6157
            $result[$format] = true;
6158
            return true;
6159
        } else {
6160
            $result[$format] = false;
6161
            return false;
6162
        }
6163
    } elseif ($format == 'mp4') {
6164
        //native mp4 support (TODO: Android, iPhone)
6165
        if ($current_browser == 'Android' || $current_browser == 'iPhone') {
6166
            $result[$format] = true;
6167
            return true;
6168
        } else {
6169
            $result[$format] = false;
6170
            return false;
6171
        }
6172
    } elseif ($format == 'mov') {
6173
        //native mov support( TODO:check iPhone)
6174
        if ($current_browser == 'Safari' && $current_majorver >= 5 || $current_browser == 'iPhone') {
6175
            $result[$format] = true;
6176
            return true;
6177
        } else {
6178
            $result[$format] = false;
6179
            return false;
6180
        }
6181
    } elseif ($format == 'avi') {
6182
        //native avi support
6183
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6184
            $result[$format] = true;
6185
            return true;
6186
        } else {
6187
            $result[$format] = false;
6188
            return false;
6189
        }
6190
    } elseif ($format == 'wmv') {
6191
        //native wmv support
6192
        if ($current_browser == 'Firefox' && $current_majorver >= 4) {
6193
            $result[$format] = true;
6194
            return true;
6195
        } else {
6196
            $result[$format] = false;
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
            $result[$format] = true;
6208
            return true;
6209
        } else {
6210
            $result[$format] = false;
6211
            return false;
6212
        }
6213
    } elseif ($format == 'wav') {
6214
        //native wav support (only some codecs !)
6215
        if (($current_browser == 'Firefox' && $current_majorver >= 4) ||
6216
            ($current_browser == 'Safari' && $current_majorver >= 5) ||
6217
            ($current_browser == 'Opera' && $current_majorver >= 9) ||
6218
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6219
            ($current_browser == 'Chrome' && $current_majorver > 9) ||
6220
            $current_browser == 'Android' ||
6221
            $current_browser == 'iPhone'
6222
        ) {
6223
            $result[$format] = true;
6224
            return true;
6225
        } else {
6226
            $result[$format] = false;
6227
            return false;
6228
        }
6229
    } elseif ($format == 'mid' || $format == 'kar') {
6230
        //native midi support (TODO:check Android)
6231
        if ($current_browser == 'Opera' && $current_majorver >= 9 || $current_browser == 'Android') {
6232
            $result[$format] = true;
6233
            return true;
6234
        } else {
6235
            $result[$format] = false;
6236
            return false;
6237
        }
6238
    } elseif ($format == 'wma') {
6239
        //native wma support
6240
        if ($current_browser == 'Firefox' && $current_majorver >= 4) {
6241
            $result[$format] = true;
6242
            return true;
6243
        } else {
6244
            $result[$format] = false;
6245
            return false;
6246
        }
6247
    } elseif ($format == 'au') {
6248
        //native au support
6249
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6250
            $result[$format] = true;
6251
            return true;
6252
        } else {
6253
            $result[$format] = false;
6254
            return false;
6255
        }
6256 View Code Duplication
    } elseif ($format == 'mp3') {
6257
        //native mp3 support (TODO:check Android, iPhone)
6258
        if (($current_browser == 'Safari' && $current_majorver >= 5) ||
6259
            ($current_browser == 'Chrome' && $current_majorver >= 6) ||
6260
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6261
            $current_browser == 'Android' ||
6262
            $current_browser == 'iPhone' ||
6263
            $current_browser == 'Firefox'
6264
        ) {
6265
            $result[$format] = true;
6266
            return true;
6267
        } else {
6268
            $result[$format] = false;
6269
            return false;
6270
        }
6271
    } elseif ($format == "check_browser") {
6272
        $array_check_browser = array($current_browser, $current_majorver);
6273
        return $array_check_browser;
6274
    } else {
6275
        $result[$format] = false;
6276
        return false;
6277
    }
6278
}
6279
6280
/**
6281
 * This function checks if exist path and file browscap.ini
6282
 * In order for this to work, your browscap configuration setting in php.ini
6283
 * must point to the correct location of the browscap.ini file on your system
6284
 * http://php.net/manual/en/function.get-browser.php
6285
 *
6286
 * @return bool
6287
 *
6288
 * @author Juan Carlos Raña Trabado
6289
 */
6290
function api_check_browscap() {
6291
    $setting = ini_get('browscap');
6292
    if ($setting) {
6293
        $browser = get_browser($_SERVER['HTTP_USER_AGENT'], true);
6294
        if (strpos($setting, 'browscap.ini') && !empty($browser)) {
6295
            return true;
6296
        }
6297
    }
6298
    return false;
6299
}
6300
6301
/**
6302
 * Returns the <script> HTML tag
6303
 */
6304
function api_get_js($file) {
6305
    return '<script type="text/javascript" src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/'.$file.'"></script>'."\n";
6306
}
6307
6308
/**
6309
 * Returns the <script> HTML tag
6310
 * @return string
6311
 */
6312
function api_get_asset($file)
6313
{
6314
    return '<script type="text/javascript" src="'.api_get_path(WEB_PATH).'web/assets/'.$file.'"></script>'."\n";
6315
}
6316
6317
/**
6318
 * Returns the <script> HTML tag
6319
 * @return string
6320
 */
6321
function api_get_css_asset($file, $media = 'screen')
6322
{
6323
    return '<link href="'.api_get_path(WEB_PATH).'web/assets/'.$file.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
6324
}
6325
6326
/**
6327
 * Returns the <link> HTML tag
6328
 * @param string $file
6329
 */
6330
function api_get_css($file, $media = 'screen') {
6331
    return '<link href="'.$file.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
6332
}
6333
6334
/**
6335
 * Returns the js header to include the jquery library
6336
 */
6337
function api_get_jquery_js()
6338
{
6339
    return api_get_asset('jquery/dist/jquery.min.js');
6340
}
6341
6342
/**
6343
 * Returns the jquery path
6344
 * @return string
6345
 */
6346
function api_get_jquery_web_path()
6347
{
6348
    return api_get_path(WEB_PATH).'web/assets/jquery/dist/jquery.min.js';
6349
}
6350
6351
/**
6352
 * @return string
6353
 */
6354
function api_get_jquery_ui_js_web_path()
6355
{
6356
    return api_get_path(WEB_PATH).'web/assets/jquery-ui/jquery-ui.min.js';
6357
}
6358
6359
/**
6360
 * @return string
6361
 */
6362
function api_get_jquery_ui_css_web_path()
6363
{
6364
    return api_get_path(WEB_PATH).'web/assets/jquery-ui/themes/smoothness/jquery-ui.min.css';
6365
}
6366
6367
/**
6368
 * Returns the jquery-ui library js headers
6369
 * @param   bool    add the jqgrid library
6370
 * @return  string  html tags
6371
 *
6372
 */
6373
function api_get_jquery_ui_js($include_jqgrid = false) {
6374
    $libraries = array();
6375
    if ($include_jqgrid) {
6376
       $libraries[]='jqgrid';
6377
    }
6378
    return api_get_jquery_libraries_js($libraries);
6379
}
6380
6381
function api_get_jqgrid_js() {
6382
    return api_get_jquery_libraries_js(array('jqgrid'));
6383
}
6384
6385
/**
6386
 * Returns the jquery library js and css headers
6387
 *
6388
 * @param   array   list of jquery libraries supported jquery-ui, jqgrid
6389
 * @param   bool    add the jquery library
6390
 * @return  string  html tags
6391
 *
6392
 */
6393
function api_get_jquery_libraries_js($libraries) {
6394
    $js = '';
6395
    $js_path = api_get_path(WEB_LIBRARY_PATH).'javascript/';
6396
6397
    //jqgrid js and css
6398
    if (in_array('jqgrid', $libraries)) {
6399
        $languaje   = 'en';
6400
        $platform_isocode = strtolower(api_get_language_isocode());
6401
6402
        //languages supported by jqgrid see files in main/inc/lib/javascript/jqgrid/js/i18n
6403
        $jqgrid_langs = array(
6404
            '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'
6405
        );
6406
6407
        if (in_array($platform_isocode, $jqgrid_langs)) {
6408
            $languaje = $platform_isocode;
6409
        }
6410
        //$js .= '<link rel="stylesheet" href="'.$js_path.'jqgrid/css/ui.jqgrid.css" type="text/css">';
6411
        $js .= api_get_css($js_path.'jqgrid/css/ui.jqgrid.css');
6412
        $js .= api_get_js('jqgrid/js/i18n/grid.locale-'.$languaje.'.js');
6413
        $js .= api_get_js('jqgrid/js/jquery.jqGrid.min.js');
6414
    }
6415
6416
    //Document multiple upload funcionality
6417
    if (in_array('jquery-upload', $libraries)) {
6418
6419
        $js .= api_get_asset('blueimp-load-image/js/load-image.all.min.js');
6420
        $js .= api_get_asset('blueimp-canvas-to-blob/js/canvas-to-blob.min.js');
6421
        $js .= api_get_asset('jquery-file-upload/js/jquery.iframe-transport.js');
6422
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload.js');
6423
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-process.js');
6424
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-image.js');
6425
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-audio.js');
6426
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-video.js');
6427
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-validate.js');
6428
6429
        $js .= api_get_css(api_get_path(WEB_PATH).'web/assets/jquery-file-upload/css/jquery.fileupload.css');
6430
        $js .= api_get_css(api_get_path(WEB_PATH).'web/assets/jquery-file-upload/css/jquery.fileupload-ui.css');
6431
    }
6432
6433
    // jquery datepicker
6434
    if (in_array('datepicker', $libraries)) {
6435
        $languaje   = 'en-GB';
6436
        $platform_isocode = strtolower(api_get_language_isocode());
6437
6438
        // languages supported by jqgrid see files in main/inc/lib/javascript/jqgrid/js/i18n
6439
        $datapicker_langs = array(
6440
            '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'
6441
        );
6442
        if (in_array($platform_isocode, $datapicker_langs)) {
6443
            $languaje = $platform_isocode;
6444
        }
6445
6446
        $js .= api_get_js('jquery-ui/jquery-ui-i18n.min.js');
6447
        $script = '<script>
6448
        $(function(){
6449
            $.datepicker.setDefaults($.datepicker.regional["'.$languaje.'"]);
6450
            $.datepicker.regional["local"] = $.datepicker.regional["'.$languaje.'"];
6451
        });
6452
        </script>
6453
        ';
6454
        $js .= $script;
6455
    }
6456
    return $js;
6457
}
6458
6459
/**
6460
 * Returns the course's URL
6461
 *
6462
 * This function relies on api_get_course_info()
6463
 * @param   string  The course code - optional (takes it from session if not given)
6464
 * @param   int     The session id  - optional (takes it from session if not given)
6465
 * @param integer $session_id
6466
 * @return  string|null   The URL of the course or null if something does not work
6467
 * @author  Julio Montoya <[email protected]>
6468
 */
6469
function api_get_course_url($course_code = null, $session_id = null)
6470
{
6471
    if (empty($course_code)) {
6472
        $course_info = api_get_course_info();
6473
    } else {
6474
        $course_info = api_get_course_info($course_code);
6475
    }
6476
    if (empty($session_id)) {
6477
        $session_url = '?id_session='.api_get_session_id();
6478
    } else {
6479
        $session_url = '?id_session='.intval($session_id);
6480
    }
6481
    /*
6482
    if (empty($group_id)) {
6483
        $group_url = '&gidReq='.api_get_group_id();
6484
    } else {
6485
        $group_url = '&gidReq='.intval($group_id);
6486
    }*/
6487
    if (!empty($course_info['path'])) {
6488
        return api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php'.$session_url;
6489
    }
6490
    return null;
6491
}
6492
6493
/**
6494
 *
6495
 * Check if the current portal has the $_configuration['multiple_access_urls'] parameter on
6496
 * @return bool true if multi site is enabled
6497
 *
6498
 **/
6499
function api_get_multiple_access_url() {
6500
    global $_configuration;
6501
    if (isset($_configuration['multiple_access_urls']) && $_configuration['multiple_access_urls']) {
6502
        return true;
6503
    }
6504
    return false;
6505
}
6506
6507
/**
6508
 * @return bool
6509
 */
6510
function api_is_multiple_url_enabled() {
6511
    return api_get_multiple_access_url();
6512
}
6513
6514
/**
6515
 * Returns a md5 unique id
6516
 * @todo add more parameters
6517
 */
6518
function api_get_unique_id() {
6519
    $id = md5(time().uniqid().api_get_user_id().api_get_course_id().api_get_session_id());
6520
    return $id;
6521
}
6522
6523
/**
6524
 * Get home path
6525
 * @return string
6526
 */
6527
function api_get_home_path()
6528
{
6529
    // FIX : Start the routing determination from central path definition
6530
    $home = api_get_path(SYS_HOME_PATH);
6531
    if (api_get_multiple_access_url()) {
6532
        $access_url_id = api_get_current_access_url_id();
6533
        $url_info = api_get_access_url($access_url_id);
6534
        $url = api_remove_trailing_slash(preg_replace('/https?:\/\//i', '', $url_info['url']));
6535
        $clean_url = api_replace_dangerous_char($url);
6536
        $clean_url = str_replace('/', '-', $clean_url);
6537
        $clean_url .= '/';
6538
        if ($clean_url != 'localhost/') {
6539
            // means that the multiple URL was not well configured we don't rename the $home variable
6540
            return "{$home}{$clean_url}";
6541
        }
6542
    }
6543
6544
    return $home;
6545
}
6546
6547
/**
6548
 *
6549
 * @param int Course id
6550
 * @param int tool id: TOOL_QUIZ, TOOL_FORUM, TOOL_STUDENTPUBLICATION, TOOL_LEARNPATH
6551
 * @param int the item id (tool id, exercise id, lp id)
6552
 *
6553
 */
6554
function api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code = null) {
6555
    if (api_is_platform_admin()) {
6556
        return false;
6557
    }
6558
    if (api_get_setting('gradebook_locking_enabled') == 'true') {
6559
        if (empty($course_code)) {
6560
            $course_code = api_get_course_id();
6561
        }
6562
        $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
6563
        $item_id = intval($item_id);
6564
        $link_type = intval($link_type);
6565
        $course_code = Database::escape_string($course_code);
6566
        $sql = "SELECT locked FROM $table
6567
                WHERE locked = 1 AND ref_id = $item_id AND type = $link_type AND course_code = '$course_code' ";
6568
        $result = Database::query($sql);
6569
        if (Database::num_rows($result)) {
6570
            return true;
6571
        }
6572
    }
6573
    return false;
6574
}
6575
6576
/**
6577
 * Blocks a page if the item was added in a gradebook
6578
 *
6579
 * @param int       exercise id, work id, thread id,
6580
 * @param int       LINK_EXERCISE, LINK_STUDENTPUBLICATION, LINK_LEARNPATH LINK_FORUM_THREAD, LINK_ATTENDANCE
6581
 * see gradebook/lib/be/linkfactory
6582
 * @param string    course code
6583
 * @return false|null
6584
 */
6585
function api_block_course_item_locked_by_gradebook($item_id, $link_type, $course_code = null) {
6586
    if (api_is_platform_admin()) {
6587
        return false;
6588
    }
6589
6590
    if (api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code)) {
6591
        $message = Display::return_message(get_lang('ResourceLockedByGradebook'), 'warning');
6592
        api_not_allowed(true, $message);
6593
    }
6594
}
6595
/**
6596
 * Checks the PHP version installed is enough to run Chamilo
6597
 * @param string Include path (used to load the error page)
6598
 * @return void
6599
 */
6600
function api_check_php_version($my_inc_path = null) {
6601
    if (!function_exists('version_compare') || version_compare( phpversion(), REQUIRED_PHP_VERSION, '<')) {
6602
        $global_error_code = 1;
6603
        // Incorrect PHP version
6604
        $global_page = $my_inc_path.'global_error_message.inc.php';
6605
        if (file_exists($global_page)) {
6606
            require $global_page;
6607
        }
6608
        exit;
6609
    }
6610
}
6611
/**
6612
 * Checks whether the Archive directory is present and writeable. If not,
6613
 * prints a warning message.
6614
 */
6615
function api_check_archive_dir() {
6616 View Code Duplication
    if (is_dir(api_get_path(SYS_ARCHIVE_PATH)) && !is_writable(api_get_path(SYS_ARCHIVE_PATH))) {
6617
        $message = Display::return_message(get_lang('ArchivesDirectoryNotWriteableContactAdmin'),'warning');
6618
        api_not_allowed(true, $message);
6619
    }
6620
}
6621
/**
6622
 * Returns an array of global configuration settings which should be ignored
6623
 * when printing the configuration settings screens
6624
 * @return array Array of strings, each identifying one of the excluded settings
6625
 */
6626
function api_get_locked_settings() {
6627
    return array(
6628
        'server_type',
6629
        'permanently_remove_deleted_files',
6630
        'account_valid_duration',
6631
        'service_ppt2lp',
6632
        'wcag_anysurfer_public_pages',
6633
        'upload_extensions_list_type',
6634
        'upload_extensions_blacklist',
6635
        'upload_extensions_whitelist',
6636
        'upload_extensions_skip',
6637
        'upload_extensions_replace_by',
6638
        'hide_dltt_markup',
6639
        'split_users_upload_directory',
6640
        'permissions_for_new_directories',
6641
        'permissions_for_new_files',
6642
        'platform_charset',
6643
        'ldap_description',
6644
        'cas_activate',
6645
        'cas_server',
6646
        'cas_server_uri',
6647
        'cas_port',
6648
        'cas_protocol',
6649
        'cas_add_user_activate',
6650
        'update_user_info_cas_with_ldap',
6651
        'languagePriority1',
6652
        'languagePriority2',
6653
        'languagePriority3',
6654
        'languagePriority4',
6655
        'login_is_email',
6656
        'chamilo_database_version'
6657
    );
6658
}
6659
6660
/**
6661
 * Checks if the user is corrently logged in. Returns the user ID if he is, or
6662
 * false if he isn't. If the user ID is given and is an integer, then the same
6663
 * ID is simply returned
6664
 * @param  integer User ID
6665
 * @return boolean Integer User ID is logged in, or false otherwise
6666
 */
6667
function api_user_is_login($user_id = null) {
6668
    $user_id = empty($user_id) ? api_get_user_id() : intval($user_id);
6669
    return $user_id && !api_is_anonymous();
6670
}
6671
6672
/**
6673
 * Guess the real ip for register in the database, even in reverse proxy cases.
6674
 * To be recognized, the IP has to be found in either $_SERVER['REMOTE_ADDR'] or
6675
 * in $_SERVER['HTTP_X_FORWARDED_FOR'], which is in common use with rproxies.
6676
 * @return string the user's real ip (unsafe - escape it before inserting to db)
6677
 * @author Jorge Frisancho Jibaja <[email protected]>, USIL - Some changes to allow the use of real IP using reverse proxy
6678
 * @version CEV CHANGE 24APR2012
6679
 */
6680
function api_get_real_ip(){
6681
    // Guess the IP if behind a reverse proxy
6682
    global $debug;
6683
    $ip = trim($_SERVER['REMOTE_ADDR']);
6684
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
6685
        if (preg_match('/,/', $_SERVER['HTTP_X_FORWARDED_FOR'])) {
6686
            @list($ip1, $ip2) = @explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
6687
        } else {
6688
            $ip1 = $_SERVER['HTTP_X_FORWARDED_FOR'];
6689
        }
6690
        $ip = trim($ip1);
6691
    }
6692
    if (!empty($debug)) error_log('Real IP: '.$ip);
6693
    return $ip;
6694
}
6695
6696
/**
6697
 * Checks whether an IP is included inside an IP range
6698
 * @param string IP address
6699
 * @param string IP range
6700
 * @param string $ip
6701
 * @return bool True if IP is in the range, false otherwise
6702
 * @author claudiu at cnixs dot com  on http://www.php.net/manual/fr/ref.network.php#55230
6703
 * @author Yannick Warnier for improvements and managment of multiple ranges
6704
 * @todo check for IPv6 support
6705
 */
6706
function api_check_ip_in_range($ip,$range)
6707
{
6708
    if (empty($ip) or empty($range)) {
6709
        return false;
6710
    }
6711
    $ip_ip = ip2long ($ip);
6712
    // divide range param into array of elements
6713
    if (strpos($range,',')!==false) {
6714
        $ranges = explode(',',$range);
6715
    } else {
6716
        $ranges = array($range);
6717
    }
6718
    foreach ($ranges as $range) {
6719
        $range = trim($range);
6720
        if (empty($range)) { continue; }
6721
        if (strpos($range,'/')===false) {
6722
            if (strcmp($ip,$range)===0) {
6723
                return true; // there is a direct IP match, return OK
6724
            }
6725
            continue; //otherwise, get to the next range
6726
        }
6727
        // the range contains a "/", so analyse completely
6728
        list ($net, $mask) = explode("/", $range);
6729
6730
        $ip_net = ip2long ($net);
6731
        // mask binary magic
6732
        $ip_mask = ~((1 << (32 - $mask)) - 1);
6733
6734
        $ip_ip_net = $ip_ip & $ip_mask;
6735
        if ($ip_ip_net == $ip_net) {
6736
            return true;
6737
        }
6738
    }
6739
6740
    return false;
6741
}
6742
6743
function api_check_user_access_to_legal($course_visibility) {
6744
    $course_visibility_list = array(COURSE_VISIBILITY_OPEN_WORLD, COURSE_VISIBILITY_OPEN_PLATFORM);
6745
    return in_array($course_visibility, $course_visibility_list) || api_is_drh();
6746
}
6747
6748
/**
6749
 * Checks if the global chat is enabled or not
6750
 *
6751
 * @return bool
6752
 */
6753
function api_is_global_chat_enabled()
6754
{
6755
    return
6756
        !api_is_anonymous() &&
6757
        api_get_setting('allow_global_chat') == 'true' &&
6758
        api_get_setting('allow_social_tool') == 'true';
6759
}
6760
6761
/**
6762
 * @todo Fix tool_visible_by_default_at_creation labels
6763
 * @todo Add sessionId parameter to avoid using context
6764
 *
6765
 * @param int $item_id
6766
 * @param int $tool_id
6767
 * @param int $group_id iid
6768
 * @param array $courseInfo
6769
 */
6770
function api_set_default_visibility(
6771
    $item_id,
6772
    $tool_id,
6773
    $group_id = 0,
6774
    $courseInfo = array(),
6775
    $sessionId = 0,
6776
    $userId = 0
6777
) {
6778
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
6779
    $courseId = $courseInfo['real_id'];
6780
    $courseCode = $courseInfo['code'];
6781
    $sessionId = empty($sessionId) ? api_get_session_id() : $sessionId;
6782
    $userId = empty($userId) ? api_get_user_id() : $userId;
6783
6784
    if (empty($group_id)) {
6785
        $group_id = api_get_group_id();
6786
    }
6787
6788
    $groupInfo = GroupManager::get_group_properties($group_id);
6789
    $groupIid = 0;
6790
    if ($groupInfo) {
6791
        $groupIid = $groupInfo['iid'];
6792
    }
6793
6794
    $original_tool_id = $tool_id;
6795
6796
    switch ($tool_id) {
6797
        case TOOL_LINK:
6798
        case TOOL_LINK_CATEGORY:
6799
            $tool_id = 'links';
6800
            break;
6801
        case TOOL_DOCUMENT:
6802
            $tool_id = 'documents';
6803
            break;
6804
        case TOOL_LEARNPATH:
6805
            $tool_id = 'learning';
6806
            break;
6807
        case TOOL_ANNOUNCEMENT:
6808
            $tool_id = 'announcements';
6809
            break;
6810
        case TOOL_FORUM:
6811
        case TOOL_FORUM_CATEGORY:
6812
        case TOOL_FORUM_THREAD:
6813
            $tool_id = 'forums';
6814
            break;
6815
        case TOOL_QUIZ:
6816
            $tool_id = 'quiz';
6817
            break;
6818
    }
6819
    $setting = api_get_setting('tool_visible_by_default_at_creation');
6820
6821
    if (isset($setting[$tool_id])) {
6822
        $visibility = 'invisible';
6823
        if ($setting[$tool_id] == 'true') {
6824
            $visibility = 'visible';
6825
        }
6826
6827
        // Read the portal and course default visibility
6828
        if ($tool_id == 'documents') {
6829
            $visibility = DocumentManager::getDocumentDefaultVisibility($courseCode);
6830
        }
6831
6832
        api_item_property_update(
6833
            $courseInfo,
6834
            $original_tool_id,
6835
            $item_id,
6836
            $visibility,
6837
            $userId,
6838
            $groupIid,
6839
            null,
6840
            null,
6841
            null,
6842
            api_get_session_id()
6843
        );
6844
6845
        // Fixes default visibility for tests
6846
6847
        switch ($original_tool_id) {
6848
            case TOOL_QUIZ:
6849
                if (empty($sessionId)) {
6850
                    $objExerciseTmp = new Exercise($courseId);
6851
                    $objExerciseTmp->read($item_id);
6852
                    if ($visibility == 'visible') {
6853
                        $objExerciseTmp->enable();
6854
                        $objExerciseTmp->save();
6855
                    } else {
6856
                        $objExerciseTmp->disable();
6857
                        $objExerciseTmp->save();
6858
                    }
6859
                }
6860
                break;
6861
        }
6862
    }
6863
}
6864
6865
/**
6866
 * @return string
6867
 */
6868
function api_get_security_key() {
6869
    return api_get_configuration_value('security_key');
6870
}
6871
6872
/**
6873
 * @param int $user_id
6874
 * @param int $courseId
6875
 * @param int $session_id
6876
 * @return array
6877
 */
6878
function api_detect_user_roles($user_id, $courseId, $session_id = 0)
6879
{
6880
    $user_roles = array();
6881
    /*$user_info = api_get_user_info($user_id);
6882
    $user_roles[] = $user_info['status'];*/
6883
    $courseInfo = api_get_course_info_by_id($courseId);
6884
    $course_code = $courseInfo['code'];
6885
6886
    $url_id = api_get_current_access_url_id();
6887
    if (api_is_platform_admin_by_id($user_id, $url_id)) {
6888
        $user_roles[] = PLATFORM_ADMIN;
6889
    }
6890
6891
    /*if (api_is_drh()) {
6892
        $user_roles[] = DRH;
6893
    }*/
6894
6895
    if (!empty($session_id)) {
6896
        if (SessionManager::user_is_general_coach($user_id, $session_id)) {
6897
            $user_roles[] = SESSION_GENERAL_COACH;
6898
        }
6899
    }
6900
6901
    if (!empty($course_code)) {
6902
        if (empty($session_id)) {
6903
            if (CourseManager::is_course_teacher($user_id, $course_code)) {
6904
                $user_roles[] = COURSEMANAGER;
6905
            }
6906
            if (CourseManager::get_tutor_in_course_status($user_id, $courseInfo['real_id'])) {
6907
                $user_roles[] = COURSE_TUTOR;
6908
            }
6909
6910
            if (CourseManager::is_user_subscribed_in_course($user_id, $course_code)) {
6911
                $user_roles[] = COURSE_STUDENT;
6912
            }
6913
        } else {
6914
            $user_status_in_session = SessionManager::get_user_status_in_course_session(
6915
                $user_id,
6916
                $courseId,
6917
                $session_id
6918
            );
6919
6920
            if (!empty($user_status_in_session)) {
6921
                if ($user_status_in_session == 0) {
6922
                    $user_roles[] = SESSION_STUDENT;
6923
                }
6924
                if ($user_status_in_session == 2) {
6925
                    $user_roles[] = SESSION_COURSE_COACH;
6926
                }
6927
            }
6928
6929
            /*if (api_is_course_session_coach($user_id, $course_code, $session_id)) {
6930
               $user_roles[] = SESSION_COURSE_COACH;
6931
            }*/
6932
        }
6933
    }
6934
    return $user_roles;
6935
}
6936
6937
/**
6938
 * @param int $courseId
6939
 * @param int $session_id
6940
 * @return bool
6941
 */
6942
function api_coach_can_edit_view_results($courseId = null, $session_id = null)
6943
{
6944
    $user_id = api_get_user_id();
6945
6946
    if (empty($courseId)) {
6947
        $courseId = api_get_course_int_id();
6948
    }
6949
6950
    if (empty($session_id)) {
6951
        $session_id = api_get_session_id();
6952
    }
6953
6954
    if (api_is_platform_admin()) {
6955
        return true;
6956
    }
6957
6958
    $roles = api_detect_user_roles($user_id, $courseId, $session_id);
6959
6960
    if (in_array(SESSION_COURSE_COACH, $roles)) {
6961
        //return api_get_setting('session_tutor_reports_visibility') == 'true';
6962
        return true;
6963
    } else {
6964
        if (in_array(COURSEMANAGER, $roles)) {
6965
            return true;
6966
        }
6967
        return false;
6968
    }
6969
}
6970
6971
function api_get_js_simple($file) {
6972
    return '<script type="text/javascript" src="'.$file.'"></script>'."\n";
6973
}
6974
6975
function api_set_settings_and_plugins() {
6976
    global $_configuration;
6977
    $_setting = array();
6978
    $_plugins = array();
6979
6980
    // access_url == 1 is the default chamilo location
6981
    $settings_by_access_list = array();
6982
    $access_url_id = api_get_current_access_url_id();
6983 View Code Duplication
    if ($access_url_id != 1) {
6984
        $url_info = api_get_access_url($_configuration['access_url']);
6985
        if ($url_info['active'] == 1) {
6986
            $settings_by_access = & api_get_settings(null, 'list', $_configuration['access_url'], 1);
6987
            foreach ($settings_by_access as & $row) {
6988
                if (empty($row['variable'])) {
6989
                    $row['variable'] = 0;
6990
                }
6991
                if (empty($row['subkey'])) {
6992
                    $row['subkey'] = 0;
6993
                }
6994
                if (empty($row['category'])) {
6995
                    $row['category'] = 0;
6996
                }
6997
                $settings_by_access_list[$row['variable']][$row['subkey']][$row['category']] = $row;
6998
            }
6999
        }
7000
    }
7001
7002
    $result = api_get_settings(null, 'list', 1);
7003
7004 View Code Duplication
    foreach ($result as & $row) {
7005
        if ($access_url_id != 1) {
7006
            if ($url_info['active'] == 1) {
7007
                $var = empty($row['variable']) ? 0 : $row['variable'];
7008
                $subkey = empty($row['subkey']) ? 0 : $row['subkey'];
7009
                $category = empty($row['category']) ? 0 : $row['category'];
7010
            }
7011
7012
            if ($row['access_url_changeable'] == 1 && $url_info['active'] == 1) {
7013
                if (isset($settings_by_access_list[$var]) &&
7014
                    $settings_by_access_list[$var][$subkey][$category]['selected_value'] != '') {
7015
                    if ($row['subkey'] == null) {
7016
                        $_setting[$row['variable']] = $settings_by_access_list[$var][$subkey][$category]['selected_value'];
7017
                    } else {
7018
                        $_setting[$row['variable']][$row['subkey']] = $settings_by_access_list[$var][$subkey][$category]['selected_value'];
7019
                    }
7020
                } else {
7021
                    if ($row['subkey'] == null) {
7022
                        $_setting[$row['variable']] = $row['selected_value'];
7023
                    } else {
7024
                        $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7025
                    }
7026
                }
7027
            } else {
7028
                if ($row['subkey'] == null) {
7029
                    $_setting[$row['variable']] = $row['selected_value'];
7030
                } else {
7031
                    $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7032
                }
7033
            }
7034
        } else {
7035
            if ($row['subkey'] == null) {
7036
                $_setting[$row['variable']] = $row['selected_value'];
7037
            } else {
7038
                $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7039
            }
7040
        }
7041
    }
7042
7043
    $result = api_get_settings('Plugins', 'list', $access_url_id);
7044
    $_plugins = array();
7045 View Code Duplication
    foreach ($result as & $row) {
7046
        $key = & $row['variable'];
7047
        if (is_string($_setting[$key])) {
7048
            $_setting[$key] = array();
7049
        }
7050
        $_setting[$key][] = $row['selected_value'];
7051
        $_plugins[$key][] = $row['selected_value'];
7052
    }
7053
7054
    $_SESSION['_setting'] = $_setting;
7055
    $_SESSION['_plugins'] = $_plugins;
7056
}
7057
7058
/**
7059
 * Tries to set memory limit, if authorized and new limit is higher than current
7060
 * @param string New memory limit
7061
 * @param string $mem
7062
 * @return bool True on success, false on failure or current is higher than suggested
7063
 * @assert (null) === false
7064
 * @assert (-1) === false
7065
 * @assert (0) === true
7066
 * @assert ('1G') === true
7067
 */
7068
function api_set_memory_limit($mem){
7069
    //if ini_set() not available, this function is useless
7070
    if (!function_exists('ini_set') || is_null($mem) || $mem == -1) {
7071
        return false;
7072
    }
7073
7074
    $memory_limit = ini_get('memory_limit');
7075
    if (api_get_bytes_memory_limit($mem) > api_get_bytes_memory_limit($memory_limit)){
7076
        ini_set('memory_limit', $mem);
7077
        return true;
7078
    }
7079
    return false;
7080
}
7081
7082
/**
7083
 * Gets memory limit in bytes
7084
 * @param string The memory size (128M, 1G, 1000K, etc)
7085
 * @return int
7086
 * @assert (null) === false
7087
 * @assert ('1t')  === 1099511627776
7088
 * @assert ('1g')  === 1073741824
7089
 * @assert ('1m')  === 1048576
7090
 * @assert ('100k') === 102400
7091
 */
7092
function api_get_bytes_memory_limit($mem){
7093
    $size = strtolower(substr($mem,-1));
7094
7095
    switch ($size) {
7096
        case 't':
7097
            $mem = intval(substr($mem,-1))*1024*1024*1024*1024;
7098
            break;
7099
        case 'g':
7100
            $mem = intval(substr($mem,0,-1))*1024*1024*1024;
7101
            break;
7102
        case 'm':
7103
            $mem = intval(substr($mem,0,-1))*1024*1024;
7104
            break;
7105
        case 'k':
7106
            $mem = intval(substr($mem,0,-1))*1024;
7107
            break;
7108
        default:
7109
            // we assume it's integer only
7110
            $mem = intval($mem);
7111
            break;
7112
    }
7113
    return $mem;
7114
}
7115
7116
/**
7117
 * Finds all the information about a user from username instead of user id
7118
 *
7119
 * @param string $officialCode
7120
 * @return array $user_info user_id, lastname, firstname, username, email, ...
7121
 * @author Yannick Warnier <[email protected]>
7122
 */
7123 View Code Duplication
function api_get_user_info_from_official_code($officialCode)
7124
{
7125
    if (empty($officialCode)) {
7126
        return false;
7127
    }
7128
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
7129
            WHERE official_code ='".Database::escape_string($officialCode)."'";
7130
    $result = Database::query($sql);
7131
    if (Database::num_rows($result) > 0) {
7132
        $result_array = Database::fetch_array($result);
7133
        return _api_format_user($result_array);
7134
    }
7135
    return false;
7136
}
7137
7138
/**
7139
 * @param string $usernameInputId
7140
 * @param string $passwordInputId
7141
 * @return null|string
7142
 */
7143
function api_get_password_checker_js($usernameInputId, $passwordInputId)
7144
{
7145
    $checkPass = api_get_setting('allow_strength_pass_checker');
7146
    $useStrengthPassChecker = $checkPass === 'true';
7147
7148
    if ($useStrengthPassChecker === false) {
7149
        return null;
7150
    }
7151
7152
    $translations = [
7153
        'wordLength' => get_lang('PasswordIsTooShort'),
7154
        'wordNotEmail' => get_lang('YourPasswordCannotBeTheSameAsYourEmail'),
7155
        'wordSimilarToUsername' => get_lang('YourPasswordCannotContainYourUsername'),
7156
        'wordTwoCharacterClasses' => get_lang('WordTwoCharacterClasses'),
7157
        'wordRepetitions' => get_lang('TooManyRepetitions'),
7158
        'wordSequences' => get_lang('YourPasswordContainsSequences'),
7159
        'errorList' => get_lang('ErrorsFound'),
7160
        'veryWeak' => get_lang('PasswordVeryWeak'),
7161
        'weak' => get_lang('PasswordWeak'),
7162
        'normal' => get_lang('PasswordNormal'),
7163
        'medium' => get_lang('PasswordMedium'),
7164
        'strong' => get_lang('PasswordStrong'),
7165
        'veryStrong' => get_lang('PasswordVeryStrong')
7166
    ];
7167
7168
    $js = api_get_asset('pwstrength-bootstrap/dist/pwstrength-bootstrap.min.js');
7169
    $js .=  "<script>    
7170
    var errorMessages = {
7171
        password_to_short : \"" . get_lang('PasswordIsTooShort')."\",
7172
        same_as_username : \"".get_lang('YourPasswordCannotBeTheSameAsYourUsername')."\"
7173
    };
7174
7175
    $(document).ready(function() {
7176
        var lang = ".json_encode($translations).";     
7177
        var options = {        
7178
            onLoad : function () {
7179
                //$('#messages').text('Start typing password');
7180
            },
7181
            onKeyUp: function (evt) {
7182
                $(evt.target).pwstrength('outputErrorList');
7183
            },
7184
            errorMessages : errorMessages,
7185
            viewports: {
7186
                progress: '#password_progress',
7187
                verdict: '#password-verdict',
7188
                errors: '#password-errors'
7189
            },
7190
            usernameField: '$usernameInputId'
7191
        };
7192
        options.i18n = {
7193
            t: function (key) {
7194
                var result = lang[key];
7195
                return result === key ? '' : result; // This assumes you return the                
7196
            }
7197
        };
7198
        $('".$passwordInputId."').pwstrength(options);
7199
    });
7200
    </script>";
7201
7202
    return $js;
7203
}
7204
7205
/**
7206
 * @param string $username
7207
 * create an user extra field called 'captcha_blocked_until_date'
7208
 */
7209
function api_block_account_captcha($username)
7210
{
7211
    $userInfo = api_get_user_info_from_username($username);
7212
    if (empty($userInfo)) {
7213
        return false;
7214
    }
7215
    $minutesToBlock = api_get_setting('captcha_time_to_block');
7216
    $time = time() + $minutesToBlock*60;
7217
    UserManager::update_extra_field_value(
7218
        $userInfo['user_id'],
7219
        'captcha_blocked_until_date',
7220
        api_get_utc_datetime($time)
7221
    );
7222
}
7223
7224
/**
7225
 * @param string $username
7226
 */
7227
function api_clean_account_captcha($username)
7228
{
7229
    $userInfo = api_get_user_info_from_username($username);
7230
    if (empty($userInfo)) {
7231
        return false;
7232
    }
7233
    Session::erase('loginFailedCount');
7234
    UserManager::update_extra_field_value(
7235
        $userInfo['user_id'],
7236
        'captcha_blocked_until_date',
7237
        null
7238
    );
7239
}
7240
7241
/**
7242
 * @param string $username
7243
 * @return bool
7244
 */
7245
function api_get_user_blocked_by_captcha($username)
7246
{
7247
    $userInfo = api_get_user_info_from_username($username);
7248
    if (empty($userInfo)) {
7249
        return false;
7250
    }
7251
    $data = UserManager::get_extra_user_data_by_field(
7252
        $userInfo['user_id'],
7253
        'captcha_blocked_until_date'
7254
    );
7255
    if (isset($data) && isset($data['captcha_blocked_until_date'])) {
7256
        return $data['captcha_blocked_until_date'];
7257
    }
7258
    return false;
7259
}
7260
7261
/**
7262
 * Remove tags from HTML anf return the $in_number_char first non-HTML char
7263
 * Postfix the text with "..." if it has been truncated.
7264
 * @param integer $in_number_char
7265
 * @return string
7266
 * @author hubert borderiou
7267
 */
7268
function api_get_short_text_from_html($in_html, $in_number_char)
7269
{
7270
    $out_res = api_remove_tags_with_space($in_html, false);
7271
    $postfix = "...";
7272
    if (strlen($out_res) > $in_number_char) {
7273
        $out_res = substr($out_res, 0, $in_number_char).$postfix;
7274
    }
7275
    return $out_res;
7276
}
7277
7278
/**
7279
 * Replace tags with a space in a text.
7280
 * If $in_double_quote_replace, replace " with '' (for HTML attribute purpose, for exemple)
7281
 * @return string
7282
 * @author hubert borderiou
7283
 */
7284
function api_remove_tags_with_space($in_html, $in_double_quote_replace = true) {
7285
    $out_res = $in_html;
7286
    if ($in_double_quote_replace) {
7287
        $out_res = str_replace('"', "''", $out_res);
7288
    }
7289
    // avoid text stuck together when tags are removed, adding a space after >
7290
    $out_res = str_replace (">", "> ", $out_res);
7291
    $out_res = strip_tags($out_res);
7292
7293
    return $out_res;
7294
}
7295
7296
/**
7297
 * If true, the drh can access all content (courses, users) inside a session
7298
 * @return bool
7299
 */
7300
function api_drh_can_access_all_session_content()
7301
{
7302
    $value = api_get_setting('drh_can_access_all_session_content');
7303
7304
    return $value === 'true';
7305
}
7306
7307
/**
7308
 * @param string $tool
7309
 * @param string $setting
7310
 * @param integer $defaultValue
7311
 * @return string
7312
 */
7313
function api_get_default_tool_setting($tool, $setting, $defaultValue)
7314
{
7315
    global $_configuration;
7316
    if (isset($_configuration[$tool]) &&
7317
        isset($_configuration[$tool]['default_settings']) &&
7318
        isset($_configuration[$tool]['default_settings'][$setting])
7319
    ) {
7320
        return $_configuration[$tool]['default_settings'][$setting];
7321
    }
7322
7323
    return $defaultValue;
7324
}
7325
7326
/**
7327
 * Checks if user can login as another user
7328
 *
7329
 * @param int $loginAsUserId the user id to log in
7330
 * @param int $userId my user id
7331
 * @return bool
7332
 */
7333
function api_can_login_as($loginAsUserId, $userId = null)
7334
{
7335
    if (empty($userId)) {
7336
        $userId = api_get_user_id();
7337
    }
7338
    if ($loginAsUserId == $userId) {
7339
        return false;
7340
    }
7341
7342
    if (empty($loginAsUserId)) {
7343
        return false;
7344
    }
7345
7346
    if ($loginAsUserId != strval(intval($loginAsUserId))) {
7347
        return false;
7348
    }
7349
7350
    // Check if the user to login is an admin
7351
    if (api_is_platform_admin_by_id($loginAsUserId)) {
7352
        // Only super admins can login to admin accounts
7353
        if (!api_global_admin_can_edit_admin($loginAsUserId)) {
7354
            return false;
7355
        }
7356
    }
7357
7358
    $userInfo = api_get_user_info($userId);
7359
7360
    $isDrh = function() use($loginAsUserId) {
7361
        if (api_is_drh()) {
7362
            if (api_drh_can_access_all_session_content()) {
7363
                $users = SessionManager::getAllUsersFromCoursesFromAllSessionFromStatus('drh_all', api_get_user_id());
7364
                $userList = array();
7365
                if (is_array($users)) {
7366
                    foreach ($users as $user) {
7367
                        $userList[] = $user['user_id'];
7368
                    }
7369
                }
7370
                if (in_array($loginAsUserId, $userList)) {
7371
                    return true;
7372
                }
7373
            } else {
7374
                if (api_is_drh() && UserManager::is_user_followed_by_drh($loginAsUserId, api_get_user_id())) {
7375
                    return true;
7376
                }
7377
            }
7378
        }
7379
        return false;
7380
    };
7381
7382
    return api_is_platform_admin() || (api_is_session_admin() && $userInfo['status'] == 5) || $isDrh();
7383
}
7384
7385
/**
7386
 * @return bool
7387
 */
7388
function api_is_allowed_in_course()
7389
{
7390
    if (api_is_platform_admin()) {
7391
        return true;
7392
    }
7393
7394
    return Session::read('is_allowed_in_course');
7395
}
7396
7397
/**
7398
 * Set the cookie to go directly to the course code $in_firstpage
7399
 * after login
7400
 * @param string $in_firstpage is the course code of the course to go
7401
 */
7402
function api_set_firstpage_parameter($in_firstpage)
7403
{
7404
    setcookie('GotoCourse', $in_firstpage);
7405
}
7406
7407
/**
7408
 * Delete the cookie to go directly to the course code $in_firstpage
7409
 * after login
7410
 */
7411
function api_delete_firstpage_parameter()
7412
{
7413
    setcookie('GotoCourse', '', time() - 3600);
7414
}
7415
7416
/**
7417
 * @return boolean if course_code for direct course access after login is set
7418
 */
7419
function exist_firstpage_parameter()
7420
{
7421
    return (isset($_COOKIE['GotoCourse']) && $_COOKIE['GotoCourse'] != "");
7422
}
7423
7424
/**
7425
 * @return return the course_code of the course where user login
7426
 */
7427
function api_get_firstpage_parameter()
7428
{
7429
    return $_COOKIE['GotoCourse'];
7430
}
7431
7432
/**
7433
 * Return true on https install
7434
 * @return boolean
7435
 */
7436
function api_is_https()
7437
{
7438
    return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off');
7439
}
7440
7441
/**
7442
 * Return protocol (http or https)
7443
 * @return string
7444
 */
7445
function api_get_protocol()
7446
{
7447
    return api_is_https() ? 'https' : 'http';
7448
}
7449
7450
/**
7451
 * Return a string where " are replaced with 2 '
7452
 * It is useful when you pass a PHP variable in a Javascript browser dialog
7453
 * e.g. : alert("<?php get_lang('Message') ?>");
7454
 * and message contains character "
7455
 *
7456
 * @param string $in_text
7457
 * @return string
7458
 */
7459
function convert_double_quote_to_single($in_text)
7460
{
7461
    return api_preg_replace('/"/', "''", $in_text);
7462
}
7463
7464
/**
7465
 * Get origin
7466
 *
7467
 * @param string
7468
 * @return string
7469
 **/
7470
function api_get_origin()
7471
{
7472
    if (isset($_REQUEST['origin'])) {
7473
        return $_REQUEST['origin'] === 'learnpath' ? 'learnpath' : '';
7474
    }
7475
7476
    return '';
7477
}
7478
7479
/**
7480
 * Warns an user that the portal reach certain limit.
7481
 * @param string $limitName
7482
 */
7483
function api_warn_hosting_contact($limitName)
7484
{
7485
    $hostingParams = api_get_configuration_value(1);
7486
    $email = null;
7487
7488
    if (!empty($hostingParams)) {
7489
        if (isset($hostingParams['hosting_contact_mail'])) {
7490
            $email = $hostingParams['hosting_contact_mail'];
7491
        }
7492
    }
7493
7494
    if (!empty($email)) {
7495
        $subject = get_lang('HostingWarningReached');
7496
        $body = get_lang('PortalName').': '.api_get_path(WEB_PATH)." \n ";
7497
        $body .= get_lang('PortalLimitType').': '.$limitName." \n ";
7498
        if (isset($hostingParams[$limitName])) {
7499
            $body .= get_lang('Value') . ': ' . $hostingParams[$limitName];
7500
        }
7501
        api_mail_html(null, $email, $subject, $body);
7502
    }
7503
}
7504
7505
/**
7506
 * @param string $variable
7507
 * @return bool|mixed
7508
 */
7509
function api_get_configuration_value($variable)
7510
{
7511
    global $_configuration;
7512
    if (isset($_configuration[$variable])) {
7513
        return $_configuration[$variable];
7514
    }
7515
    return false;
7516
}
7517
7518
/**
7519
 * Returns supported image extensions in the portal
7520
 * @param   bool    $supportVectors Whether vector images should also be accepted or not
7521
 * @return  array   Supported image extensions in the portal
7522
 */
7523
function api_get_supported_image_extensions($supportVectors = true)
7524
{
7525
    // jpg can also be called jpeg, jpe, jfif and jif. See https://en.wikipedia.org/wiki/JPEG#JPEG_filename_extensions
7526
    $supportedImageExtensions = array('jpg', 'jpeg', 'png', 'gif', 'jpe', 'jfif', 'jif');
7527
    if ($supportVectors) {
7528
        array_push($supportedImageExtensions, 'svg');
7529
    }
7530
    if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
7531
        array_push($supportedImageExtensions, 'webp');
7532
    }
7533
    return $supportedImageExtensions;
7534
}
7535
7536
/**
7537
 * This setting changes the registration status for the campus
7538
 *
7539
 * @author Patrick Cool <[email protected]>, Ghent University
7540
 * @version August 2006
7541
 * @param   bool    $listCampus Whether we authorize
7542
 * @todo the $_settings should be reloaded here. => write api function for this and use this in global.inc.php also.
7543
 */
7544 View Code Duplication
function api_register_campus($listCampus = true) {
7545
    $tbl_settings = Database :: get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
7546
7547
    $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='registered'";
7548
    Database::query($sql);
7549
7550
    if (!$listCampus) {
7551
        $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='donotlistcampus'";
7552
        Database::query($sql);
7553
    }
7554
}
7555
7556
/**
7557
 * Checks whether current user is a student boss
7558
 * @global array $_user
7559
 * @return boolean
7560
 */
7561
function api_is_student_boss()
7562
{
7563
    $_user = api_get_user_info();
7564
7565
    return isset($_user['status']) && $_user['status'] == STUDENT_BOSS;
7566
}
7567
7568
/**
7569
 * Check whether the user type should be exclude.
7570
 * Such as invited or anonymous users
7571
 * @param boolean $checkDB Optional. Whether check the user status
7572
 * @param int $userId Options. The user id
7573
 *
7574
 * @return boolean
7575
 */
7576
function api_is_excluded_user_type($checkDB = false, $userId = 0)
7577
{
7578
    if ($checkDB) {
7579
        $userId = empty($userId) ? api_get_user_id() : intval($userId);
7580
7581
        if ($userId == 0) {
7582
            return true;
7583
        }
7584
7585
        $userInfo = api_get_user_info($userId);
7586
7587
        switch ($userInfo['status']) {
7588
            case INVITEE:
7589
                //no break;
7590
            case ANONYMOUS:
7591
                return true;
7592
            default:
7593
                return false;
7594
        }
7595
    }
7596
7597
    $isInvited = api_is_invitee();
7598
    $isAnonymous = api_is_anonymous();
7599
7600
    if ($isInvited || $isAnonymous) {
7601
        return true;
7602
    }
7603
7604
    return false;
7605
}
7606
7607
/**
7608
 * Get the user status to ignore in reports
7609
 * @param string $format Optional. The result type (array or string)
7610
 * @return array|string
7611
 */
7612
function api_get_users_status_ignored_in_reports($format = 'array')
7613
{
7614
    $excludedTypes = array(
7615
        INVITEE,
7616
        ANONYMOUS
7617
    );
7618
7619
    if ($format == 'string') {
7620
        return implode(', ', $excludedTypes);
7621
    }
7622
7623
    return $excludedTypes;
7624
}
7625
7626
/**
7627
 * Set the Site Use Cookie Warning for 1 year
7628
 */
7629
function api_set_site_use_cookie_warning_cookie()
7630
{
7631
    setcookie('ChamiloUsesCookies', 'ok', time()+31556926);
7632
}
7633
7634
/**
7635
 * Return true if the Site Use Cookie Warning Cookie warning exists
7636
 * @return bool
7637
 */
7638
function api_site_use_cookie_warning_cookie_exist()
7639
{
7640
    return isset($_COOKIE['ChamiloUsesCookies']);
7641
}
7642
7643
/**
7644
 * Given a number of seconds, format the time to show hours, minutes and seconds
7645
 * @param int $time The time in seconds
7646
 * @param string $originFormat Optional. PHP o JS
7647
 * @return string (00h00'00")
7648
 */
7649
function api_format_time($time, $originFormat = 'php')
7650
{
7651
    $h = get_lang('h');
7652
    $hours = $time / 3600;
7653
    $mins = ($time % 3600) / 60;
7654
    $secs = ($time % 60);
7655
7656
    if ($time < 0) {
7657
        $hours = 0;
7658
        $mins = 0;
7659
        $secs = 0;
7660
    }
7661
7662
    if ($originFormat == 'js') {
7663
        $formattedTime = trim(sprintf("%02d : %02d : %02d", $hours, $mins, $secs));
7664
    } else {
7665
        $formattedTime = trim(sprintf("%02d$h%02d'%02d\"", $hours, $mins, $secs));
7666
    }
7667
7668
    return $formattedTime;
7669
}
7670
7671
/**
7672
 * Create a new empty directory with index.html file
7673
 * @param string $name The new directory name
7674
 * @param string $parentDirectory Directory parent directory name
7675
 * @return boolean Return true if the directory was create. Otherwise return false
7676
 */
7677
function api_create_protected_dir($name, $parentDirectory)
7678
{
7679
    $isCreated = false;
7680
7681
    if (!is_writable($parentDirectory)) {
7682
        return false;
7683
    }
7684
7685
    $fullPath = $parentDirectory . api_replace_dangerous_char($name);
7686
7687
    if (mkdir($fullPath, api_get_permissions_for_new_directories(), true)) {
7688
        $fp = fopen($fullPath . '/index.html', 'w');
7689
7690
        if ($fp) {
7691
            if (fwrite($fp, '<html><head></head><body></body></html>')) {
7692
                $isCreated = true;
7693
            }
7694
        }
7695
7696
        fclose($fp);
7697
    }
7698
7699
    return $isCreated;
7700
}
7701
7702
/**
7703
 * Sends an HTML email using the phpmailer class (and multipart/alternative to downgrade gracefully)
7704
 * Sender name and email can be specified, if not specified
7705
 * name and email of the platform admin are used
7706
 *
7707
 * @author Bert Vanderkimpen ICT&O UGent
7708
 * @author Yannick Warnier <[email protected]>
7709
 *
7710
 * @param string    name of recipient
7711
 * @param string    email of recipient
7712
 * @param string    email subject
7713
 * @param string    email body
7714
 * @param string    sender name
7715
 * @param string    sender e-mail
7716
 * @param array     extra headers in form $headers = array($name => $value) to allow parsing
7717
 * @param array     data file (path and filename)
7718
 * @param bool      True for attaching a embedded file inside content html (optional)
7719
 * @param array     Additional parameters
7720
 * @return          integer true if mail was sent
7721
 * @see             class.phpmailer.php
7722
 */
7723
function api_mail_html(
7724
    $recipient_name,
7725
    $recipient_email,
7726
    $subject,
7727
    $message,
7728
    $senderName = '',
7729
    $senderEmail = '',
7730
    $extra_headers = array(),
7731
    $data_file = array(),
7732
    $embedded_image = false,
7733
    $additionalParameters = array()
7734
) {
7735
    global $platform_email;
7736
7737
    $mail = new PHPMailer();
7738
    $mail->Mailer = $platform_email['SMTP_MAILER'];
7739
    $mail->Host = $platform_email['SMTP_HOST'];
7740
    $mail->Port = $platform_email['SMTP_PORT'];
7741
    $mail->CharSet = $platform_email['SMTP_CHARSET'];
7742
    // Stay far below SMTP protocol 980 chars limit.
7743
    $mail->WordWrap = 200;
7744
7745
    if ($platform_email['SMTP_AUTH']) {
7746
        $mail->SMTPAuth = 1;
7747
        $mail->Username = $platform_email['SMTP_USER'];
7748
        $mail->Password = $platform_email['SMTP_PASS'];
7749
        if (isset($platform_email['SMTP_SECURE'])) {
7750
            $mail->SMTPSecure = $platform_email['SMTP_SECURE'];
7751
        }
7752
    }
7753
    $mail->SMTPDebug = isset($platform_email['SMTP_DEBUG'])?$platform_email['SMTP_DEBUG']:0;
7754
7755
    // 5 = low, 1 = high
7756
    $mail->Priority = 3;
7757
    $mail->SMTPKeepAlive = true;
7758
7759
    // Default values
7760
    $notification = new Notification();
7761
    $defaultEmail = $notification->getDefaultPlatformSenderEmail();
7762
    $defaultName = $notification->getDefaultPlatformSenderName();
7763
7764
    // If the parameter is set don't use the admin.
7765
    $senderName = !empty($senderName) ? $senderName : $defaultName;
7766
    $senderEmail = !empty($senderEmail) ? $senderEmail : $defaultEmail;
7767
7768
    // Reply to first
7769
    if (isset($extra_headers['reply_to'])) {
7770
        $mail->AddReplyTo(
7771
            $extra_headers['reply_to']['mail'],
7772
            $extra_headers['reply_to']['name']
7773
        );
7774
            // Errors to sender
7775
        $mail->AddCustomHeader('Errors-To: '.$extra_headers['reply_to']['mail']);
7776
        $mail->Sender = $extra_headers['reply_to']['mail'];
7777
        unset($extra_headers['reply_to']);
7778
    } else {
7779
        $mail->AddCustomHeader('Errors-To: '.$defaultEmail);
7780
    }
7781
7782
    //If the SMTP configuration only accept one sender
7783
    if (isset($platform_email['SMTP_UNIQUE_SENDER']) && $platform_email['SMTP_UNIQUE_SENDER']) {
7784
        $senderName = $platform_email['SMTP_FROM_NAME'];
7785
        $senderEmail = $platform_email['SMTP_FROM_EMAIL'];
7786
    }
7787
    $mail->SetFrom($senderEmail, $senderName);
7788
    $mail->Subject = $subject;
7789
    $mail->AltBody = strip_tags(
7790
        str_replace('<br />', "\n", api_html_entity_decode($message))
7791
    );
7792
7793
    // Send embedded image.
7794
    if ($embedded_image) {
7795
        // Get all images html inside content.
7796
        preg_match_all("/<img\s+.*?src=[\"\']?([^\"\' >]*)[\"\']?[^>]*>/i", $message, $m);
7797
        // Prepare new tag images.
7798
        $new_images_html = array();
7799
        $i = 1;
7800
        if (!empty($m[1])) {
7801
            foreach ($m[1] as $image_path) {
7802
                $real_path = realpath($image_path);
7803
                $filename  = basename($image_path);
7804
                $image_cid = $filename.'_'.$i;
7805
                $encoding = 'base64';
7806
                $image_type = mime_content_type($real_path);
7807
                $mail->AddEmbeddedImage(
7808
                    $real_path,
7809
                    $image_cid,
7810
                    $filename,
7811
                    $encoding,
7812
                    $image_type
7813
                );
7814
                $new_images_html[] = '<img src="cid:'.$image_cid.'" />';
7815
                $i++;
7816
            }
7817
        }
7818
7819
        // Replace origin image for new embedded image html.
7820
        $x = 0;
7821
        if (!empty($m[0])) {
7822
            foreach ($m[0] as $orig_img) {
7823
                $message = str_replace($orig_img, $new_images_html[$x], $message);
7824
                $x++;
7825
            }
7826
        }
7827
    }
7828
7829
    $mailView = new Template(null, false, false, false, false, false, false);
7830
    $mailView->assign('content', $message);
7831
7832
    if (isset($additionalParameters['link'])) {
7833
        $mailView->assign('link', $additionalParameters['link']);
7834
    }
7835
    $mailView->assign('mail_header_style', api_get_configuration_value('mail_header_style'));
7836
    $mailView->assign('mail_content_style', api_get_configuration_value('mail_content_style'));
7837
    $layout = $mailView->get_template('mail/mail.tpl');
7838
    $mail->Body = $mailView->fetch($layout);
7839
7840
    // Attachment ...
7841
    if (!empty($data_file)) {
7842
        $o = 0;
7843
        foreach ($data_file as $file_attach) {
7844
            if (!empty($file_attach['path']) && !empty($file_attach['filename'])) {
7845
                $mail->AddAttachment($file_attach['path'], $file_attach['filename']);
7846
            }
7847
            $o++;
7848
        }
7849
    }
7850
7851
    // Only valid addresses are accepted.
7852
    if (is_array($recipient_email)) {
7853
        foreach ($recipient_email as $dest) {
7854
            if (api_valid_email($dest)) {
7855
                $mail->AddAddress($dest, $recipient_name);
7856
            }
7857
        }
7858
    } else {
7859
        if (api_valid_email($recipient_email)) {
7860
            $mail->AddAddress($recipient_email, $recipient_name);
7861
        } else {
7862
            return 0;
7863
        }
7864
    }
7865
7866
    if (is_array($extra_headers) && count($extra_headers) > 0) {
7867
        foreach ($extra_headers as $key => $value) {
7868
            switch (strtolower($key)) {
7869
                case 'encoding':
7870
                case 'content-transfer-encoding':
7871
                    $mail->Encoding = $value;
7872
                    break;
7873
                case 'charset':
7874
                    $mail->Charset = $value;
7875
                    break;
7876
                case 'contenttype':
7877
                case 'content-type':
7878
                    $mail->ContentType = $value;
7879
                    break;
7880
                default:
7881
                    $mail->AddCustomHeader($key.':'.$value);
7882
                    break;
7883
            }
7884
        }
7885
    } else {
7886
        if (!empty($extra_headers)) {
7887
            $mail->AddCustomHeader($extra_headers);
7888
        }
7889
    }
7890
7891
    // WordWrap the html body (phpMailer only fixes AltBody) FS#2988
7892
    $mail->Body = $mail->WrapText($mail->Body, $mail->WordWrap);
7893
7894
    // Send the mail message.
7895
    if (!$mail->Send()) {
7896
        error_log('ERROR: mail not sent to '.$recipient_name.' ('.$recipient_email.') because of '.$mail->ErrorInfo.'<br />');
7897
        if ($mail->SMTPDebug) {
7898
            error_log(
7899
                "Connection details :: " .
7900
                "Protocol: " . $mail->Mailer . ' :: ' .
7901
                "Host/Port: " . $mail->Host . ':' . $mail->Port . ' :: ' .
7902
                "Authent/Open: " . ($mail->SMTPAuth?'Authent':'Open') . ' :: ' .
7903
                ($mail->SMTPAuth?"  User/Pass: " . $mail->Username . ':' . $mail->Password:'')
7904
            );
7905
        }
7906
        return 0;
7907
    }
7908
7909
    if (!empty($additionalParameters)) {
7910
        $plugin = new AppPlugin();
7911
        $smsPlugin = $plugin->getSMSPluginLibrary();
7912
        if ($smsPlugin) {
7913
            $smsPlugin->send($additionalParameters);
7914
        }
7915
    }
7916
7917
    // Clear all the addresses.
7918
    $mail->ClearAddresses();
7919
7920
    // Clear all attachments
7921
    $mail->ClearAttachments();
7922
7923
    return 1;
7924
}
7925
7926
/**
7927
 * @param string $tool Possible values:
7928
 * GroupManager::GROUP_TOOL_*
7929
 *
7930
 */
7931
function api_protect_course_group($tool, $showHeader = true)
7932
{
7933
    $userId = api_get_user_id();
7934
    $groupId = api_get_group_id();
7935
    $groupInfo = GroupManager::get_group_properties($groupId);
7936
7937
    if (!empty($groupInfo)) {
7938
        $allow = GroupManager::user_has_access(
7939
            $userId,
7940
            $groupInfo['iid'],
7941
            $tool
7942
        );
7943
7944
        if (!$allow) {
7945
            api_not_allowed($showHeader);
7946
        }
7947
    }
7948
}
7949
7950
/**
7951
 * Check if a date is in a date range
7952
 *
7953
 * @param datetime $startDate
7954
 * @param datetime $endDate
7955
 * @param datetime $currentDate
7956
 * @return bool true if date is in rage, false otherwise
7957
 */
7958
function api_is_date_in_date_range($startDate, $endDate, $currentDate = null)
7959
{
7960
    $startDate = strtotime(api_get_local_time($startDate));
7961
    $endDate = strtotime(api_get_local_time($endDate));
7962
    $currentDate = strtotime(api_get_local_time($currentDate));
7963
7964
    if ($currentDate >= $startDate && $currentDate <= $endDate) {
7965
        return true;
7966
    }
7967
7968
    return false;
7969
}
7970
7971
/**
7972
 * Eliminate the duplicates of a multidimensional array by sending the key
7973
 *
7974
 * @param array $array multidimensional array
7975
 * @param int $key key to find to compare
7976
 * @return array
7977
 *
7978
 */
7979
function api_unique_multidim_array($array, $key){
7980
    $temp_array = [];
7981
    $i = 0;
7982
    $key_array = [];
7983
7984
    foreach($array as $val){
7985
        if(!in_array($val[$key],$key_array)){
7986
            $key_array[$i] = $val[$key];
7987
            $temp_array[$i] = $val;
7988
        }
7989
        $i++;
7990
    }
7991
    return $temp_array;
7992
}
7993
7994
/**
7995
 * Limit the access to Session Admins wheen the limit_session_admin_role
7996
 * configuration variable is set to true
7997
 */
7998
function api_protect_limit_for_session_admin()
7999
{
8000
    $limitAdmin = api_get_setting('limit_session_admin_role');
8001
    if (api_is_session_admin() && $limitAdmin === 'true') {
8002
        api_not_allowed(true);
8003
    }
8004
}
8005
8006
function api_is_student_view_active() {
8007
    $studentView = Session::read('studentview');
8008
    return $studentView == 'studentview';
8009
}
8010
8011
/**
8012
 * Adds a file inside the upload/$type/id
8013
 *
8014
 * @param string $type
8015
 * @param array $file
8016
 * @param int $itemId
8017
 * @param string $cropParameters
8018
 * @return array|bool
8019
 */
8020
function api_upload_file($type, $file, $itemId, $cropParameters = '')
8021
{
8022
    $upload = process_uploaded_file($file);
8023
    if ($upload) {
8024
        $name = api_replace_dangerous_char($file['name']);
8025
8026
        // No "dangerous" files
8027
        $name = disable_dangerous_file($name);
8028
8029
        $pathId = '/'.substr((string)$itemId, 0, 1).'/'.$itemId.'/';
8030
        $path = api_get_path(SYS_UPLOAD_PATH).$type.$pathId;
8031
8032
        if (!is_dir($path)) {
8033
            mkdir($path, api_get_permissions_for_new_directories(), true);
8034
        }
8035
8036
        $pathToSave = $path.$name;
8037
8038
        $result = move_uploaded_file($file['tmp_name'], $pathToSave);
8039
        if ($result) {
8040
            if (!empty($cropParameters)) {
8041
                $image = new Image($pathToSave);
8042
                $image->crop($cropParameters);
8043
            }
8044
8045
            return ['path_to_save' => $pathId.$name];
8046
        }
8047
        return false;
8048
    }
8049
}
8050
8051
/**
8052
 * @param string $type
8053
 * @param string $file
8054
 */
8055
function api_remove_uploaded_file($type, $file)
8056
{
8057
    $path = api_get_path(SYS_UPLOAD_PATH).$type.'/'.$file;
8058
    if (file_exists($path)) {
8059
        unlink($path);
8060
    }
8061
}
8062
8063
/**
8064
 * Converts string value to float value
8065
 *
8066
 * 3.141516 => 3.141516
8067
 * 3,141516 => 3.141516
8068
 * @todo WIP
8069
 *
8070
 * @param string $number
8071
 * @return float
8072
 */
8073
function api_float_val($number)
8074
{
8075
    $number = (float) str_replace(',', '.', trim($number));
8076
    return $number;
8077
}
8078
8079
/**
8080
 * Converts float values
8081
 * Example if $decimals = 2
8082
 *
8083
 * 3.141516 => 3.14
8084
 * 3,141516 => 3,14
8085
 *
8086
 * @todo WIP
8087
 *
8088
 * @param string $number number in iso code
8089
 * @param int $decimals
8090
 * @return bool|string
8091
 */
8092
function api_number_format($number, $decimals = 0)
8093
{
8094
    $number = api_float_val($number);
8095
8096
    return number_format($number, $decimals);
8097
}
8098
8099
/**
8100
 * Set location url with a exit break by default
8101
 *
8102
 * @param $url
8103
 * @param bool $exit
8104
 * @return void
8105
 */
8106
function location($url, $exit = true)
8107
{
8108
    header('Location: ' . $url);
8109
8110
    if ($exit) {
8111
        exit;
8112
    }
8113
}
8114