Test Setup Failed
Push — master ( 4e700f...c7183e )
by Julito
63:12
created

api.lib.php ➔ api_add_setting()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 57
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 40
nc 8
nop 11
dl 0
loc 57
rs 9.0309
c 0
b 0
f 0

How to fix   Long Method    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use ChamiloSession as Session;
5
use Chamilo\CourseBundle\Entity\CItemProperty;
6
use Symfony\Component\Validator\Constraints as Assert;
7
use Chamilo\UserBundle\Entity\User;
8
use Chamilo\CoreBundle\Entity\Course;
9
use Chamilo\CoreBundle\Framework\Container;
10
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
11
use Symfony\Component\Finder\Finder;
12
use Chamilo\CoreBundle\Entity\SettingsCurrent;
13
14
/**
15
 * This is a code library for Chamilo.
16
 * It is included by default in every Chamilo file (through including the global.inc.php)
17
 * This library is in process of being transferred to src/Chamilo/CoreBundle/Component/Utils/ChamiloApi.
18
 * Whenever a function is transferred to the ChamiloApi class, the places where it is used should include
19
 * the "use Chamilo\CoreBundle\Component\Utils\ChamiloApi;" statement.
20
 * @package chamilo.library
21
 */
22
23
/**
24
 * Constants declaration
25
 */
26
27
// PHP version requirement.
28
define('REQUIRED_PHP_VERSION', '7.0');
29
define('REQUIRED_MIN_MEMORY_LIMIT', '128');
30
define('REQUIRED_MIN_UPLOAD_MAX_FILESIZE', '10');
31
define('REQUIRED_MIN_POST_MAX_SIZE', '10');
32
33
// USER STATUS CONSTANTS
34
/** global status of a user: student */
35
define('STUDENT', 5);
36
/** global status of a user: course manager */
37
define('COURSEMANAGER', 1);
38
/** global status of a user: session admin */
39
define('SESSIONADMIN', 3);
40
/** global status of a user: human ressource manager */
41
define('DRH', 4);
42
/** global status of a user: human ressource manager */
43
define('ANONYMOUS', 6);
44
/** global status of a user: low security, necessary for inserting data from
45
 * the teacher through HTMLPurifier */
46
define('COURSEMANAGERLOWSECURITY', 10);
47
// Soft user status
48
define('PLATFORM_ADMIN', 11);
49
define('SESSION_COURSE_COACH', 12);
50
define('SESSION_GENERAL_COACH', 13);
51
define('COURSE_STUDENT', 14); //student subscribed in a course
52
define('SESSION_STUDENT', 15); //student subscribed in a session course
53
define('COURSE_TUTOR', 16); // student is tutor of a course (NOT in session)
54
define('STUDENT_BOSS', 17); // student is boss
55
define('INVITEE', 20);
56
57
// Table of status
58
$_status_list[COURSEMANAGER] = 'teacher'; // 1
59
$_status_list[SESSIONADMIN] = 'session_admin'; // 3
60
$_status_list[DRH] = 'drh'; // 4
61
$_status_list[STUDENT] = 'user'; // 5
62
$_status_list[ANONYMOUS] = 'anonymous'; // 6
63
$_status_list[INVITEE] = 'invited'; // 20
64
65
// COURSE VISIBILITY CONSTANTS
66
/** only visible for course admin */
67
define('COURSE_VISIBILITY_CLOSED', 0);
68
/** only visible for users registered in the course */
69
define('COURSE_VISIBILITY_REGISTERED', 1);
70
/** Open for all registered users on the platform */
71
define('COURSE_VISIBILITY_OPEN_PLATFORM', 2);
72
/** Open for the whole world */
73
define('COURSE_VISIBILITY_OPEN_WORLD', 3);
74
/** Invisible to all except admin */
75
define('COURSE_VISIBILITY_HIDDEN', 4);
76
77
define('COURSE_REQUEST_PENDING', 0);
78
define('COURSE_REQUEST_ACCEPTED', 1);
79
define('COURSE_REQUEST_REJECTED', 2);
80
define('DELETE_ACTION_ENABLED', false);
81
82
// EMAIL SENDING RECIPIENT CONSTANTS
83
define('SEND_EMAIL_EVERYONE', 1);
84
define('SEND_EMAIL_STUDENTS', 2);
85
define('SEND_EMAIL_TEACHERS', 3);
86
87
// SESSION VISIBILITY CONSTANTS
88
define('SESSION_VISIBLE_READ_ONLY', 1);
89
define('SESSION_VISIBLE', 2);
90
define('SESSION_INVISIBLE', 3); // not available
91
define('SESSION_AVAILABLE', 4);
92
93
define('SESSION_LINK_TARGET', '_self');
94
95
define('SUBSCRIBE_ALLOWED', 1);
96
define('SUBSCRIBE_NOT_ALLOWED', 0);
97
define('UNSUBSCRIBE_ALLOWED', 1);
98
define('UNSUBSCRIBE_NOT_ALLOWED', 0);
99
100
// SURVEY VISIBILITY CONSTANTS
101
define('SURVEY_VISIBLE_TUTOR', 0);
102
define('SURVEY_VISIBLE_TUTOR_STUDENT', 1);
103
define('SURVEY_VISIBLE_PUBLIC', 2);
104
105
// CONSTANTS defining all tools, using the english version
106
/* When you add a new tool you must add it into function api_get_tools_lists() too */
107
define('TOOL_DOCUMENT', 'document');
108
define('TOOL_LP_FINAL_ITEM', 'final_item');
109
define('TOOL_THUMBNAIL', 'thumbnail');
110
define('TOOL_HOTPOTATOES', 'hotpotatoes');
111
define('TOOL_CALENDAR_EVENT', 'calendar_event');
112
define('TOOL_LINK', 'link');
113
define('TOOL_LINK_CATEGORY', 'link_category');
114
define('TOOL_COURSE_DESCRIPTION', 'course_description');
115
define('TOOL_SEARCH', 'search');
116
define('TOOL_LEARNPATH', 'learnpath');
117
define('TOOL_LEARNPATH_CATEGORY', 'learnpath_category');
118
define('TOOL_AGENDA', 'agenda');
119
define('TOOL_ANNOUNCEMENT', 'announcement');
120
define('TOOL_FORUM', 'forum');
121
define('TOOL_FORUM_CATEGORY', 'forum_category');
122
define('TOOL_FORUM_THREAD', 'forum_thread');
123
define('TOOL_FORUM_POST', 'forum_post');
124
define('TOOL_FORUM_ATTACH', 'forum_attachment');
125
define('TOOL_FORUM_THREAD_QUALIFY', 'forum_thread_qualify');
126
define('TOOL_THREAD', 'thread');
127
define('TOOL_POST', 'post');
128
define('TOOL_DROPBOX', 'dropbox');
129
define('TOOL_QUIZ', 'quiz');
130
define('TOOL_TEST_CATEGORY', 'test_category');
131
define('TOOL_USER', 'user');
132
define('TOOL_GROUP', 'group');
133
define('TOOL_BLOGS', 'blog_management');
134
define('TOOL_CHAT', 'chat');
135
define('TOOL_STUDENTPUBLICATION', 'student_publication');
136
define('TOOL_TRACKING', 'tracking');
137
define('TOOL_HOMEPAGE_LINK', 'homepage_link');
138
define('TOOL_COURSE_SETTING', 'course_setting');
139
define('TOOL_BACKUP', 'backup');
140
define('TOOL_COPY_COURSE_CONTENT', 'copy_course_content');
141
define('TOOL_RECYCLE_COURSE', 'recycle_course');
142
define('TOOL_COURSE_HOMEPAGE', 'course_homepage');
143
define('TOOL_COURSE_RIGHTS_OVERVIEW', 'course_rights');
144
define('TOOL_UPLOAD', 'file_upload');
145
define('TOOL_COURSE_MAINTENANCE', 'course_maintenance');
146
define('TOOL_SURVEY', 'survey');
147
define('TOOL_WIKI', 'wiki');
148
define('TOOL_GLOSSARY', 'glossary');
149
define('TOOL_GRADEBOOK', 'gradebook');
150
define('TOOL_NOTEBOOK', 'notebook');
151
define('TOOL_ATTENDANCE', 'attendance');
152
define('TOOL_COURSE_PROGRESS', 'course_progress');
153
154
// CONSTANTS defining Chamilo interface sections
155
define('SECTION_CAMPUS', 'mycampus');
156
define('SECTION_COURSES', 'mycourses');
157
define('SECTION_CATALOG', 'catalog');
158
define('SECTION_MYPROFILE', 'myprofile');
159
define('SECTION_MYAGENDA', 'myagenda');
160
define('SECTION_COURSE_ADMIN', 'course_admin');
161
define('SECTION_PLATFORM_ADMIN', 'platform_admin');
162
define('SECTION_MYGRADEBOOK', 'mygradebook');
163
define('SECTION_TRACKING', 'session_my_space');
164
define('SECTION_SOCIAL', 'social-network');
165
define('SECTION_DASHBOARD', 'dashboard');
166
define('SECTION_REPORTS', 'reports');
167
define('SECTION_GLOBAL', 'global');
168
169
// CONSTANT name for local authentication source
170
define('PLATFORM_AUTH_SOURCE', 'platform');
171
define('CAS_AUTH_SOURCE', 'cas');
172
define('LDAP_AUTH_SOURCE', 'extldap');
173
174
// CONSTANT defining the default HotPotatoes files directory
175
define('DIR_HOTPOTATOES', '/HotPotatoes_files');
176
177
// event logs types
178
define('LOG_COURSE_DELETE', 'course_deleted');
179
define('LOG_COURSE_CREATE', 'course_created');
180
181
// @todo replace 'soc_gr' with social_group
182
define('LOG_GROUP_PORTAL_CREATED', 'soc_gr_created');
183
define('LOG_GROUP_PORTAL_UPDATED', 'soc_gr_updated');
184
define('LOG_GROUP_PORTAL_DELETED', 'soc_gr_deleted');
185
define('LOG_GROUP_PORTAL_USER_DELETE_ALL', 'soc_gr_delete_users');
186
187
define('LOG_GROUP_PORTAL_ID', 'soc_gr_portal_id');
188
define('LOG_GROUP_PORTAL_REL_USER_ARRAY', 'soc_gr_user_array');
189
190
define('LOG_GROUP_PORTAL_USER_SUBSCRIBED', 'soc_gr_u_subs');
191
define('LOG_GROUP_PORTAL_USER_UNSUBSCRIBED', 'soc_gr_u_unsubs');
192
define('LOG_GROUP_PORTAL_USER_UPDATE_ROLE', 'soc_gr_update_role');
193
194
define('LOG_USER_DELETE', 'user_deleted');
195
define('LOG_USER_CREATE', 'user_created');
196
define('LOG_USER_ENABLE', 'user_enable');
197
define('LOG_USER_DISABLE', 'user_disable');
198
define('LOG_USER_FIELD_CREATE', 'user_field_created');
199
define('LOG_USER_FIELD_DELETE', 'user_field_deleted');
200
define('LOG_SESSION_CREATE', 'session_created');
201
define('LOG_SESSION_DELETE', 'session_deleted');
202
define('LOG_SESSION_ADD_USER_COURSE', 'session_add_user_course');
203
define('LOG_SESSION_DELETE_USER_COURSE', 'session_delete_user_course');
204
define('LOG_SESSION_DELETE_USER', 'session_delete_user');
205
define('LOG_SESSION_ADD_COURSE', 'session_add_course');
206
define('LOG_SESSION_DELETE_COURSE', 'session_delete_course');
207
208
define('LOG_SESSION_CATEGORY_CREATE', 'session_cat_created'); //changed in 1.9.8
209
define('LOG_SESSION_CATEGORY_DELETE', 'session_cat_deleted'); //changed in 1.9.8
210
define('LOG_CONFIGURATION_SETTINGS_CHANGE', 'settings_changed');
211
define('LOG_PLATFORM_LANGUAGE_CHANGE', 'platform_lng_changed'); //changed in 1.9.8
212
define('LOG_SUBSCRIBE_USER_TO_COURSE', 'user_subscribed');
213
define('LOG_UNSUBSCRIBE_USER_FROM_COURSE', 'user_unsubscribed');
214
define('LOG_ATTEMPTED_FORCED_LOGIN', 'attempted_forced_login');
215
216
define('LOG_HOMEPAGE_CHANGED', 'homepage_changed');
217
218
define('LOG_PROMOTION_CREATE', 'promotion_created');
219
define('LOG_PROMOTION_DELETE', 'promotion_deleted');
220
define('LOG_CAREER_CREATE', 'career_created');
221
define('LOG_CAREER_DELETE', 'career_deleted');
222
223
define('LOG_USER_PERSONAL_DOC_DELETED', 'user_doc_deleted');
224
define('LOG_WIKI_ACCESS', 'wiki_page_view');
225
226
define('LOG_EXERCISE_RESULT_DELETE', 'exe_result_deleted');
227
define('LOG_LP_ATTEMPT_DELETE', 'lp_attempt_deleted');
228
define('LOG_QUESTION_RESULT_DELETE', 'qst_attempt_deleted');
229
230
define('LOG_MY_FOLDER_CREATE', 'my_folder_created');
231
define('LOG_MY_FOLDER_CHANGE', 'my_folder_changed');
232
define('LOG_MY_FOLDER_DELETE', 'my_folder_deleted');
233
define('LOG_MY_FOLDER_COPY', 'my_folder_copied');
234
define('LOG_MY_FOLDER_CUT', 'my_folder_cut');
235
define('LOG_MY_FOLDER_PASTE', 'my_folder_pasted');
236
define('LOG_MY_FOLDER_UPLOAD', 'my_folder_uploaded');
237
238
// Event logs data types (max 20 chars)
239
define('LOG_COURSE_CODE', 'course_code');
240
define('LOG_COURSE_ID', 'course_id');
241
define('LOG_USER_ID', 'user_id');
242
define('LOG_USER_OBJECT', 'user_object');
243
define('LOG_USER_FIELD_VARIABLE', 'user_field_variable');
244
define('LOG_SESSION_ID', 'session_id');
245
define('LOG_SESSION_CATEGORY_ID', 'session_category_id');
246
define('LOG_CONFIGURATION_SETTINGS_CATEGORY', 'settings_category');
247
define('LOG_CONFIGURATION_SETTINGS_VARIABLE', 'settings_variable');
248
define('LOG_PLATFORM_LANGUAGE', 'default_platform_language');
249
define('LOG_CAREER_ID', 'career_id');
250
define('LOG_PROMOTION_ID', 'promotion_id');
251
define('LOG_GRADEBOOK_LOCKED', 'gradebook_locked');
252
define('LOG_GRADEBOOK_UNLOCKED', 'gradebook_unlocked');
253
define('LOG_GRADEBOOK_ID', 'gradebook_id');
254
define('LOG_WIKI_PAGE_ID', 'wiki_page_id');
255
define('LOG_EXERCISE_ID', 'exercise_id');
256
define('LOG_EXERCISE_AND_USER_ID', 'exercise_and_user_id');
257
define('LOG_LP_ID', 'lp_id');
258
define('LOG_EXERCISE_ATTEMPT_QUESTION_ID', 'exercise_a_q_id');
259
260
define('LOG_WORK_DIR_DELETE', 'work_dir_delete');
261
define('LOG_WORK_FILE_DELETE', 'work_file_delete');
262
define('LOG_WORK_DATA', 'work_data_array');
263
264
define('LOG_MY_FOLDER_PATH', 'path');
265
define('LOG_MY_FOLDER_NEW_PATH', 'new_path');
266
267
define('USERNAME_PURIFIER', '/[^0-9A-Za-z_\.]/');
268
269
//used when login_is_email setting is true
270
define('USERNAME_PURIFIER_MAIL', '/[^0-9A-Za-z_\.@]/');
271
define('USERNAME_PURIFIER_SHALLOW', '/\s/');
272
273
// This constant is a result of Windows OS detection, it has a boolean value:
274
// true whether the server runs on Windows OS, false otherwise.
275
define('IS_WINDOWS_OS', api_is_windows_os());
276
277
// Checks for installed optional php-extensions.
278
define('INTL_INSTALLED', function_exists('intl_get_error_code')); // intl extension (from PECL), it is installed by default as of PHP 5.3.0
279
define('ICONV_INSTALLED', function_exists('iconv')); // iconv extension, for PHP5 on Windows it is installed by default.
280
define('MBSTRING_INSTALLED', function_exists('mb_strlen')); // mbstring extension.
281
282
// Patterns for processing paths.                                   // Examples:
283
define('REPEATED_SLASHES_PURIFIER', '/\/{2,}/'); // $path = preg_replace(REPEATED_SLASHES_PURIFIER, '/', $path);
284
define('VALID_WEB_PATH', '/https?:\/\/[^\/]*(\/.*)?/i'); // $is_valid_path = preg_match(VALID_WEB_PATH, $path);
285
define('VALID_WEB_SERVER_BASE', '/https?:\/\/[^\/]*/i'); // $new_path = preg_replace(VALID_WEB_SERVER_BASE, $new_base, $path);
286
287
// Constants for api_get_path() and api_get_path_type(), etc. - registered path types.
288
// basic (leaf elements)
289
define('REL_CODE_PATH', 'REL_CODE_PATH');
290
define('REL_COURSE_PATH', 'REL_COURSE_PATH');
291
define('REL_HOME_PATH', 'REL_HOME_PATH');
292
293
// Constants for api_get_path() and api_get_path_type(), etc. - registered path types.
294
define('WEB_PATH', 'WEB_PATH');
295
define('WEB_APP_PATH', 'WEB_APP_PATH');
296
define('SYS_PATH', 'SYS_PATH');
297
define('SYS_APP_PATH', 'SYS_APP_PATH');
298
define('SYS_UPLOAD_PATH', 'SYS_UPLOAD_PATH');
299
define('WEB_UPLOAD_PATH', 'WEB_UPLOAD_PATH');
300
301
define('REL_PATH', 'REL_PATH');
302
define('WEB_COURSE_PATH', 'WEB_COURSE_PATH');
303
define('SYS_COURSE_PATH', 'SYS_COURSE_PATH');
304
define('WEB_CODE_PATH', 'WEB_CODE_PATH');
305
define('SYS_CODE_PATH', 'SYS_CODE_PATH');
306
define('SYS_LANG_PATH', 'SYS_LANG_PATH');
307
define('WEB_IMG_PATH', 'WEB_IMG_PATH');
308
define('WEB_CSS_PATH', 'WEB_CSS_PATH');
309
define('WEB_PUBLIC_PATH', 'WEB_PUBLIC_PATH');
310
define('SYS_CSS_PATH', 'SYS_CSS_PATH');
311
define('SYS_PLUGIN_PATH', 'SYS_PLUGIN_PATH');
312
define('WEB_PLUGIN_PATH', 'WEB_PLUGIN_PATH');
313
define('WEB_PLUGIN_ASSET_PATH', 'WEB_PLUGIN_ASSET_PATH');
314
define('SYS_ARCHIVE_PATH', 'SYS_ARCHIVE_PATH');
315
define('WEB_ARCHIVE_PATH', 'WEB_ARCHIVE_PATH');
316
define('SYS_INC_PATH', 'SYS_INC_PATH');
317
define('LIBRARY_PATH', 'LIBRARY_PATH');
318
define('CONFIGURATION_PATH', 'CONFIGURATION_PATH');
319
define('WEB_LIBRARY_PATH', 'WEB_LIBRARY_PATH');
320
define('WEB_LIBRARY_JS_PATH', 'WEB_LIBRARY_JS_PATH');
321
define('WEB_AJAX_PATH', 'WEB_AJAX_PATH');
322
define('SYS_TEST_PATH', 'SYS_TEST_PATH');
323
define('WEB_TEMPLATE_PATH', 'WEB_TEMPLATE_PATH');
324
define('SYS_TEMPLATE_PATH', 'SYS_TEMPLATE_PATH');
325
define('SYS_PUBLIC_PATH', 'SYS_PUBLIC_PATH');
326
define('SYS_HOME_PATH', 'SYS_HOME_PATH');
327
define('WEB_HOME_PATH', 'WEB_HOME_PATH');
328
define('WEB_FONTS_PATH', 'WEB_FONTS_PATH');
329
define('SYS_FONTS_PATH', 'SYS_FONTS_PATH');
330
331
define('SYS_DEFAULT_COURSE_DOCUMENT_PATH', 'SYS_DEFAULT_COURSE_DOCUMENT_PATH');
332
define('REL_DEFAULT_COURSE_DOCUMENT_PATH', 'REL_DEFAULT_COURSE_DOCUMENT_PATH');
333
define('WEB_DEFAULT_COURSE_DOCUMENT_PATH', 'WEB_DEFAULT_COURSE_DOCUMENT_PATH');
334
335
// Relations type with Course manager
336
define('COURSE_RELATION_TYPE_COURSE_MANAGER', 1);
337
define('SESSION_RELATION_TYPE_COURSE_MANAGER', 1);
338
339
// Relations type with Human resources manager
340
define('COURSE_RELATION_TYPE_RRHH', 1);
341
define('SESSION_RELATION_TYPE_RRHH', 1);
342
343
//User image sizes
344
define('USER_IMAGE_SIZE_ORIGINAL', 1);
345
define('USER_IMAGE_SIZE_BIG', 2);
346
define('USER_IMAGE_SIZE_MEDIUM', 3);
347
define('USER_IMAGE_SIZE_SMALL', 4);
348
349
// Relation type between users
350
define('USER_UNKNOWN', 0);
351
define('USER_RELATION_TYPE_UNKNOWN', 1);
352
define('USER_RELATION_TYPE_PARENT', 2); // should be deprecated is useless
353
define('USER_RELATION_TYPE_FRIEND', 3);
354
define('USER_RELATION_TYPE_GOODFRIEND', 4); // should be deprecated is useless
355
define('USER_RELATION_TYPE_ENEMY', 5); // should be deprecated is useless
356
define('USER_RELATION_TYPE_DELETED', 6);
357
define('USER_RELATION_TYPE_RRHH', 7);
358
define('USER_RELATION_TYPE_BOSS', 8);
359
360
// Gradebook link constants
361
// Please do not change existing values, they are used in the database !
362
define('GRADEBOOK_ITEM_LIMIT', 1000);
363
364
define('LINK_EXERCISE', 1);
365
define('LINK_DROPBOX', 2);
366
define('LINK_STUDENTPUBLICATION', 3);
367
define('LINK_LEARNPATH', 4);
368
define('LINK_FORUM_THREAD', 5);
369
//define('LINK_WORK',6);
370
define('LINK_ATTENDANCE', 7);
371
define('LINK_SURVEY', 8);
372
define('LINK_HOTPOTATOES', 9);
373
374
// Score display types constants
375
define('SCORE_DIV', 1); // X / Y
376
define('SCORE_PERCENT', 2); // XX %
377
define('SCORE_DIV_PERCENT', 3); // X / Y (XX %)
378
define('SCORE_AVERAGE', 4); // XX %
379
define('SCORE_DECIMAL', 5); // 0.50  (X/Y)
380
define('SCORE_BAR', 6); // Uses the Display::bar_progress function
381
define('SCORE_SIMPLE', 7); // X
382
define('SCORE_IGNORE_SPLIT', 8); //  ??
383
define('SCORE_DIV_PERCENT_WITH_CUSTOM', 9); // X / Y (XX %) - Good!
384
define('SCORE_CUSTOM', 10); // Good!
385
define('SCORE_DIV_SIMPLE_WITH_CUSTOM', 11); // X - Good!
386
define('SCORE_DIV_SIMPLE_WITH_CUSTOM_LETTERS', 12); // X - Good!
387
define('SCORE_ONLY_SCORE', 13); // X - Good!
388
389
define('SCORE_BOTH', 1);
390
define('SCORE_ONLY_DEFAULT', 2);
391
define('SCORE_ONLY_CUSTOM', 3);
392
393
// From display.lib.php
394
395
define('MAX_LENGTH_BREADCRUMB', 100);
396
define('ICON_SIZE_ATOM', 8);
397
define('ICON_SIZE_TINY', 16);
398
define('ICON_SIZE_SMALL', 22);
399
define('ICON_SIZE_MEDIUM', 32);
400
define('ICON_SIZE_LARGE', 48);
401
define('ICON_SIZE_BIG', 64);
402
define('ICON_SIZE_HUGE', 128);
403
define('SHOW_TEXT_NEAR_ICONS', false);
404
405
// Session catalog
406
define('CATALOG_COURSES', 0);
407
define('CATALOG_SESSIONS', 1);
408
define('CATALOG_COURSES_SESSIONS', 2);
409
410
// Hook type events, pre-process and post-process.
411
// All means to be executed for both hook event types
412
define('HOOK_EVENT_TYPE_PRE', 0);
413
define('HOOK_EVENT_TYPE_POST', 1);
414
define('HOOK_EVENT_TYPE_ALL', 10);
415
416
define('CAREER_STATUS_ACTIVE', 1);
417
define('CAREER_STATUS_INACTIVE', 0);
418
419
define('PROMOTION_STATUS_ACTIVE', 1);
420
define('PROMOTION_STATUS_INACTIVE', 0);
421
422
// Group permissions
423
define('GROUP_PERMISSION_OPEN', '1');
424
define('GROUP_PERMISSION_CLOSED', '2');
425
426
// Group user permissions
427
define('GROUP_USER_PERMISSION_ADMIN', '1'); // the admin of a group
428
define('GROUP_USER_PERMISSION_READER', '2'); // a normal user
429
define('GROUP_USER_PERMISSION_PENDING_INVITATION', '3'); // When an admin/moderator invites a user
430
define('GROUP_USER_PERMISSION_PENDING_INVITATION_SENT_BY_USER', '4'); // an user joins a group
431
define('GROUP_USER_PERMISSION_MODERATOR', '5'); // a moderator
432
define('GROUP_USER_PERMISSION_ANONYMOUS', '6'); // an anonymous user
433
define('GROUP_USER_PERMISSION_HRM', '7'); // a human resources manager
434
435
define('GROUP_IMAGE_SIZE_ORIGINAL', 1);
436
define('GROUP_IMAGE_SIZE_BIG', 2);
437
define('GROUP_IMAGE_SIZE_MEDIUM', 3);
438
define('GROUP_IMAGE_SIZE_SMALL', 4);
439
define('GROUP_TITLE_LENGTH', 50);
440
441
// Exercise
442
// @todo move into a class
443
define('ALL_ON_ONE_PAGE', 1);
444
define('ONE_PER_PAGE', 2);
445
446
define('EXERCISE_FEEDBACK_TYPE_END', 0); //Feedback 		 - show score and expected answers
447
define('EXERCISE_FEEDBACK_TYPE_DIRECT', 1); //DirectFeedback - Do not show score nor answers
448
define('EXERCISE_FEEDBACK_TYPE_EXAM', 2); //NoFeedback 	 - Show score only
449
450
define('RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS', 0); //show score and expected answers
451
define('RESULT_DISABLE_NO_SCORE_AND_EXPECTED_ANSWERS', 1); //Do not show score nor answers
452
define('RESULT_DISABLE_SHOW_SCORE_ONLY', 2); //Show score only
453
define('RESULT_DISABLE_SHOW_FINAL_SCORE_ONLY_WITH_CATEGORIES', 3); //Show final score only with categories
454
define('RESULT_DISABLE_SHOW_SCORE_ATTEMPT_SHOW_ANSWERS_LAST_ATTEMPT', 4); //Show final score only with categories
455
456
define('EXERCISE_MAX_NAME_SIZE', 80);
457
458
// Question types (edit next array as well when adding values)
459
// @todo move into a class
460
define('UNIQUE_ANSWER', 1);
461
define('MULTIPLE_ANSWER', 2);
462
define('FILL_IN_BLANKS', 3);
463
define('MATCHING', 4);
464
define('FREE_ANSWER', 5);
465
define('HOT_SPOT', 6);
466
define('HOT_SPOT_ORDER', 7);
467
define('HOT_SPOT_DELINEATION', 8);
468
define('MULTIPLE_ANSWER_COMBINATION', 9);
469
define('UNIQUE_ANSWER_NO_OPTION', 10);
470
define('MULTIPLE_ANSWER_TRUE_FALSE', 11);
471
define('MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE', 12);
472
define('ORAL_EXPRESSION', 13);
473
define('GLOBAL_MULTIPLE_ANSWER', 14);
474
define('MEDIA_QUESTION', 15);
475
define('CALCULATED_ANSWER', 16);
476
define('UNIQUE_ANSWER_IMAGE', 17);
477
define('DRAGGABLE', 18);
478
define('MATCHING_DRAGGABLE', 19);
479
define('ANNOTATION', 20);
480
define('READING_COMPREHENSION', 21);
481
482
define('EXERCISE_CATEGORY_RANDOM_SHUFFLED', 1);
483
define('EXERCISE_CATEGORY_RANDOM_ORDERED', 2);
484
define('EXERCISE_CATEGORY_RANDOM_DISABLED', 0);
485
486
// Question selection type
487
define('EX_Q_SELECTION_ORDERED', 1);
488
define('EX_Q_SELECTION_RANDOM', 2);
489
define('EX_Q_SELECTION_CATEGORIES_ORDERED_QUESTIONS_ORDERED', 3);
490
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_ORDERED', 4);
491
define('EX_Q_SELECTION_CATEGORIES_ORDERED_QUESTIONS_RANDOM', 5);
492
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_RANDOM', 6);
493
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_ORDERED_NO_GROUPED', 7);
494
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_RANDOM_NO_GROUPED', 8);
495
define('EX_Q_SELECTION_CATEGORIES_ORDERED_BY_PARENT_QUESTIONS_ORDERED', 9);
496
define('EX_Q_SELECTION_CATEGORIES_ORDERED_BY_PARENT_QUESTIONS_RANDOM', 10);
497
498
// one big string with all question types, for the validator in pear/HTML/QuickForm/Rule/QuestionType
499
define('QUESTION_TYPES',
500
    UNIQUE_ANSWER.':'.
501
    MULTIPLE_ANSWER.':'.
502
    FILL_IN_BLANKS.':'.
503
    MATCHING.':'.
504
    FREE_ANSWER.':'.
505
    HOT_SPOT.':'.
506
    HOT_SPOT_ORDER.':'.
507
    HOT_SPOT_DELINEATION.':'.
508
    MULTIPLE_ANSWER_COMBINATION.':'.
509
    UNIQUE_ANSWER_NO_OPTION.':'.
510
    MULTIPLE_ANSWER_TRUE_FALSE.':'.
511
    MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE.':'.
512
    ORAL_EXPRESSION.':'.
513
    GLOBAL_MULTIPLE_ANSWER.':'.
514
    MEDIA_QUESTION.':'.
515
    CALCULATED_ANSWER.':'.
516
    UNIQUE_ANSWER_IMAGE.':'.
517
    DRAGGABLE.':'.
518
    MATCHING_DRAGGABLE.':'.
519
    ANNOTATION
520
);
521
522
//Some alias used in the QTI exports
523
define('MCUA', 1);
524
define('TF', 1);
525
define('MCMA', 2);
526
define('FIB', 3);
527
528
// Skills
529
define('SKILL_TYPE_REQUIREMENT', 'required');
530
define('SKILL_TYPE_ACQUIRED', 'acquired');
531
define('SKILL_TYPE_BOTH', 'both');
532
533
// Message
534
define('MESSAGE_STATUS_NEW', '0');
535
define('MESSAGE_STATUS_UNREAD', '1');
536
//2 ??
537
define('MESSAGE_STATUS_DELETED', '3');
538
define('MESSAGE_STATUS_OUTBOX', '4');
539
define('MESSAGE_STATUS_INVITATION_PENDING', '5');
540
define('MESSAGE_STATUS_INVITATION_ACCEPTED', '6');
541
define('MESSAGE_STATUS_INVITATION_DENIED', '7');
542
define('MESSAGE_STATUS_WALL', '8');
543
define('MESSAGE_STATUS_WALL_DELETE', '9');
544
define('MESSAGE_STATUS_WALL_POST', '10');
545
define('MESSAGE_STATUS_CONVERSATION', '11');
546
547
// Images
548
define('IMAGE_WALL_SMALL_SIZE', 200);
549
define('IMAGE_WALL_MEDIUM_SIZE', 500);
550
define('IMAGE_WALL_BIG_SIZE', 2000);
551
define('IMAGE_WALL_SMALL', 'small');
552
define('IMAGE_WALL_MEDIUM', 'medium');
553
define('IMAGE_WALL_BIG', 'big');
554
555
// Social PLUGIN PLACES
556
define('SOCIAL_LEFT_PLUGIN', 1);
557
define('SOCIAL_CENTER_PLUGIN', 2);
558
define('SOCIAL_RIGHT_PLUGIN', 3);
559
define('CUT_GROUP_NAME', 50);
560
561
/**
562
 * FormValidator Filter
563
 */
564
define('NO_HTML', 1);
565
define('STUDENT_HTML', 2);
566
define('TEACHER_HTML', 3);
567
define('STUDENT_HTML_FULLPAGE', 4);
568
define('TEACHER_HTML_FULLPAGE', 5);
569
570
// Timeline
571
define('TIMELINE_STATUS_ACTIVE', '1');
572
define('TIMELINE_STATUS_INACTIVE', '2');
573
574
// Event email template class
575
define('EVENT_EMAIL_TEMPLATE_ACTIVE', 1);
576
define('EVENT_EMAIL_TEMPLATE_INACTIVE', 0);
577
578
// Course home
579
define('SHORTCUTS_HORIZONTAL', 0);
580
define('SHORTCUTS_VERTICAL', 1);
581
582
// Image class
583
define('IMAGE_PROCESSOR', 'gd'); // 'imagick' or 'gd' strings
584
585
// Course copy
586
define('FILE_SKIP', 1);
587
define('FILE_RENAME', 2);
588
define('FILE_OVERWRITE', 3);
589
define('UTF8_CONVERT', false); //false by default
590
591
define('DOCUMENT', 'file');
592
define('FOLDER', 'folder');
593
594
define('RESOURCE_ASSET', 'asset');
595
define('RESOURCE_DOCUMENT', 'document');
596
define('RESOURCE_GLOSSARY', 'glossary');
597
define('RESOURCE_EVENT', 'calendar_event');
598
define('RESOURCE_LINK', 'link');
599
define('RESOURCE_COURSEDESCRIPTION', 'course_description');
600
define('RESOURCE_LEARNPATH', 'learnpath');
601
define('RESOURCE_ANNOUNCEMENT', 'announcement');
602
define('RESOURCE_FORUM', 'forum');
603
define('RESOURCE_FORUMTOPIC', 'thread');
604
define('RESOURCE_FORUMPOST', 'post');
605
define('RESOURCE_QUIZ', 'quiz');
606
define('RESOURCE_TEST_CATEGORY', 'test_category');
607
define('RESOURCE_QUIZQUESTION', 'Exercise_Question');
608
define('RESOURCE_TOOL_INTRO', 'Tool introduction');
609
define('RESOURCE_LINKCATEGORY', 'Link_Category');
610
define('RESOURCE_FORUMCATEGORY', 'Forum_Category');
611
define('RESOURCE_SCORM', 'Scorm');
612
define('RESOURCE_SURVEY', 'survey');
613
define('RESOURCE_SURVEYQUESTION', 'survey_question');
614
define('RESOURCE_SURVEYINVITATION', 'survey_invitation');
615
define('RESOURCE_WIKI', 'wiki');
616
define('RESOURCE_THEMATIC', 'thematic');
617
define('RESOURCE_ATTENDANCE', 'attendance');
618
define('RESOURCE_WORK', 'work');
619
define('RESOURCE_SESSION_COURSE', 'session_course');
620
define('RESOURCE_GRADEBOOK', 'gradebook');
621
define('ADD_THEMATIC_PLAN', 6);
622
623
// Max online users to show per page (whoisonline)
624
define('MAX_ONLINE_USERS', 12);
625
626
// Number of characters maximum to show in preview of course blog posts
627
define('BLOG_MAX_PREVIEW_CHARS', 800);
628
// HTML string to replace with a 'Read more...' link
629
define('BLOG_PAGE_BREAK', '<div style="page-break-after: always"><span style="display: none;">&nbsp;</span></div>');
630
631
// Make sure the CHAMILO_LOAD_WYSIWYG constant is defined
632
// To remove CKeditor libs from HTML, set this constant to true before loading
633
if (!defined('CHAMILO_LOAD_WYSIWYG')) {
634
    define('CHAMILO_LOAD_WYSIWYG', true);
635
}
636
637
/* Constants for course home */
638
define('TOOL_PUBLIC', 'Public');
639
define('TOOL_PUBLIC_BUT_HIDDEN', 'PublicButHide');
640
define('TOOL_COURSE_ADMIN', 'courseAdmin');
641
define('TOOL_PLATFORM_ADMIN', 'platformAdmin');
642
define('TOOL_AUTHORING', 'toolauthoring');
643
define('TOOL_INTERACTION', 'toolinteraction');
644
define('TOOL_COURSE_PLUGIN', 'toolcourseplugin'); //all plugins that can be enabled in courses
645
define('TOOL_ADMIN', 'tooladmin');
646
define('TOOL_ADMIN_PLATFORM', 'tooladminplatform');
647
define('TOOL_DRH', 'tool_drh');
648
define('TOOL_STUDENT_VIEW', 'toolstudentview');
649
define('TOOL_ADMIN_VISIBLE', 'tooladminvisible');
650
651
define('FORUM_NEW_POST', 0);
652
define('CONFVAL_ASK_FOR_OFFICIAL_CODE', true);
653
define('CHECK_PASS_EASY_TO_FIND', false);
654
655
656
/**
657
 * Inclusion of internationalization libraries
658
 */
659
require_once __DIR__.'/internationalization.lib.php';
660
661
/**
662
 * Returns a path to a certain resource within the Chamilo area, specifyed through a parameter.
663
 * Also, this function provides conversion between path types, in this case the input path points inside the Chamilo area too.
664
 *
665
 * See $_configuration['course_folder'] in the configuration.php to alter the WEB_COURSE_PATH and SYS_COURSE_PATH parameters.
666
667
 * @param string $path (optional)   A path which type is to be converted. Also, it may be a defined constant for a path.
668
 * This parameter has meaning when $type parameter has one of the following values: TO_WEB, TO_SYS, TO_REL. Otherwise it is ignored.
669
 * @return string                   The requested path or the converted path.
670
 *
671
 *
672
 * Notes about the current behaviour model:
673
 * 1. Windows back-slashes are converted to slashes in the result.
674
 * 2. A semi-absolute web-path is detected by its leading slash. On Linux systems, absolute system paths start with
675
 * a slash too, so an additional check about presence of leading system server base is implemented. For example, the function is
676
 * able to distinguish type difference between /var/www/chamilo/courses/ (SYS) and /chamilo/courses/ (REL).
677
 * 3. The function api_get_path() returns only these three types of paths, which in some sense are absolute. The function has
678
 * no a mechanism for processing relative web/system paths, such as: lesson01.html, ./lesson01.html, ../css/my_styles.css.
679
 * It has not been identified as needed yet.
680
 * 4. Also, resolving the meta-symbols "." and ".." within paths has not been implemented, it is to be identified as needed.
681
 *
682
 * For examples go to: *
683
 * See main/admin/system_status.php?section=paths
684
 *
685
 * Vchamilo changes : allow using an alternate configuration
686
 * to get vchamilo  instance paths
687
*/
688
function api_get_path($path = '', $configuration = [])
689
{
690
    global $paths;
691
692
    // get proper configuration data if exists
693
    global $_configuration;
694
695
    if (empty($configuration)) {
696
        $configuration = (array) $_configuration;
697
    }
698
699
    $course_folder = 'courses/';
700
    $root_sys = Container::getRootDir();
701
    $root_rel = isset($configuration['url_append']) ? $configuration['url_append'] : '';
702
703
    // Resolve master hostname.
704
    if (!empty($configuration) && array_key_exists('root_web', $configuration)) {
705
        $root_web = $configuration['root_web'];
706
    } else {
707
        $root_web = Container::getUrlGenerator()->generate(
708
            'home',
709
            []
710
        );
711
    }
712
713
    if (isset($configuration['multiple_access_urls']) && $configuration['multiple_access_urls']) {
714
        // To avoid that the api_get_access_url() function fails since global.inc.php also calls the main_api.lib.php
715
        if (isset($configuration['access_url']) && !empty($configuration['access_url'])) {
716
            // We look into the DB the function api_get_access_url
717
            $url_info = api_get_access_url($configuration['access_url']);
718
            // Avoid default value
719
            $defaulValues = ['http://localhost/', 'https://localhost/'];
720
            if (!empty($url_info['url']) && !in_array($url_info['url'], $defaulValues)) {
721
                $root_web = $url_info['active'] == 1 ? $url_info['url'] : $configuration['root_web'];
722
            }
723
        }
724
    }
725
726
    if (empty($paths)) {
727
        $paths = [];
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 => 'web/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
            WEB_PLUGIN_ASSET_PATH => 'web/plugins/',
750
            SYS_ARCHIVE_PATH => 'app/cache/',
751
            WEB_ARCHIVE_PATH => 'app/cache/',
752
            SYS_HOME_PATH => 'app/home/',
753
            WEB_HOME_PATH => 'app/home/',
754
            REL_HOME_PATH => 'app/home/',
755
            SYS_APP_PATH => 'app/',
756
            WEB_APP_PATH => 'app/',
757
            SYS_UPLOAD_PATH => 'app/upload/',
758
            SYS_INC_PATH => 'inc/',
759
            CONFIGURATION_PATH => 'app/config/',
760
            LIBRARY_PATH => 'inc/lib/',
761
            WEB_LIBRARY_PATH => 'inc/lib/',
762
            WEB_LIBRARY_JS_PATH => 'web/js/',
763
            WEB_AJAX_PATH => 'inc/ajax/',
764
            SYS_TEST_PATH => 'tests/',
765
            WEB_TEMPLATE_PATH => 'template/',
766
            SYS_TEMPLATE_PATH => 'template/',
767
            WEB_UPLOAD_PATH => 'app/upload/',
768
            WEB_PUBLIC_PATH => 'web/',
769
            SYS_PUBLIC_PATH => 'web/',
770
            WEB_FONTS_PATH => 'fonts/',
771
            SYS_FONTS_PATH => 'fonts/',
772
        );
773
    }
774
775
    $isInitialized = [];
776
    $course_folder = isset($configuration['course_folder']) ? $configuration['course_folder'] : $course_folder;
777
778
    // Web server base and system server base.
779
    if (!array_key_exists($root_web, $isInitialized)) {
780
        // process absolute global roots
781
        $code_folder = 'main';
782
        // Support for the installation process.
783
        // Developers might use the function api_get_path() directly or indirectly (this is difficult to be traced), at the moment when
784
        // configuration has not been created yet. This is why this function should be upgraded to return correct results in this case.
785
786
        // Dealing with trailing slashes.
787
        $slashed_root_web = api_add_trailing_slash($root_web);
788
789
        $root_sys = api_add_trailing_slash($root_sys);
790
        $root_rel = api_add_trailing_slash($root_rel);
791
        $code_folder = api_add_trailing_slash($code_folder);
792
        $course_folder = api_add_trailing_slash($course_folder);
793
794
        // Initialization of a table that contains common-purpose paths.
795
        $paths[$root_web][REL_PATH] = $root_rel;
796
        $paths[$root_web][REL_COURSE_PATH] = $root_rel.$course_folder;
797
        $paths[$root_web][REL_DEFAULT_COURSE_DOCUMENT_PATH] = $paths[$root_web][REL_PATH].'main/default_course_document/';
798
799
        $paths[$root_web][WEB_PATH] = $slashed_root_web;
800
        $paths[$root_web][WEB_CODE_PATH] = $paths[$root_web][WEB_PATH].$code_folder;
801
        $paths[$root_web][WEB_COURSE_PATH] = $paths[$root_web][WEB_PATH].$course_folder;
802
        $paths[$root_web][WEB_DEFAULT_COURSE_DOCUMENT_PATH] = $paths[$root_web][WEB_CODE_PATH].'default_course_document/';
803
        $paths[$root_web][WEB_APP_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_APP_PATH];
804
        $paths[$root_web][WEB_PLUGIN_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_PLUGIN_PATH];
805
        $paths[$root_web][WEB_PLUGIN_ASSET_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_PLUGIN_ASSET_PATH];
806
        $paths[$root_web][WEB_ARCHIVE_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_ARCHIVE_PATH];
807
        $paths[$root_web][WEB_CSS_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_CSS_PATH];
808
        $paths[$root_web][WEB_IMG_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_IMG_PATH];
809
        $paths[$root_web][WEB_LIBRARY_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_LIBRARY_PATH];
810
        $paths[$root_web][WEB_LIBRARY_JS_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_LIBRARY_JS_PATH];
811
        $paths[$root_web][WEB_AJAX_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_AJAX_PATH];
812
        $paths[$root_web][WEB_FONTS_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_FONTS_PATH];
813
        $paths[$root_web][WEB_TEMPLATE_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_TEMPLATE_PATH];
814
        $paths[$root_web][WEB_UPLOAD_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_UPLOAD_PATH];
815
        $paths[$root_web][WEB_PUBLIC_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_PUBLIC_PATH];
816
        $paths[$root_web][WEB_HOME_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][REL_HOME_PATH];
817
818
        $paths[$root_web][SYS_PATH] = $root_sys;
819
        $paths[$root_web][SYS_CODE_PATH] = $root_sys.$code_folder;
820
        $paths[$root_web][SYS_TEST_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_TEST_PATH];
821
        $paths[$root_web][SYS_TEMPLATE_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_TEMPLATE_PATH];
822
        $paths[$root_web][SYS_PUBLIC_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_PUBLIC_PATH];
823
        $paths[$root_web][SYS_CSS_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_CSS_PATH];
824
        $paths[$root_web][SYS_FONTS_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_FONTS_PATH];
825
        $paths[$root_web][SYS_ARCHIVE_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_ARCHIVE_PATH];
826
        $paths[$root_web][SYS_APP_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_APP_PATH];
827
        $paths[$root_web][SYS_COURSE_PATH] = $paths[$root_web][SYS_APP_PATH].$course_folder;
828
        $paths[$root_web][SYS_UPLOAD_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_UPLOAD_PATH];
829
        $paths[$root_web][SYS_LANG_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_LANG_PATH];
830
        $paths[$root_web][SYS_HOME_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_HOME_PATH];
831
        $paths[$root_web][SYS_PLUGIN_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_PLUGIN_PATH];
832
        $paths[$root_web][SYS_INC_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_INC_PATH];
833
834
        $paths[$root_web][LIBRARY_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][LIBRARY_PATH];
835
        $paths[$root_web][CONFIGURATION_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][CONFIGURATION_PATH];
836
837
        global $virtualChamilo;
838
        if (!empty($virtualChamilo)) {
839
            $paths[$root_web][SYS_ARCHIVE_PATH] = api_add_trailing_slash($virtualChamilo[SYS_ARCHIVE_PATH]);
840
            $paths[$root_web][SYS_HOME_PATH] = api_add_trailing_slash($virtualChamilo[SYS_HOME_PATH]);
841
            $paths[$root_web][SYS_COURSE_PATH] = api_add_trailing_slash($virtualChamilo[SYS_COURSE_PATH]);
842
            $paths[$root_web][SYS_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[SYS_UPLOAD_PATH]);
843
844
            $paths[$root_web][WEB_HOME_PATH] = api_add_trailing_slash($virtualChamilo[WEB_HOME_PATH]);
845
            $paths[$root_web][WEB_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[WEB_UPLOAD_PATH]);
846
            $paths[$root_web][WEB_ARCHIVE_PATH] = api_add_trailing_slash($virtualChamilo[WEB_ARCHIVE_PATH]);
847
            //$paths[$root_web][WEB_COURSE_PATH] = api_add_trailing_slash($virtualChamilo[WEB_COURSE_PATH]);
848
849
            // WEB_UPLOAD_PATH should be handle by apache htaccess in the vhost
850
851
            // RewriteEngine On
852
            // RewriteRule /app/upload/(.*)$ http://localhost/other/upload/my-chamilo111-net/$1 [QSA,L]
853
854
            //$paths[$root_web][WEB_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[WEB_UPLOAD_PATH]);
855
            //$paths[$root_web][REL_PATH] = $virtualChamilo[REL_PATH];
856
            //$paths[$root_web][REL_COURSE_PATH] = $virtualChamilo[REL_COURSE_PATH];
857
        }
858
859
        $isInitialized[$root_web] = true;
860
    }
861
862
    $path = trim($path);
863
864
    // Retrieving a common-purpose path.
865
    if (isset($paths[$root_web][$path])) {
866
        return $paths[$root_web][$path];
867
    }
868
869
    // Second purification.
870
871
    // Replacing Windows back slashes.
872
    $path = str_replace('\\', '/', $path);
873
    // Query strings sometimes mighth wrongly appear in non-URLs.
874
    // Let us check remove them from all types of paths.
875
    if (($pos = strpos($path, '?')) !== false) {
876
        $path = substr($path, 0, $pos);
877
    }
878
879
    // Detection of the input path type. Conversion to semi-absolute type ( /chamilo/main/inc/.... ).
880
881
    if (preg_match(VALID_WEB_PATH, $path)) {
882
        // A special case: When a URL points to the document download script directly, without
883
        // mod-rewrite translation, we have to translate it into an "ordinary" web path.
884
        // For example:
885
        // http://localhost/chamilo/main/document/download.php?doc_url=/image.png&cDir=/
886
        // becomes
887
        // http://localhost/chamilo/courses/TEST/document/image.png
888
        // TEST is a course directory name, so called "system course code".
889
        if (strpos($path, 'download.php') !== false) { // Fast detection first.
890
            $path = urldecode($path);
891
            if (preg_match('/(.*)main\/document\/download.php\?doc_url=\/(.*)&cDir=\/(.*)?/', $path, $matches)) {
892
                $sys_course_code =
893
                    isset($_SESSION['_course']['sysCode'])  // User is inside a course?
894
                        ? $_SESSION['_course']['sysCode']   // Yes, then use course's directory name.
895
                        : '{SYS_COURSE_CODE}';              // No, then use a fake code, it may be processed later.
896
                $path = $matches[1].'courses/'.$sys_course_code.'/document/'.str_replace('//', '/', $matches[3].'/'.$matches[2]);
897
            }
898
        }
899
        // Replacement of the present web server base with a slash '/'.
900
        $path = preg_replace(VALID_WEB_SERVER_BASE, '/', $path);
901
    }
902
903
    // Path now is semi-absolute. It is convenient at this moment repeated slashes to be removed.
904
    $path = preg_replace(REPEATED_SLASHES_PURIFIER, '/', $path);
905
906
    return $path;
907
}
908
909
/**
910
 * Gets a modified version of the path for the CDN, if defined in
911
 * configuration.php
912
 * @param string $web_path The path of the resource without CDN
913
 * @return string The path of the resource converted to CDN
914
 * @author Yannick Warnier <[email protected]>
915
 */
916
function api_get_cdn_path($web_path)
917
{
918
    global $_configuration;
919
    $web_root = api_get_path(WEB_PATH);
920
    $ext = substr($web_path, strrpos($web_path, '.'));
921
    if (isset($ext[2])) { // faster version of strlen to check if len>2
922
        // Check for CDN definitions
923
        if (!empty($_configuration['cdn_enable']) && !empty($ext)) {
924
            foreach ($_configuration['cdn'] as $host => $exts) {
925
                if (in_array($ext, $exts)) {
926
                    //Use host as defined in $_configuration['cdn'], without
927
                    // trailing slash
928
                    return str_replace($web_root, $host.'/', $web_path);
929
                }
930
            }
931
        }
932
    }
933
    return $web_path;
934
}
935
936
/**
937
 * @return bool Return true if CAS authentification is activated
938
 *
939
 */
940
function api_is_cas_activated() {
941
    return api_get_setting('cas_activate') == "true";
942
}
943
944
/**
945
 * @return bool     Return true if LDAP authentification is activated
946
 *
947
 */
948
function api_is_ldap_activated() {
949
    global $extAuthSource;
950
    return is_array($extAuthSource[LDAP_AUTH_SOURCE]);
951
}
952
953
/**
954
 * @return bool     Return true if Facebook authentification is activated
955
 *
956
 */
957
function api_is_facebook_auth_activated() {
958
    global $_configuration;
959
    return (isset($_configuration['facebook_auth']) && $_configuration['facebook_auth'] == 1);
960
}
961
962
/**
963
 * Adds to a given path a trailing slash if it is necessary (adds "/" character at the end of the string).
964
 * @param string $path          The input path.
965
 * @return string               Returns the modified path.
966
 */
967
function api_add_trailing_slash($path) {
968
    return substr($path, -1) == '/' ? $path : $path.'/';
969
}
970
971
/**
972
 * Removes from a given path the trailing slash if it is necessary (removes "/" character from the end of the string).
973
 * @param string $path          The input path.
974
 * @return string               Returns the modified path.
975
 */
976
function api_remove_trailing_slash($path) {
977
    return substr($path, -1) == '/' ? substr($path, 0, -1) : $path;
978
}
979
980
/**
981
 * Checks the RFC 3986 syntax of a given URL.
982
 * @param string $url       The URL to be checked.
983
 * @param bool $absolute    Whether the URL is absolute (beginning with a scheme such as "http:").
984
 * @return string|false             Returns the URL if it is valid, FALSE otherwise.
985
 * This function is an adaptation from the function valid_url(), Drupal CMS.
986
 * @link http://drupal.org
987
 * Note: The built-in function filter_var($urs, FILTER_VALIDATE_URL) has a bug for some versions of PHP.
988
 * @link http://bugs.php.net/51192
989
 */
990
function api_valid_url($url, $absolute = false) {
991
    if ($absolute) {
992
        if (preg_match("
993
            /^                                                      # Start at the beginning of the text
994
            (?:ftp|https?|feed):\/\/                                # Look for ftp, http, https or feed schemes
995
            (?:                                                     # Userinfo (optional) which is typically
996
                (?:(?:[\w\.\-\+!$&'\(\)*\+,;=]|%[0-9a-f]{2})+:)*    # a username or a username and password
997
                (?:[\w\.\-\+%!$&'\(\)*\+,;=]|%[0-9a-f]{2})+@        # combination
998
            )?
999
            (?:
1000
                (?:[a-z0-9\-\.]|%[0-9a-f]{2})+                      # A domain name or a IPv4 address
1001
                |(?:\[(?:[0-9a-f]{0,4}:)*(?:[0-9a-f]{0,4})\])       # or a well formed IPv6 address
1002
            )
1003
            (?::[0-9]+)?                                            # Server port number (optional)
1004
            (?:[\/|\?]
1005
                (?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2}) # The path and query (optional)
1006
            *)?
1007
            $/xi", $url)) {
1008
            return $url;
1009
        }
1010
        return false;
1011
    } else {
1012
        return preg_match("/^(?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2})+$/i", $url) ? $url : false;
1013
    }
1014
}
1015
1016
/**
1017
 * Checks whether a given string looks roughly like an email address.
1018
 *
1019
 * @param string $address   The e-mail address to be checked.
1020
 * @return mixed            Returns the e-mail if it is valid, FALSE otherwise.
1021
 */
1022
function api_valid_email($address)
1023
{
1024
    return filter_var($address, FILTER_VALIDATE_EMAIL);
1025
}
1026
1027
/* PROTECTION FUNCTIONS
1028
   Use these functions to protect your scripts. */
1029
1030
/**
1031
 * Function used to protect a course script.
1032
 * The function blocks access when
1033
 * - there is no $_SESSION["_course"] defined; or
1034
 * - $is_allowed_in_course is set to false (this depends on the course
1035
 * visibility and user status).
1036
 *
1037
 * This is only the first proposal, test and improve!
1038
 * @param boolean Option to print headers when displaying error message. Default: false
1039
 * @param boolean Whether session admins should be allowed or not.
1040
 * @return boolean True if the user has access to the current course or is out of a course context, false otherwise
1041
 * @todo replace global variable
1042
 * @author Roan Embrechts
1043
 */
1044
function api_protect_course_script($print_headers = false, $allow_session_admins = false, $allow_drh = false)
1045
{
1046
    $is_allowed_in_course = api_is_allowed_in_course();
1047
1048
    $is_visible = false;
1049
    $course_info = api_get_course_info();
1050
1051
    if (empty($course_info)) {
1052
        api_not_allowed($print_headers);
1053
        return false;
1054
    }
1055
1056
    if (api_is_drh()) {
1057
        return true;
1058
    }
1059
1060
    // Session admin has access to course
1061
    $sessionAccess = api_get_configuration_value('session_admins_access_all_content');
1062
    if ($sessionAccess) {
1063
        $allow_session_admins = true;
1064
    }
1065
1066
    if (api_is_platform_admin($allow_session_admins)) {
1067
        return true;
1068
    }
1069
1070
    if (isset($course_info) && isset($course_info['visibility'])) {
1071
        switch ($course_info['visibility']) {
1072
            default:
1073 View Code Duplication
            case COURSE_VISIBILITY_CLOSED:
1074
                // Completely closed: the course is only accessible to the teachers. - 0
1075
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1076
                    $is_visible = true;
1077
                }
1078
                break;
1079 View Code Duplication
            case COURSE_VISIBILITY_REGISTERED:
1080
                // Private - access authorized to course members only - 1
1081
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1082
                    $is_visible = true;
1083
                }
1084
                break;
1085 View Code Duplication
            case COURSE_VISIBILITY_OPEN_PLATFORM:
1086
                // Open - access allowed for users registered on the platform - 2
1087
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1088
                    $is_visible = true;
1089
                }
1090
                break;
1091
            case COURSE_VISIBILITY_OPEN_WORLD:
1092
                //Open - access allowed for the whole world - 3
1093
                $is_visible = true;
1094
                break;
1095
            case COURSE_VISIBILITY_HIDDEN:
1096
                //Completely closed: the course is only accessible to the teachers. - 0
1097
                if (api_is_platform_admin()) {
1098
                    $is_visible = true;
1099
                }
1100
                break;
1101
        }
1102
1103
        //If password is set and user is not registered to the course then the course is not visible
1104
        if ($is_allowed_in_course == false &&
1105
            isset($course_info['registration_code']) &&
1106
            !empty($course_info['registration_code'])
1107
        ) {
1108
            $is_visible = false;
1109
        }
1110
    }
1111
1112
    // Check session visibility
1113
    $session_id = api_get_session_id();
1114
1115
    if (!empty($session_id)) {
1116
        //$is_allowed_in_course was set in local.inc.php
1117
        if (!$is_allowed_in_course) {
1118
            $is_visible = false;
1119
        }
1120
    }
1121
1122
    if (!$is_visible) {
1123
        api_not_allowed($print_headers);
1124
        return false;
1125
    }
1126
    return true;
1127
}
1128
1129
/**
1130
 * Function used to protect an admin script.
1131
 *
1132
 * The function blocks access when the user has no platform admin rights
1133
 * with an error message printed on default output
1134
 * @param bool Whether to allow session admins as well
1135
 * @param bool Whether to allow HR directors as well
1136
 * @param string An optional message (already passed through get_lang)
1137
 * @return bool True if user is allowed, false otherwise.
1138
 * The function also outputs an error message in case not allowed
1139
 * @author Roan Embrechts (original author)
1140
 */
1141
function api_protect_admin_script($allow_sessions_admins = false, $allow_drh = false, $message = null)
1142
{
1143
    if (!api_is_platform_admin($allow_sessions_admins, $allow_drh)) {
1144
        api_not_allowed(true, $message);
1145
        return false;
1146
    }
1147
    return true;
1148
}
1149
1150
/**
1151
 * Function used to protect a teacher script.
1152
 * The function blocks access when the user has no teacher rights.
1153
 *
1154
 * @author Yoselyn Castillo
1155
 */
1156
function api_protect_teacher_script($allow_sessions_admins = false)
1157
{
1158
    if (!api_is_allowed_to_edit()) {
1159
        api_not_allowed(true);
1160
        return false;
1161
    }
1162
    return true;
1163
}
1164
1165
/**
1166
 * Function used to prevent anonymous users from accessing a script.
1167
 * @param bool|true $printHeaders
1168
 * @author Roan Embrechts
1169
 *
1170
 * @return bool
1171
 */
1172
function api_block_anonymous_users($printHeaders = true)
1173
{
1174
    $user = api_get_user_info();
1175 View Code Duplication
    if (!(isset($user['user_id']) && $user['user_id']) || api_is_anonymous($user['user_id'], true)) {
1176
        api_not_allowed($printHeaders);
1177
        return false;
1178
    }
1179
1180
    return true;
1181
}
1182
1183
/**
1184
 * @return array with the navigator name and version
1185
 */
1186
function api_get_navigator() {
1187
    $navigator = 'Unknown';
1188
    $version = 0;
1189
1190
    if (!isset($_SERVER['HTTP_USER_AGENT'])) {
1191
        return array('name' => 'Unknown', 'version' => '0.0.0');
1192
    }
1193
1194
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') !== false) {
1195
        $navigator = 'Opera';
1196
        list (, $version) = explode('Opera', $_SERVER['HTTP_USER_AGENT']);
1197 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {
1198
        $navigator = 'Internet Explorer';
1199
        list (, $version) = explode('MSIE', $_SERVER['HTTP_USER_AGENT']);
1200
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome') !== false) {
1201
        $navigator = 'Chrome';
1202
        list (, $version) = explode('Chrome', $_SERVER['HTTP_USER_AGENT']);
1203 View Code Duplication
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'safari') !== false) {
1204
        $navigator = 'Safari';
1205
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1206
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Gecko') !== false) {
1207
        $navigator = 'Mozilla';
1208
        list (, $version) = explode('; rv:', $_SERVER['HTTP_USER_AGENT']);
1209 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Netscape') !== false) {
1210
        $navigator = 'Netscape';
1211
        list (, $version) = explode('Netscape', $_SERVER['HTTP_USER_AGENT']);
1212
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Konqueror') !== false) {
1213
        $navigator = 'Konqueror';
1214
        list (, $version) = explode('Konqueror', $_SERVER['HTTP_USER_AGENT']);
1215 View Code Duplication
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'applewebkit') !== false) {
1216
        $navigator = 'AppleWebKit';
1217
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1218
    }
1219
    $version = str_replace('/', '', $version);
1220
    if (strpos($version, '.') === false) {
1221
        $version = number_format(doubleval($version), 1);
1222
    }
1223
    $return = array('name' => $navigator, 'version' => $version);
1224
    return $return;
1225
}
1226
1227
/**
1228
 * @return True if user self registration is allowed, false otherwise.
1229
 */
1230
function api_is_self_registration_allowed()
1231
{
1232
    return isset($GLOBALS['allowSelfReg']) ? $GLOBALS['allowSelfReg'] : false;
1233
}
1234
1235
/**
1236
 * This function returns the id of the user which is stored in the $_user array.
1237
 *
1238
 * example: The function can be used to check if a user is logged in
1239
 *          if (api_get_user_id())
1240
 * @return int the id of the current user, 0 if is empty
1241
 */
1242
function api_get_user_id()
1243
{
1244
    $userInfo = Session::read('_user');
1245
    if ($userInfo && isset($userInfo['user_id'])) {
1246
        return (int) $userInfo['user_id'];
1247
    }
1248
    return 0;
1249
}
1250
1251
/**
1252
 * Gets the list of courses a specific user is subscribed to
1253
 * @param int       User ID
1254
 * @param boolean   $fetch_session Whether to get session courses or not - NOT YET IMPLEMENTED
1255
 * @return array    Array of courses in the form [0]=>('code'=>xxx,'db'=>xxx,'dir'=>xxx,'status'=>d)
1256
 * @deprecated use CourseManager::get_courses_list_by_user_id()
1257
 */
1258
function api_get_user_courses($userid, $fetch_session = true)
1259
{
1260
    // Get out if not integer
1261
    if ($userid != strval(intval($userid))) {
1262
        return array();
1263
    }
1264
1265
    $t_course = Database::get_main_table(TABLE_MAIN_COURSE);
1266
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1267
1268
    $sql = "SELECT cc.id as real_id, cc.code code, cc.directory dir, cu.status status
1269
            FROM    $t_course       cc,
1270
                    $t_course_user   cu
1271
            WHERE
1272
                cc.id = cu.c_id AND
1273
                cu.user_id = '".$userid."' AND
1274
                cu.relation_type<>".COURSE_RELATION_TYPE_RRHH." ";
1275
    $result = Database::query($sql);
1276
    if ($result === false) {
1277
        return array();
1278
    }
1279
1280
    $courses = array();
1281
    while ($row = Database::fetch_array($result)) {
1282
        // we only need the database name of the course
1283
        $courses[] = $row;
1284
    }
1285
1286
    return $courses;
1287
}
1288
1289
/**
1290
 * Formats user information into a standard array
1291
 * This function should be only used inside api_get_user_info()
1292
 *
1293
 * @param User $user
1294
 * @param bool $checkIfUserOnline
1295
 * @param bool $showPassword
1296
 * @param bool $loadExtraData
1297
 * @param bool $loadOnlyVisibleExtraData
1298
 * @return array
1299
 */
1300
function _api_format_user(
1301
    User $user,
1302
    $checkIfUserOnline = false,
1303
    $showPassword = false,
1304
    $loadExtraData = false,
1305
    $loadOnlyVisibleExtraData = false
1306
) {
1307
    $result = array();
1308
1309
    $result['username'] = $user->getUsername();
1310
    $result['firstName'] = $result['firstname'] = $user->getFirstname();
1311
    $result['lastName'] = $result['lastname'] = $user->getLastname();
1312
    $result['complete_name'] = api_get_person_name($result['firstname'], $result['lastname']);
1313
    $result['complete_name_with_username'] = $result['complete_name'];
1314
    if (!empty($result['username'])) {
1315
        $result['complete_name_with_username'] = $result['complete_name'].' ('.$result['username'].')';
1316
    }
1317
    $result['phone'] = $user->getPhone();
1318
    $result['address'] = $user->getAddress();
1319
    $result['official_code'] = $user->getOfficialCode();
1320
    $result['status'] = $user->getStatus();
1321
    $result['active'] = $user->getActive();
1322
    $result['auth_source'] = $user->getAuthSource();
1323
    $result['theme'] = $user->getTheme();
1324
    $result['language'] = $user->getLanguage();
1325
    $result['creator_id'] = $user->getCreatorId();
1326
    $result['registration_date'] = $user->getRegistrationDate() ? $user->getRegistrationDate()->format('Y-m-d h:i:s') : '';
1327
    $result['hr_dept_id'] = $user->getHrDeptId();
1328
    $result['expiration_date'] = $user->getExpirationDate() ? $user->getExpirationDate()->format('Y-m-d h:i:s') : '';
1329
    $result['picture_uri'] = $user->getPictureUri();
1330
1331
    if (api_get_setting('extended_profile') === 'true') {
1332
        $result['competences'] = $user->getCompetences();
1333
        $result['diplomas']  = $user->getDiplomas();
1334
        $result['teach'] = $user->getTeach();
1335
        $result['openarea'] = $user->getOpenarea();
1336
    }
1337
1338
    $result['email'] = $result['mail'] = $user->getEmail();
1339
    $userId = $user->getId();
1340
    // Maintain the user_id index for backwards compatibility
1341
    $result['user_id'] = $result['id'] = $userId;
1342
    $result['last_login'] = $user->getLastLogin() ? $user->getLastLogin()->format('Y-m-d h:i:s') : '';
1343
1344
    // Getting user avatar.
1345
    $originalFile = UserManager::getUserPicture($userId, USER_IMAGE_SIZE_ORIGINAL, null, $result);
1346
    $smallFile = UserManager::getUserPicture($userId, USER_IMAGE_SIZE_SMALL, null, $result);
1347
    $mediumFile = UserManager::getUserPicture($userId, USER_IMAGE_SIZE_MEDIUM, null, $result);
1348
1349
    $result['avatar'] = $originalFile;
1350
    $avatarString = explode('?', $originalFile);
1351
    $result['avatar_no_query'] = reset($avatarString);
1352
    $result['avatar_small'] = $smallFile;
1353
    $result['avatar_medium'] = $mediumFile;
1354
1355
    if ($showPassword) {
1356
        $result['password'] = $user->getPassword();
1357
    }
1358
1359
    $result['profile_completed'] = $user->isProfileCompleted();
1360
    $result['profile_url'] = api_get_path(WEB_CODE_PATH).'social/profile.php?u='.$userId;
1361
1362
    // Send message link
1363
    $sendMessage = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&user_id='.$user_id;
0 ignored issues
show
Bug introduced by
The variable $user_id does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
1364
    $result['complete_name_with_message_link'] = Display::url(
1365
        $result['complete_name'],
1366
        $sendMessage,
1367
        ['class' => 'ajax']
1368
    );
1369
1370
    if ($checkIfUserOnline) {
1371
        $use_status_in_platform = UserManager::user_is_online($userId);
1372
1373
        $result['user_is_online'] = $use_status_in_platform;
1374
        $user_online_in_chat = 0;
1375
1376
        if ($use_status_in_platform) {
1377
            $user_status = UserManager::get_extra_user_data_by_field(
1378
                $userId,
1379
                'user_chat_status',
1380
                false,
1381
                true
1382
            );
1383
            if (intval($user_status['user_chat_status']) == 1) {
1384
                $user_online_in_chat = 1;
1385
            }
1386
        }
1387
        $result['user_is_online_in_chat'] = $user_online_in_chat;
1388
    }
1389
1390
    if ($loadExtraData) {
1391
        $fieldValue = new ExtraFieldValue('user');
1392
1393
        $result['extra'] = $fieldValue->getAllValuesForAnItem(
1394
            $userId,
1395
            $loadOnlyVisibleExtraData
1396
        );
1397
    }
1398
1399
    return $result;
1400
}
1401
1402
/**
1403
 * Finds all the information about a user.
1404
 * If no parameter is passed you find all the information about the current user.
1405
 * @param int  $user_id
1406
 * @param bool $checkIfUserOnline
1407
 * @param bool $showPassword
1408
 * @param bool $loadExtraData
1409
 * @param bool $loadOnlyVisibleExtraData Get the user extra fields that are visible
1410
 * @param bool $loadAvatars turn off to improve performance and if avatars are not needed.
1411
 * @param bool $updateCache update apc cache if exists
1412
 *
1413
 * @return array $user_info user_id, lastname, firstname, username, email, etc
1414
 * @author Patrick Cool <[email protected]>
1415
 * @author Julio Montoya
1416
 * @version 21 September 2004
1417
 */
1418
function api_get_user_info(
1419
    $user_id = 0,
1420
    $checkIfUserOnline = false,
1421
    $showPassword = false,
1422
    $loadExtraData = false,
1423
    $loadOnlyVisibleExtraData = false,
1424
    $loadAvatars = true,
1425
    $updateCache = false
1426
) {
1427
    $apcVar = null;
1428
    $user = false;
1429
    $cacheAvailable = api_get_configuration_value('apc');
1430
1431
    if (empty($user_id)) {
1432
        $storage = Container::getTokenStorage();
1433
        $token = $storage->getToken();
1434
        $user = $token->getUser();
1435
        if ($user instanceof User) {
1436
            return _api_format_user(
1437
                $token->getUser(),
1438
                $checkIfUserOnline,
1439
                $showPassword,
1440
                $loadExtraData,
1441
                $loadOnlyVisibleExtraData,
1442
		$loadAvatars
1443
            );
1444
        }
1445
1446
        return false;
1447
    }
1448
1449
    $user = UserManager::getManager()->find($user_id);
1450
1451
    if ($user) {
1452
        return _api_format_user(
1453
            $user,
1454
            $checkIfUserOnline,
1455
            $showPassword,
1456
            $loadExtraData,
1457
            $loadOnlyVisibleExtraData,
1458
            $loadAvatars
1459
        );
1460
    }
1461
    return false;
1462
}
1463
1464
/**
1465
 * @param int $userId
1466
 * @return User
1467
 */
1468
function api_get_user_entity($userId)
1469
{
1470
    /** @var \Chamilo\UserBundle\Repository\UserRepository $repo */
1471
    $repo = Database::getManager()->getRepository('ChamiloUserBundle:User');
1472
1473
    return $repo->find($userId);
1474
}
1475
1476
/**
1477
 * @param int $courseId
1478
 *
1479
 * @return Course
1480
 */
1481
function api_get_user_course_entity($courseId = 0)
1482
{
1483
    if (empty($courseId)) {
1484
        $courseId = api_get_course_int_id();
1485
    }
1486
    return CourseManager::getManager()->find($courseId);
1487
}
1488
1489
/**
1490
 * Finds all the information about a user from username instead of user id
1491
 * @param string $username
1492
 * @return array $user_info array user_id, lastname, firstname, username, email
1493
 * @author Yannick Warnier <[email protected]>
1494
 */
1495 View Code Duplication
function api_get_user_info_from_username($username = '')
1496
{
1497
    if (empty($username)) {
1498
        return false;
1499
    }
1500
    $username = trim($username);
1501
1502
1503
    $user = UserManager::getManager()->findUserByUsername($username);
1504
    if ($user) {
1505
        return _api_format_user($user);
0 ignored issues
show
Compatibility introduced by
$user of type object<FOS\UserBundle\Model\UserInterface> is not a sub-type of object<Chamilo\UserBundle\Entity\User>. It seems like you assume a concrete implementation of the interface FOS\UserBundle\Model\UserInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
1506
    }
1507
    return false;
1508
}
1509
1510
/**
1511
 * Get first user with an email
1512
 * @param string $email
1513
 * @return array|bool
1514
 */
1515 View Code Duplication
function api_get_user_info_from_email($email)
1516
{
1517
    if (empty($email)) {
1518
        return false;
1519
    }
1520
1521
    $user = UserManager::getManager()->findUserByEmail($email);
1522
    if ($user) {
1523
        return _api_format_user($user);
0 ignored issues
show
Compatibility introduced by
$user of type object<FOS\UserBundle\Model\UserInterface> is not a sub-type of object<Chamilo\UserBundle\Entity\User>. It seems like you assume a concrete implementation of the interface FOS\UserBundle\Model\UserInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
1524
    }
1525
1526
    return false;
1527
}
1528
1529
/**
1530
 * @return string
1531
 */
1532
function api_get_course_id()
1533
{
1534
    return Session::read('_cid', null);
1535
}
1536
1537
/**
1538
 * Returns the current course id (integer)
1539
 * @param   string  $code   Optional course code
1540
 * @return int
1541
 */
1542 View Code Duplication
function api_get_course_int_id($code = null)
1543
{
1544
    if (!empty($code)) {
1545
        $code = Database::escape_string($code);
1546
        $row = Database::select(
1547
            'id',
1548
            Database::get_main_table(TABLE_MAIN_COURSE),
1549
            array('where'=> array('code = ?' => array($code))),
1550
            'first'
1551
        );
1552
1553
        if (is_array($row) && isset($row['id'])) {
1554
            return $row['id'];
1555
        } else {
1556
            return false;
1557
        }
1558
    }
1559
    return Session::read('_real_cid', 0);
1560
}
1561
1562
/**
1563
 * Returns the current course directory
1564
 *
1565
 * This function relies on api_get_course_info()
1566
 * @param string    The course code - optional (takes it from session if not given)
1567
 * @return string   The directory where the course is located inside the Chamilo "courses" directory
1568
 * @author Yannick Warnier <[email protected]>
1569
 */
1570
function api_get_course_path($course_code = null)
1571
{
1572
    $info = !empty($course_code) ? api_get_course_info($course_code) : api_get_course_info();
1573
    return $info['path'];
1574
}
1575
1576
/**
1577
 * Gets a course setting from the current course_setting table. Try always using integer values.
1578
 * @param string    The name of the setting we want from the table
1579
 * @param string    Optional: course code
1580
 * @param string $setting_name
1581
 * @return mixed    The value of that setting in that table. Return -1 if not found.
1582
 */
1583
function api_get_course_setting($setting_name, $course_code = null)
1584
{
1585
    $course_info = api_get_course_info($course_code);
1586
    $table = Database::get_course_table(TABLE_COURSE_SETTING);
1587
    $setting_name = Database::escape_string($setting_name);
1588
    if (!empty($course_info['real_id']) && !empty($setting_name)) {
1589
        $sql = "SELECT value FROM $table
1590
                WHERE c_id = {$course_info['real_id']} AND variable = '$setting_name'";
1591
        $res = Database::query($sql);
1592 View Code Duplication
        if (Database::num_rows($res) > 0) {
1593
            $row = Database::fetch_array($res);
1594
            if ($setting_name === 'email_alert_manager_on_new_quiz') {
1595
                if (!is_null($row['value'])) {
1596
                    $result = explode(',', $row['value']);
1597
                    $row['value'] = $result;
1598
                }
1599
            }
1600
            return $row['value'];
1601
        }
1602
    }
1603
    return -1;
1604
}
1605
1606
/**
1607
 * Gets an anonymous user ID
1608
 *
1609
 * For some tools that need tracking, like the learnpath tool, it is necessary
1610
 * to have a usable user-id to enable some kind of tracking, even if not
1611
 * perfect. An anonymous ID is taken from the users table by looking for a
1612
 * status of "6" (anonymous).
1613
 * @return int  User ID of the anonymous user, or O if no anonymous user found
1614
 */
1615 View Code Duplication
function api_get_anonymous_id()
1616
{
1617
    $table = Database::get_main_table(TABLE_MAIN_USER);
1618
    $sql = "SELECT user_id FROM $table WHERE status = ".ANONYMOUS;
1619
    $res = Database::query($sql);
1620
    if (Database::num_rows($res) > 0) {
1621
        $row = Database::fetch_array($res);
1622
        return $row['user_id'];
1623
    }
1624
1625
    // No anonymous user was found.
1626
    return 0;
1627
}
1628
1629
/**
1630
 * @param string $courseCode
1631
 * @param int $sessionId
1632
 * @param int $groupId
1633
 * @return string
1634
 */
1635
function api_get_cidreq_params($courseCode, $sessionId = 0, $groupId = 0)
1636
{
1637
    $courseCode = !empty($courseCode) ? htmlspecialchars($courseCode) : '';
1638
    $sessionId = !empty($sessionId) ? (int) $sessionId : 0;
1639
    $groupId = !empty($groupId) ? (int) $groupId : 0;
1640
1641
    $url = 'cidReq='.$courseCode;
1642
    $url .= '&id_session='.$sessionId;
1643
    $url .= '&gidReq='.$groupId;
1644
1645
    return $url;
1646
}
1647
1648
/**
1649
 * Returns the current course url part including session, group, and gradebook params
1650
 *
1651
 * @param bool $addSessionId
1652
 * @param bool $addGroupId
1653
 * @param string $origin
1654
 *
1655
 * @return  string  Course & session references to add to a URL
1656
 *
1657
 */
1658
function api_get_cidreq($addSessionId = true, $addGroupId = true, $origin = '')
1659
{
1660
    $courseCode = api_get_course_id();
1661
    $url = empty($courseCode) ? '' : 'cidReq='.htmlspecialchars($courseCode);
1662
    $origin = empty($origin) ? api_get_origin() : Security::remove_XSS($origin);
1663
1664
    if ($addSessionId) {
1665
        if (!empty($url)) {
1666
            $url .= api_get_session_id() == 0 ? '&id_session=0' : '&id_session='.api_get_session_id();
1667
        }
1668
    }
1669
1670
    if ($addGroupId) {
1671
        if (!empty($url)) {
1672
            $url .= api_get_group_id() == 0 ? '&gidReq=0' : '&gidReq='.api_get_group_id();
1673
        }
1674
    }
1675
1676
    if (!empty($url)) {
1677
        $url .= '&gradebook='.intval(api_is_in_gradebook());
1678
        $url .= '&origin='.$origin;
1679
    }
1680
1681
    return $url;
1682
}
1683
1684
/**
1685
 * Get if we visited a gradebook page
1686
 * @return bool
1687
 */
1688
function api_is_in_gradebook()
1689
{
1690
    return Session::read('in_gradebook', false);
1691
}
1692
1693
/**
1694
 * Set that we are in a page inside a gradebook
1695
 * @return bool
1696
 */
1697
function api_set_in_gradebook()
1698
{
1699
    Session::write('in_gradebook', true);
1700
}
1701
1702
/**
1703
 * Remove gradebook session
1704
 */
1705
function api_remove_in_gradebook()
1706
{
1707
    Session::erase('in_gradebook');
1708
}
1709
1710
/**
1711
 * Returns the current course info array see api_format_course_array()
1712
 * If the course_code is given, the returned array gives info about that
1713
 * particular course, if none given it gets the course info from the session.
1714
 *
1715
 * @param string $course_code
1716
 * @param bool $strict
1717
 *
1718
 * @return array
1719
 */
1720
function api_get_course_info($course_code = null, $strict = false)
1721
{
1722
    if (!empty($course_code)) {
1723
        $course_code = Database::escape_string($course_code);
1724
        $courseId = api_get_course_int_id($course_code);
1725
1726
        if (empty($courseId)) {
1727
            return array();
1728
        }
1729
1730
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1731
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1732
        $sql = "SELECT
1733
                    course.*,
1734
                    course_category.code faCode,
1735
                    course_category.name faName
1736
                FROM $course_table
1737
                LEFT JOIN $course_cat_table
1738
                ON course.category_code = course_category.code
1739
                WHERE course.id = $courseId";
1740
        $result = Database::query($sql);
1741
        $courseInfo = array();
1742
        if (Database::num_rows($result) > 0) {
1743
            $data = Database::fetch_array($result);
1744
            $courseInfo = api_format_course_array($data);
1745
        }
1746
1747
        return $courseInfo;
1748
    }
1749
1750
    $_course = Session::read('_course');
1751
    if ($_course == '-1') {
1752
        $_course = array();
1753
    }
1754
1755
    return $_course;
1756
}
1757
1758
/**
1759
 * Returns the current course info array.
1760
1761
 * Now if the course_code is given, the returned array gives info about that
1762
 * particular course, not specially the current one.
1763
 * @param int $id Numeric ID of the course
1764
 * @return array The course info as an array formatted by api_format_course_array, including category.name
1765
 */
1766
function api_get_course_info_by_id($id = null)
1767
{
1768
    if (!empty($id)) {
1769
        $id = intval($id);
1770
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1771
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1772
        $sql = "SELECT
1773
                    course.*,
1774
                    course_category.code faCode,
1775
                    course_category.name faName
1776
                FROM $course_table
1777
                LEFT JOIN $course_cat_table
1778
                ON course.category_code =  course_category.code
1779
                WHERE course.id = $id";
1780
        $result = Database::query($sql);
1781
        $_course = array();
1782
        if (Database::num_rows($result) > 0) {
1783
            $course_data = Database::fetch_array($result);
1784
            $_course = api_format_course_array($course_data);
1785
        }
1786
        return $_course;
1787
    }
1788
1789
    global $_course;
1790
    if ($_course == '-1') {
1791
        $_course = array();
1792
    }
1793
    return $_course;
1794
}
1795
1796
/**
1797
 * Reformat the course array (output by api_get_course_info()) in order, mostly,
1798
 * to switch from 'code' to 'id' in the array. This is a legacy feature and is
1799
 * now possibly causing massive confusion as a new "id" field has been added to
1800
 * the course table in 1.9.0.
1801
 * @param $course_data
1802
 * @return array
1803
 * @todo eradicate the false "id"=code field of the $_course array and use the int id
1804
 */
1805
function api_format_course_array($course_data)
1806
{
1807
    if (empty($course_data)) {
1808
        return array();
1809
    }
1810
1811
    $_course = array();
1812
    $_course['id'] = $course_data['code'];
1813
    $_course['real_id'] = $course_data['id'];
1814
1815
    // Added
1816
    $_course['code'] = $course_data['code'];
1817
    $_course['name'] = $course_data['title'];
1818
    $_course['title'] = $course_data['title'];
1819
    $_course['official_code'] = $course_data['visual_code'];
1820
    $_course['visual_code'] = $course_data['visual_code'];
1821
    $_course['sysCode'] = $course_data['code'];
1822
    $_course['path'] = $course_data['directory']; // Use as key in path.
1823
    $_course['directory'] = $course_data['directory'];
1824
    $_course['creation_date'] = $course_data['creation_date'];
1825
    $_course['titular'] = $course_data['tutor_name'];
1826
    $_course['language'] = $course_data['course_language'];
1827
    $_course['extLink']['url'] = $course_data['department_url'];
1828
    $_course['extLink']['name'] = $course_data['department_name'];
1829
    $_course['categoryCode'] = $course_data['faCode'];
1830
    $_course['categoryName'] = $course_data['faName'];
1831
    $_course['visibility'] = $course_data['visibility'];
1832
    $_course['subscribe_allowed'] = $course_data['subscribe'];
1833
    $_course['subscribe'] = $course_data['subscribe'];
1834
    $_course['unsubscribe'] = $course_data['unsubscribe'];
1835
    $_course['course_language'] = $course_data['course_language'];
1836
    $_course['activate_legal'] = isset($course_data['activate_legal']) ? $course_data['activate_legal'] : false;
1837
    $_course['legal'] = $course_data['legal'];
1838
    $_course['show_score'] = $course_data['show_score']; //used in the work tool
1839
    $_course['department_name'] = $course_data['department_name'];
1840
    $_course['department_url'] = $course_data['department_url'];
1841
1842
    $courseSys = api_get_path(SYS_COURSE_PATH).$course_data['directory'];
1843
    $webCourseHome = api_get_path(WEB_COURSE_PATH).$course_data['directory'];
1844
1845
    // Course password
1846
    $_course['registration_code'] = !empty($course_data['registration_code']) ? sha1($course_data['registration_code']) : null;
1847
    $_course['disk_quota'] = $course_data['disk_quota'];
1848
    $_course['course_public_url'] = $webCourseHome.'/index.php';
1849
1850
    if (array_key_exists('add_teachers_to_sessions_courses', $course_data)) {
1851
        $_course['add_teachers_to_sessions_courses'] = $course_data['add_teachers_to_sessions_courses'];
1852
    }
1853
1854
    // Course image
1855
    $_course['course_image_source'] = '';
1856 View Code Duplication
    if (file_exists($courseSys.'/course-pic85x85.png')) {
1857
        $url_image = $webCourseHome.'/course-pic85x85.png';
1858
        $_course['course_image_source'] = $courseSys.'/course-pic85x85.png';
1859
    } else {
1860
        $url_image = Display::return_icon(
1861
            'course.png',
1862
            null,
1863
            null,
1864
            ICON_SIZE_BIG,
1865
            null,
1866
            true,
1867
            false
1868
        );
1869
    }
1870
    $_course['course_image'] = $url_image;
1871
1872
    // Course large image
1873
    $_course['course_image_large_source'] = '';
1874
    if (file_exists($courseSys.'/course-pic.png')) {
1875
        $url_image = $webCourseHome.'/course-pic.png';
1876
        $_course['course_image_large_source'] = $courseSys.'/course-pic.png';
1877
    } else {
1878
        $url_image = Display::returnIconPath('session_default.png');
1879
    }
1880
    $_course['course_image_large'] = $url_image;
1881
1882
    $_course['extra_fields'] = isset($course_data['extra_fields']) ? $course_data['extra_fields'] : array();
1883
    $_course['settings'] = isset($course_data['settings']) ? $course_data['settings'] : array();
1884
    $_course['teacher_list'] = isset($course_data['teacher_list']) ? $course_data['teacher_list'] : array();
1885
    $_course['teacher_list_formatted'] = isset($course_data['teacher_list_formatted']) ? $course_data['teacher_list_formatted'] : array();
1886
1887
    return $_course;
1888
}
1889
1890
/**
1891
 * Returns a difficult to guess password.
1892
 * @param int $length the length of the password
1893
 * @return string the generated password
1894
 */
1895
function api_generate_password($length = 8)
1896
{
1897
    if ($length < 2) {
1898
        $length = 2;
1899
    }
1900
1901
    $charactersLowerCase = 'abcdefghijkmnopqrstuvwxyz';
1902
    $charactersUpperCase = 'ABCDEFGHJKLMNPQRSTUVWXYZ';
1903
    $minNumbers = 2;
1904
    $length = $length - $minNumbers;
1905
    $minLowerCase = round($length / 2);
1906
    $minUpperCase = $length - $minLowerCase;
1907
1908
    $password = '';
1909
    $passwordRequirements = api_get_configuration_value('password_requirements');
1910
1911
    $factory = new RandomLib\Factory();
1912
    $generator = $factory->getGenerator(new SecurityLib\Strength(SecurityLib\Strength::MEDIUM));
1913
1914
    if (!empty($passwordRequirements)) {
1915
        $length = $passwordRequirements['min']['length'];
1916
        $minNumbers = $passwordRequirements['min']['numeric'];
1917
        $minLowerCase = $passwordRequirements['min']['lowercase'];
1918
        $minUpperCase = $passwordRequirements['min']['uppercase'];
1919
1920
        $rest = $length - $minNumbers - $minLowerCase - $minUpperCase;
1921
        // Add the rest to fill the length requirement
1922
        if ($rest > 0) {
1923
            $password .= $generator->generateString($rest, $charactersLowerCase.$charactersUpperCase);
1924
        }
1925
    }
1926
1927
    // Min digits default 2
1928
    for ($i = 0; $i < $minNumbers; $i++) {
1929
        $password .= $generator->generateInt(2, 9);
1930
    }
1931
1932
    // Min lowercase
1933
    $password .= $generator->generateString($minLowerCase, $charactersLowerCase);
1934
1935
    // Min uppercase
1936
    $password .= $generator->generateString($minUpperCase, $charactersUpperCase);
1937
    $password = str_shuffle($password);
1938
1939
    return $password;
1940
}
1941
1942
/**
1943
 * Checks a password to see wether it is OK to use.
1944
 * @param string $password
1945
 * @return boolean if the password is acceptable, false otherwise
1946
 * Notes about what a password "OK to use" is:
1947
 * 1. The password should be at least 5 characters long.
1948
 * 2. Only English letters (uppercase or lowercase, it doesn't matter) and digits are allowed.
1949
 * 3. The password should contain at least 3 letters.
1950
 * 4. It should contain at least 2 digits.
1951
 * Settings will change if the configuration value is set: password_requirements
1952
 */
1953
function api_check_password($password)
1954
{
1955
    $passwordRequirements = Security::getPasswordRequirements();
1956
1957
    $minLength = $passwordRequirements['min']['length'];
1958
    $minNumbers = $passwordRequirements['min']['numeric'];
1959
    // Optional
1960
    $minLowerCase = $passwordRequirements['min']['lowercase'];
1961
    $minUpperCase = $passwordRequirements['min']['uppercase'];
1962
1963
    $minLetters = $minLowerCase + $minUpperCase;
1964
    $passwordLength = api_strlen($password);
1965
1966
    $conditions = [
1967
        'min_length' => $passwordLength >= $minLength
1968
    ];
1969
1970
    $digits = 0;
1971
    $lowerCase = 0;
1972
    $upperCase = 0;
1973
1974
    for ($i = 0; $i < $passwordLength; $i++) {
1975
        $currentCharacterCode = 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...
1976
        if ($currentCharacterCode >= 65 && $currentCharacterCode <= 90) {
1977
            $upperCase++;
1978
        }
1979
1980
        if ($currentCharacterCode >= 97 && $currentCharacterCode <= 122) {
1981
            $lowerCase++;
1982
        }
1983
        if ($currentCharacterCode >= 48 && $currentCharacterCode <= 57) {
1984
            $digits++;
1985
        }
1986
    }
1987
1988
    // Min number of digits
1989
    $conditions['min_numeric'] = $digits >= $minNumbers;
1990
1991
    if (!empty($minUpperCase)) {
1992
        // Uppercase
1993
        $conditions['min_uppercase'] = $upperCase >= $minUpperCase;
1994
    }
1995
1996
    if (!empty($minLowerCase)) {
1997
        // Lowercase
1998
        $conditions['min_lowercase'] = $upperCase >= $minLowerCase;
1999
    }
2000
2001
    // Min letters
2002
    $letters = $upperCase + $lowerCase;
2003
    $conditions['min_letters'] = $letters >= $minLetters;
2004
2005
    $isPasswordOk = true;
2006
    foreach ($conditions as $condition) {
2007
        if ($condition === false) {
2008
            $isPasswordOk = false;
2009
            break;
2010
        }
2011
    }
2012
2013
    if ($isPasswordOk === false) {
2014
        $output = get_lang('NewPasswordRequirementsNotMatched').'<br />';
2015
        $output .= Security::getPasswordRequirementsToString($conditions);
2016
2017
        Display::addFlash(Display::return_message($output, 'warning', false));
2018
    }
2019
2020
    return $isPasswordOk;
2021
}
2022
2023
/**
2024
 * Clears the user ID from the session if it was the anonymous user. Generally
2025
 * used on out-of-tools pages to remove a user ID that could otherwise be used
2026
 * in the wrong context.
2027
 * This function is to be used in conjunction with the api_set_anonymous()
2028
 * function to simulate the user existence in case of an anonymous visit.
2029
 * @param bool      database check switch - passed to api_is_anonymous()
2030
 * @return bool     true if succesfully unregistered, false if not anonymous.
2031
 */
2032
function api_clear_anonymous($db_check = false)
2033
{
2034
    global $_user;
2035
    if (api_is_anonymous($_user['user_id'], $db_check)) {
2036
        unset($_user['user_id']);
2037
        Session::erase('_uid');
2038
        return true;
2039
    }
2040
    return false;
2041
}
2042
2043
/**
2044
 * Returns the status string corresponding to the status code
2045
 * @author Noel Dieschburg
2046
 * @param the int status code
2047
 * @return string
2048
 */
2049
function get_status_from_code($status_code)
2050
{
2051
    switch ($status_code) {
2052
        case STUDENT:
2053
            return get_lang('Student', '');
2054
        case TEACHER:
2055
            return get_lang('Teacher', '');
2056
        case COURSEMANAGER:
2057
            return get_lang('Manager', '');
2058
        case SESSIONADMIN:
2059
            return get_lang('SessionsAdmin', '');
2060
        case DRH:
2061
            return get_lang('Drh', '');
2062
    }
2063
}
2064
2065
/**
2066
 * Sets the current user as anonymous if it hasn't been identified yet. This
2067
 * function should be used inside a tool only. The function api_clear_anonymous()
2068
 * acts in the opposite direction by clearing the anonymous user's data every
2069
 * time we get on a course homepage or on a neutral page (index, admin, my space)
2070
 * @return bool     true if set user as anonymous, false if user was already logged in or anonymous id could not be found
2071
 */
2072
function api_set_anonymous()
2073
{
2074
    $_user = Session::read('_user');
2075
2076
    if (!empty($_user['user_id'])) {
2077
        return false;
2078
    }
2079
    $user_id = api_get_anonymous_id();
2080
    if ($user_id == 0) {
2081
        return false;
2082
    }
2083
    Session::erase('_user');
2084
    $_user['user_id'] = $user_id;
2085
    $_user['is_anonymous'] = true;
2086
    $GLOBALS['_user'] = $_user;
2087
    Session::write('_user', $_user);
2088
    return true;
2089
}
2090
2091
/**
2092
 * Gets the current Chamilo (not PHP/cookie) session ID
2093
 * @return  int     O if no active session, the session ID otherwise
2094
 */
2095
function api_get_session_id()
2096
{
2097
    return (int) Session::read('id_session', 0);
2098
}
2099
2100
/**
2101
 * Gets the current Chamilo (not social network) group ID
2102
 * @return  int     O if no active session, the session ID otherwise
2103
 */
2104
function api_get_group_id()
2105
{
2106
    return Session::read('_gid', 0);
2107
}
2108
2109
/**
2110
 * Gets the current or given session name
2111
 * @param   int     Session ID (optional)
2112
 * @return  string  The session name, or null if not found
2113
 */
2114
function api_get_session_name($session_id = 0)
2115
{
2116
    if (empty($session_id)) {
2117
        $session_id = api_get_session_id();
2118
        if (empty($session_id)) {
2119
            return null;
2120
        }
2121
    }
2122
    $t = Database::get_main_table(TABLE_MAIN_SESSION);
2123
    $s = "SELECT name FROM $t WHERE id = ".(int) $session_id;
2124
    $r = Database::query($s);
2125
    $c = Database::num_rows($r);
2126
    if ($c > 0) {
2127
        //technically, there can be only one, but anyway we take the first
2128
        $rec = Database::fetch_array($r);
2129
        return $rec['name'];
2130
    }
2131
    return null;
2132
}
2133
2134
/**
2135
 * Gets the session info by id
2136
 * @param int       Session ID
2137
 * @return array    information of the session
2138
 */
2139
function api_get_session_info($session_id)
2140
{
2141
    return SessionManager::fetch($session_id);
2142
}
2143
2144
/**
2145
 * Gets the session visibility by session id
2146
 * @param int $session_id
2147
 * @param int $courseId
2148
 * @param bool $ignore_visibility_for_admins
2149
 * @return int
2150
 *  0 = session still available,
2151
 *  SESSION_VISIBLE_READ_ONLY = 1,
2152
 *  SESSION_VISIBLE = 2,
2153
 *  SESSION_INVISIBLE = 3
2154
 */
2155
function api_get_session_visibility(
2156
    $session_id,
2157
    $courseId = null,
2158
    $ignore_visibility_for_admins = true
2159
) {
2160
    // Means that the session is still available.
2161
    $visibility = 0;
2162
2163
    if (api_is_platform_admin()) {
2164
        if ($ignore_visibility_for_admins) {
2165
            return SESSION_AVAILABLE;
2166
        }
2167
    }
2168
2169
    $now = time();
2170
    if (!empty($session_id)) {
2171
        $session_id = intval($session_id);
2172
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2173
2174
        $sql = "SELECT * FROM $tbl_session
2175
                WHERE id = $session_id ";
2176
2177
        $result = Database::query($sql);
2178
2179
        if (Database::num_rows($result) > 0) {
2180
            $row = Database::fetch_array($result, 'ASSOC');
2181
            $visibility = $original_visibility = $row['visibility'];
2182
2183
            // I don't care the session visibility.
2184
            if (empty($row['access_start_date']) && empty($row['access_end_date'])) {
2185
                // Session duration per student.
2186
                if (isset($row['duration']) && !empty($row['duration'])) {
2187
                    $duration = $row['duration'] * 24 * 60 * 60;
2188
2189
                    $courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser(
2190
                        $session_id,
2191
                        api_get_user_id()
2192
                    );
2193
2194
                    // If there is a session duration but there is no previous
2195
                    // access by the user, then the session is still available
2196
                    if (count($courseAccess) == 0) {
2197
                        return SESSION_AVAILABLE;
2198
                    }
2199
2200
                    $currentTime = time();
2201
                    $firstAccess = 0;
2202
                    if (isset($courseAccess['login_course_date'])) {
2203
                        $firstAccess = api_strtotime(
2204
                            $courseAccess['login_course_date'],
2205
                            'UTC'
2206
                        );
2207
                    }
2208
                    $userDurationData = SessionManager::getUserSession(
2209
                        api_get_user_id(),
2210
                        $session_id
2211
                    );
2212
                    $userDuration = 0;
2213 View Code Duplication
                    if (isset($userDurationData['duration'])) {
2214
                        $userDuration = intval($userDurationData['duration']) * 24 * 60 * 60;
2215
                    }
2216
2217
                    $totalDuration = $firstAccess + $duration + $userDuration;
2218
                    if ($totalDuration > $currentTime) {
2219
                        return SESSION_AVAILABLE;
2220
                    } else {
2221
                        return SESSION_INVISIBLE;
2222
                    }
2223
                }
2224
2225
                return SESSION_AVAILABLE;
2226
            } else {
2227
                // If start date was set.
2228
                if (!empty($row['access_start_date'])) {
2229
                    if ($now > api_strtotime($row['access_start_date'], 'UTC')) {
2230
                        $visibility = SESSION_AVAILABLE;
2231
                    } else {
2232
                        $visibility = SESSION_INVISIBLE;
2233
                    }
2234
                }
2235
2236
                // If the end date was set.
2237
                if (!empty($row['access_end_date'])) {
2238
                    // Only if date_start said that it was ok
2239
                    if ($visibility === SESSION_AVAILABLE) {
2240
                        if ($now < api_strtotime($row['access_end_date'], 'UTC')) {
2241
                            // Date still available
2242
                            $visibility = SESSION_AVAILABLE;
2243
                        } else {
2244
                            // Session ends
2245
                            $visibility = $row['visibility'];
2246
                        }
2247
                    }
2248
                }
2249
            }
2250
2251
            /* If I'm a coach the visibility can change in my favor depending in
2252
             the coach dates */
2253
            $isCoach = api_is_coach($session_id, $courseId);
2254
2255
            if ($isCoach) {
2256
                // Test start date.
2257
                if (!empty($row['coach_access_start_date'])) {
2258
                    $start = api_strtotime($row['coach_access_start_date'], 'UTC');
2259
                    if ($start < $now) {
2260
                        $visibility = SESSION_AVAILABLE;
2261
                    } else {
2262
                        $visibility = SESSION_INVISIBLE;
2263
                    }
2264
                }
2265
2266
                // Test end date.
2267
                if (!empty($row['coach_access_end_date'])) {
2268
                    if ($visibility = SESSION_AVAILABLE) {
2269
                        $endDateCoach = api_strtotime($row['coach_access_end_date'], 'UTC');
2270
2271
                        if ($endDateCoach >= $now) {
2272
                            $visibility = SESSION_AVAILABLE;
2273
                        } else {
2274
                            $visibility = $row['visibility'];
2275
                        }
2276
                    }
2277
                }
2278
            }
2279
        } else {
2280
            $visibility = SESSION_INVISIBLE;
2281
        }
2282
    }
2283
2284
    return $visibility;
2285
}
2286
2287
/**
2288
 * This function returns a (star) session icon if the session is not null and
2289
 * the user is not a student
2290
 * @param int   $session_id
2291
 * @param int   $status_id User status id - if 5 (student), will return empty
2292
 * @return string   Session icon
2293
 */
2294
function api_get_session_image($session_id, $status_id)
2295
{
2296
    $session_id = (int) $session_id;
2297
    $session_img = '';
2298
    if ((int) $status_id != 5) { //check whether is not a student
2299
        if ($session_id > 0) {
2300
            $session_img = "&nbsp;&nbsp;".Display::return_icon(
2301
                'star.png',
2302
                get_lang('SessionSpecificResource'),
2303
                array('align' => 'absmiddle'),
2304
                ICON_SIZE_SMALL
2305
            );
2306
        }
2307
    }
2308
    return $session_img;
2309
}
2310
2311
/**
2312
 * This function add an additional condition according to the session of the course
2313
 * @param int       $session_id session id
2314
 * @param bool      $and optional, true if more than one condition false if the only condition in the query
2315
 * @param bool      $with_base_content optional, true to accept content with session=0 as well, false for strict session condition
2316
 * @param string $session_field
2317
 * @return string   condition of the session
2318
 */
2319
function api_get_session_condition(
2320
    $session_id,
2321
    $and = true,
2322
    $with_base_content = false,
2323
    $session_field = 'session_id'
2324
) {
2325
    $session_id = intval($session_id);
2326
2327
    if (empty($session_field)) {
2328
        $session_field = "session_id";
2329
    }
2330
    // Condition to show resources by session
2331
    $condition_add = $and ? " AND " : " WHERE ";
2332
2333
    if ($with_base_content) {
2334
        $condition_session = $condition_add." ( $session_field = $session_id OR $session_field = 0 OR $session_field IS NULL) ";
2335
    } else {
2336
        if (empty($session_id)) {
2337
            $condition_session = $condition_add." ($session_field = $session_id OR $session_field IS NULL)";
2338
        } else {
2339
            $condition_session = $condition_add." $session_field = $session_id ";
2340
        }
2341
    }
2342
    return $condition_session;
2343
}
2344
2345
/**
2346
 * @param string $variable
2347
 * @param string $option
2348
 * @return bool
2349
 */
2350
function api_get_setting_in_list($variable, $option)
2351
{
2352
    $value = api_get_setting($variable);
2353
2354
    return in_array($option, $value);
2355
}
2356
2357
2358
/**
2359
 * Returns the value of a setting from the web-adjustable admin config settings.
2360
 *
2361
 * WARNING true/false are stored as string, so when comparing you need to check e.g.
2362
 * if (api_get_setting('course.show_navigation_menu') == 'true') //CORRECT
2363
 * instead of
2364
 * if (api_get_setting('course.show_navigation_menu') == true) //INCORRECT
2365
 * @param string    $variable The variable name
2366
 * @return string
2367
 *
2368
 * @author Julio Montoya
2369
 */
2370
function api_get_setting($variable, $subVariable = '')
2371
{
2372
    $variable = trim($variable);
2373
2374
    switch ($variable) {
2375 View Code Duplication
        case 'header_extra_content':
2376
            $filename = api_get_path(SYS_PATH).api_get_home_path().'header_extra_content.txt';
2377
            if (file_exists($filename)) {
2378
                $value = file_get_contents($filename);
2379
                    return $value ;
2380
            } else {
2381
                return '';
2382
            }
2383
            break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
2384 View Code Duplication
        case 'footer_extra_content':
2385
            $filename = api_get_path(SYS_PATH).api_get_home_path().'footer_extra_content.txt';
2386
            if (file_exists($filename)) {
2387
                $value = file_get_contents($filename);
2388
                return $value ;
2389
            } else {
2390
                return '';
2391
            }
2392
            break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
2393
        case 'server_type':
2394
            $test = ['dev', 'test'];
2395
            $environment = Container::getEnvironment();
2396
            if (in_array($environment, $test)) {
2397
                return 'test';
2398
            }
2399
            return 'prod';
2400
        case 'stylesheets':
2401
            $variable = 'platform.theme';
2402
            break;
2403
        // deprecated settings
2404
        case 'openid_authentication':
2405
        case 'sso_authentication':
2406
        case 'service_ppt2lp':
2407
        case 'add_cas_login_button_cas_button_label':
2408
        case 'add_cas_login_button_cas_button_comment':
2409
        case 'add_cas_login_button_cas_image_url':
2410
        case 'add_cas_logout_button_cas_logout_label':
2411
        case 'add_cas_logout_button_cas_logout_comment':
2412
        case 'add_cas_logout_button_cas_logout_image_url':
2413
        case 'add_facebook_login_button_facebook_button_url':
2414
        case 'add_shibboleth_login_button_shibboleth_button_label':
2415
        case 'add_shibboleth_login_button_shibboleth_button_comment':
2416
        case 'add_shibboleth_login_button_shibboleth_image_url':
2417
        case 'formLogin_hide_unhide_label':
2418
            break;
2419
        default:
2420
            /** @var \Doctrine\ORM\EntityManager $em */
2421
            return Container::getSettingsManager()->getSetting($variable);
2422
    }
2423
}
2424
2425
/**
2426
 * @param string $plugin
2427
 * @param string $variable
2428
 * @return string
2429
 */
2430
function api_get_plugin_setting($plugin, $variable)
2431
{
2432
    $variableName = $plugin.'_'.$variable;
2433
    $params = [
2434
        'category = ? AND subkey = ? AND variable = ?' => [
2435
            'Plugins',
2436
            $plugin,
2437
            $variableName,
2438
        ],
2439
    ];
2440
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2441
    $result = Database::select(
2442
        'selected_value',
2443
        $table,
2444
        array('where' => $params),
2445
        'one'
2446
    );
2447
    if ($result) {
2448
        $result = $result['selected_value'];
2449
        return $result;
2450
    }
2451
2452
    return null;
2453
}
2454
2455
/**
2456
 * Returns the value of a setting from the web-adjustable admin config settings.
2457
 **/
2458
function api_get_settings_params($params)
2459
{
2460
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2461
    $result = Database::select('*', $table, array('where' => $params));
2462
    return $result;
2463
}
2464
2465
function api_get_settings_params_simple($params)
2466
{
2467
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2468
    $result = Database::select('*', $table, array('where' => $params), 'one');
2469
    return $result;
2470
}
2471
2472
/**
2473
 * Returns the value of a setting from the web-adjustable admin config settings.
2474
 **/
2475
function api_delete_settings_params($params)
2476
{
2477
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2478
    $result = Database::delete($table, $params);
2479
    return $result;
2480
}
2481
2482
/**
2483
 * Returns an escaped version of $_SERVER['PHP_SELF'] to avoid XSS injection
2484
 * @return string   Escaped version of $_SERVER['PHP_SELF']
2485
 */
2486
function api_get_self()
2487
{
2488
    return htmlentities($_SERVER['PHP_SELF']);
2489
}
2490
2491
/**
2492
 * Checks whether current user is a platform administrator
2493
 * @param boolean $allowSessionAdmins Whether session admins should be considered admins or not
2494
 * @param boolean $allowDrh Whether HR directors should be considered admins or not
2495
 * @return boolean True if the user has platform admin rights,
2496
 * false otherwise.
2497
 * @see usermanager::is_admin(user_id) for a user-id specific function
2498
 */
2499
function api_is_platform_admin($allowSessionAdmins = false, $allowDrh = false)
2500
{
2501
    $checker = Container::getAuthorizationChecker();
2502
    if ($checker) {
2503
        if ($checker->isGranted('ROLE_ADMIN')) {
2504
            return true;
2505
        }
2506
        if ($allowSessionAdmins) {
2507
            if ($checker->isGranted('ROLE_SESSION_MANAGER')) {
2508
                return true;
2509
            }
2510
        }
2511
    }
2512
2513
    return false;
2514
2515
    $isPlatformAdmin = Session::read('is_platformAdmin');
0 ignored issues
show
Unused Code introduced by
$isPlatformAdmin = \Cham...ad('is_platformAdmin'); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
2516
    if ($isPlatformAdmin) {
2517
        return true;
2518
    }
2519
    $_user = api_get_user_info();
2520
2521
    return
2522
        isset($_user['status']) &&
2523
        (
2524
            ($allowSessionAdmins && $_user['status'] == SESSIONADMIN) ||
2525
            ($allowDrh && $_user['status'] == DRH)
2526
        );
2527
}
2528
2529
/**
2530
 * Checks whether the user given as user id is in the admin table.
2531
 * @param int $user_id. If none provided, will use current user
0 ignored issues
show
Documentation introduced by
There is no parameter named $user_id.. Did you maybe mean $user_id?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
2532
 * @param int $url URL ID. If provided, also check if the user is active on given URL
2533
 * @result bool True if the user is admin, false otherwise
2534
 */
2535
function api_is_platform_admin_by_id($user_id = null, $url = null)
2536
{
2537
    $user_id = intval($user_id);
2538
    if (empty($user_id)) {
2539
        $user_id = api_get_user_id();
2540
    }
2541
2542
    $em = Container::getEntityManager();
2543
    $user = $em->getRepository('ChamiloUserBundle:User')->find($user_id);
2544
    $is_admin = $user->hasRole('ROLE_ADMIN');
2545
2546
    if (!$is_admin || !isset($url)) {
2547
        return $is_admin;
2548
    }
2549
    // We get here only if $url is set
2550
    $url = intval($url);
2551
    $url_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
2552
    $sql = "SELECT * FROM $url_user_table
2553
            WHERE access_url_id = $url AND user_id = $user_id";
2554
    $res = Database::query($sql);
2555
    $result = Database::num_rows($res) === 1;
2556
2557
    return $result;
2558
}
2559
2560
/**
2561
 * Returns the user's numeric status ID from the users table
2562
 * @param int $user_id If none provided, will use current user
2563
 * @return int User's status (1 for teacher, 5 for student, etc)
2564
 */
2565 View Code Duplication
function api_get_user_status($user_id = null)
2566
{
2567
    $user_id = intval($user_id);
2568
    if (empty($user_id)) {
2569
        $user_id = api_get_user_id();
2570
    }
2571
    $table = Database::get_main_table(TABLE_MAIN_USER);
2572
    $sql = "SELECT status FROM $table WHERE user_id = $user_id ";
2573
    $result = Database::query($sql);
2574
    $status = null;
2575
    if (Database::num_rows($result)) {
2576
        $row = Database::fetch_array($result);
2577
        $status = $row['status'];
2578
    }
2579
    return $status;
2580
}
2581
2582
/**
2583
 * Checks whether current user is allowed to create courses
2584
 * @return boolean True if the user has course creation rights,
2585
 * false otherwise.
2586
 */
2587
function api_is_allowed_to_create_course()
2588
{
2589
    if (api_is_platform_admin()) {
2590
        return true;
2591
    }
2592
2593
    // Teachers can only create courses
2594
    if (api_is_teacher()) {
2595
        if (api_get_setting('allow_users_to_create_courses') === 'true') {
2596
            return true;
2597
        } else {
2598
            return false;
2599
        }
2600
    }
2601
2602
    return Session::read('is_allowedCreateCourse');
2603
}
2604
2605
/**
2606
 * Checks whether the current user is a course administrator
2607
 * @return boolean True if current user is a course administrator
2608
 */
2609
function api_is_course_admin()
2610
{
2611
    if (api_is_platform_admin()) {
2612
        return true;
2613
    }
2614
    return Session::read('is_courseAdmin');
2615
}
2616
2617
/**
2618
 * Checks whether the current user is a course coach
2619
 * @return bool     True if current user is a course coach
2620
 */
2621
function api_is_course_coach()
2622
{
2623
    return Session::read('is_courseCoach');
2624
}
2625
2626
/**
2627
 * Checks whether the current user is a course tutor
2628
 * Based on the presence of user in session_rel_course_rel_user.user_id with status = 2
2629
 * @return bool     True if current user is a course tutor
2630
 */
2631
function api_is_course_tutor()
2632
{
2633
    return Session::read('is_courseTutor');
2634
}
2635
2636
/**
2637
 * @param int $user_id
2638
 * @param int $courseId
2639
 * @param int $session_id
2640
 * @return bool
2641
 */
2642
function api_is_course_session_coach($user_id, $courseId, $session_id)
2643
{
2644
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2645
    $session_rel_course_rel_user_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2646
2647
    $user_id = intval($user_id);
2648
    $session_id = intval($session_id);
2649
    $courseId = intval($courseId);
2650
2651
    $sql = "SELECT DISTINCT session.id
2652
            FROM $session_table
2653
            INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2654
            ON session.id = session_rc_ru.session_id
2655
            WHERE
2656
                session_rc_ru.user_id = '".$user_id."'  AND
2657
                session_rc_ru.c_id = '$courseId' AND
2658
                session_rc_ru.status = 2 AND
2659
                session_rc_ru.session_id = '$session_id'";
2660
    $result = Database::query($sql);
2661
2662
    return Database::num_rows($result) > 0;
2663
}
2664
2665
/**
2666
 * Checks whether the current user is a course or session coach
2667
 * @param int $session_id
2668
 * @param int $courseId
2669
 * @param bool  Check whether we are in student view and, if we are, return false
2670
 * @return boolean True if current user is a course or session coach
2671
 */
2672
function api_is_coach($session_id = 0, $courseId = null, $check_student_view = true)
2673
{
2674
    $userId = api_get_user_id();
2675
2676
    if (!empty($session_id)) {
2677
        $session_id = intval($session_id);
2678
    } else {
2679
        $session_id = api_get_session_id();
2680
    }
2681
2682
    // The student preview was on
2683
    if ($check_student_view &&
2684
        isset($_SESSION['studentview']) && $_SESSION['studentview'] == "studentview"
2685
    ) {
2686
        return false;
2687
    }
2688
2689
    if (!empty($courseId)) {
2690
        $courseId = intval($courseId);
2691
    } else {
2692
        $courseId = api_get_course_int_id();
2693
    }
2694
2695
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2696
    $session_rel_course_rel_user_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2697
    $sessionIsCoach = null;
2698
2699
    if (!empty($courseId)) {
2700
        $sql = "SELECT DISTINCT s.id, name, access_start_date, access_end_date
2701
                FROM $session_table s
2702
                INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2703
                ON session_rc_ru.session_id = s.id AND session_rc_ru.user_id = '".$userId."'
2704
                WHERE
2705
                    session_rc_ru.c_id = '$courseId' AND
2706
                    session_rc_ru.status = 2 AND
2707
                    session_rc_ru.session_id = '$session_id'";
2708
        $result = Database::query($sql);
2709
        $sessionIsCoach = Database::store_result($result);
2710
    }
2711
2712
    if (!empty($session_id)) {
2713
        $sql = "SELECT DISTINCT id, name, access_start_date, access_end_date
2714
                FROM $session_table
2715
                WHERE session.id_coach = $userId AND id = $session_id
2716
                ORDER BY access_start_date, access_end_date, name";
2717
        $result = Database::query($sql);
2718
        if (!empty($sessionIsCoach)) {
2719
            $sessionIsCoach = array_merge(
2720
                $sessionIsCoach,
2721
                Database::store_result($result)
2722
            );
2723
        } else {
2724
            $sessionIsCoach = Database::store_result($result);
2725
        }
2726
    }
2727
2728
    return (count($sessionIsCoach) > 0);
2729
}
2730
2731
/**
2732
 * Checks whether the current user is a session administrator
2733
 * @return boolean True if current user is a course administrator
2734
 */
2735
function api_is_session_admin()
2736
{
2737
    $user = api_get_user_info();
2738
    return isset($user['status']) && $user['status'] == SESSIONADMIN;
2739
}
2740
2741
/**
2742
 * Checks whether the current user is a human resources manager
2743
 * @return boolean True if current user is a human resources manager
2744
 */
2745
function api_is_drh()
2746
{
2747
    $user = api_get_user_info();
2748
    return isset($user['status']) && $user['status'] == DRH;
2749
}
2750
2751
/**
2752
 * Checks whether the current user is a student
2753
 * @return boolean True if current user is a human resources manager
2754
 */
2755
function api_is_student()
2756
{
2757
    $user = api_get_user_info();
2758
    return isset($user['status']) && $user['status'] == STUDENT;
2759
}
2760
2761
/**
2762
 * Checks whether the current user has the status 'teacher'
2763
 * @return boolean True if current user is a human resources manager
2764
 */
2765
function api_is_teacher()
2766
{
2767
    $user = api_get_user_info();
2768
    return isset($user['status']) && $user['status'] == COURSEMANAGER;
2769
}
2770
2771
/**
2772
 * Checks whether the current user is a invited user
2773
 * @return boolean
2774
 */
2775
function api_is_invitee()
2776
{
2777
    $user = api_get_user_info();
2778
2779
    return isset($user['status']) && $user['status'] == INVITEE;
2780
}
2781
2782
/**
2783
 * This function checks whether a session is assigned into a category
2784
 * @param int       - session id
2785
 * @param string    - category name
2786
 * @return bool     - true if is found, otherwise false
2787
 */
2788
function api_is_session_in_category($session_id, $category_name)
2789
{
2790
    $session_id = intval($session_id);
2791
    $category_name = Database::escape_string($category_name);
2792
    $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2793
    $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
2794
2795
    $sql = "SELECT 1
2796
            FROM $tbl_session
2797
            WHERE $session_id IN (
2798
                SELECT s.id FROM $tbl_session s, $tbl_session_category sc
2799
                WHERE
2800
                  s.session_category_id = sc.id AND
2801
                  sc.name LIKE '%$category_name'
2802
            )";
2803
    $rs = Database::query($sql);
2804
2805
    if (Database::num_rows($rs) > 0) {
2806
        return true;
2807
    } else {
2808
        return false;
2809
    }
2810
}
2811
2812
/**
2813
 * Displays the title of a tool.
2814
 * Normal use: parameter is a string:
2815
 * api_display_tool_title("My Tool")
2816
 *
2817
 * Optionally, there can be a subtitle below
2818
 * the normal title, and / or a supra title above the normal title.
2819
 *
2820
 * e.g. supra title:
2821
 * group
2822
 * GROUP PROPERTIES
2823
 *
2824
 * e.g. subtitle:
2825
 * AGENDA
2826
 * calender & events tool
2827
 *
2828
 * @author Hugues Peeters <[email protected]>
2829
 * @param  mixed $title_element - it could either be a string or an array
2830
 *                               containing 'supraTitle', 'mainTitle',
2831
 *                               'subTitle'
2832
 * @return void
2833
 */
2834
function api_display_tool_title($title_element)
2835
{
2836
    if (is_string($title_element)) {
2837
        $tit = $title_element;
2838
        unset($title_element);
2839
        $title_element['mainTitle'] = $tit;
2840
    }
2841
    echo '<h3>';
2842
    if (!empty($title_element['supraTitle'])) {
2843
        echo '<small>'.$title_element['supraTitle'].'</small><br />';
2844
    }
2845
    if (!empty($title_element['mainTitle'])) {
2846
        echo $title_element['mainTitle'];
2847
    }
2848
    if (!empty($title_element['subTitle'])) {
2849
        echo '<br /><small>'.$title_element['subTitle'].'</small>';
2850
    }
2851
    echo '</h3>';
2852
}
2853
2854
/**
2855
 * Displays options for switching between student view and course manager view
2856
 *
2857
 * Changes in version 1.2 (Patrick Cool)
2858
 * Student view switch now behaves as a real switch. It maintains its current state until the state
2859
 * is changed explicitly
2860
 *
2861
 * Changes in version 1.1 (Patrick Cool)
2862
 * student view now works correctly in subfolders of the document tool
2863
 * student view works correctly in the new links tool
2864
 *
2865
 * Example code for using this in your tools:
2866
 * //if ($is_courseAdmin && api_get_setting('student_view_enabled') == 'true') {
2867
 * //   display_tool_view_option($isStudentView);
2868
 * //}
2869
 * //and in later sections, use api_is_allowed_to_edit()
2870
 *
2871
 * @author Roan Embrechts
2872
 * @author Patrick Cool
2873
 * @author Julio Montoya, changes added in Chamilo
2874
 * @version 1.2
2875
 * @todo rewrite code so it is easier to understand
2876
 */
2877
function api_display_tool_view_option()
2878
{
2879
    if (api_get_setting('student_view_enabled') != 'true') {
2880
        return '';
2881
    }
2882
2883
    $sourceurl = '';
2884
    $is_framed = false;
2885
    // Exceptions apply for all multi-frames pages
2886
    if (strpos($_SERVER['REQUEST_URI'], 'chat/chat_banner.php') !== false) {
2887
        // The chat is a multiframe bit that doesn't work too well with the student_view, so do not show the link
2888
        return '';
2889
    }
2890
2891
    // Uncomment to remove student view link from document view page
2892
    if (strpos($_SERVER['REQUEST_URI'], 'lp/lp_header.php') !== false) {
2893
        if (empty($_GET['lp_id'])) {
2894
            return '';
2895
        }
2896
        $sourceurl = substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], '?'));
2897
        $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);
2898
        //showinframes doesn't handle student view anyway...
2899
        //return '';
2900
        $is_framed = true;
2901
    }
2902
2903
    // Check whether the $_SERVER['REQUEST_URI'] contains already url parameters (thus a questionmark)
2904
    if (!$is_framed) {
2905
        if (strpos($_SERVER['REQUEST_URI'], '?') === false) {
2906
            $sourceurl = api_get_self().'?'.api_get_cidreq();
2907
        } else {
2908
            $sourceurl = $_SERVER['REQUEST_URI'];
2909
        }
2910
    }
2911
2912
    $output_string = '';
2913
    if (!empty($_SESSION['studentview'])) {
2914
        if ($_SESSION['studentview'] == 'studentview') {
2915
            // We have to remove the isStudentView=true from the $sourceurl
2916
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
2917
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
2918
            $output_string .= '<a class="btn btn-primary btn-sm" href="'.$sourceurl.'&isStudentView=false" target="_self">'.Display::returnFontAwesomeIcon('eye').' '.get_lang('SwitchToTeacherView').'</a>';
2919
        } elseif ($_SESSION['studentview'] == 'teacherview') {
2920
            // Switching to teacherview
2921
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
2922
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
2923
            $output_string .= '<a class="btn btn-default btn-sm" href="'.$sourceurl.'&isStudentView=true" target="_self">'.Display::returnFontAwesomeIcon('eye').' '.get_lang('SwitchToStudentView').'</a>';
2924
        }
2925
    } else {
2926
        $output_string .= '<a class="btn btn-default btn-sm" href="'.$sourceurl.'&isStudentView=true" target="_self">'.Display::returnFontAwesomeIcon('eye').' '.get_lang('SwitchToStudentView').'</a>';
2927
    }
2928
    $html = Display::tag('div', $output_string, array('class'=>'view-options'));
2929
    return $html;
2930
}
2931
2932
// TODO: This is for the permission section.
2933
/**
2934
 * Function that removes the need to directly use is_courseAdmin global in
2935
 * tool scripts. It returns true or false depending on the user's rights in
2936
 * this particular course.
2937
 * Optionally checking for tutor and coach roles here allows us to use the
2938
 * student_view feature altogether with these roles as well.
2939
 * @param bool  Whether to check if the user has the tutor role
2940
 * @param bool  Whether to check if the user has the coach role
2941
 * @param bool  Whether to check if the user has the session coach role
2942
 * @param bool  check the student view or not
2943
 *
2944
 * @author Roan Embrechts
2945
 * @author Patrick Cool
2946
 * @author Julio Montoya
2947
 * @version 1.1, February 2004
2948
 * @return boolean true: the user has the rights to edit, false: he does not
2949
 */
2950
2951
function api_is_allowed_to_edit(
2952
    $tutor = false,
2953
    $coach = false,
2954
    $session_coach = false,
2955
    $check_student_view = true
2956
) {
2957
    $sessionId = api_get_session_id();
2958
    $is_allowed_coach_to_edit = api_is_coach(null, null, $check_student_view);
2959
    $session_visibility = api_get_session_visibility($sessionId);
2960
2961
    // Admins can edit anything.
2962
    if (api_is_platform_admin(false)) {
2963
        // The student preview was on
2964
        if ($check_student_view && api_is_student_view_active()) {
2965
            return false;
2966
        } else {
2967
            return true;
2968
        }
2969
    }
2970
2971
    $is_courseAdmin = api_is_course_admin();
2972
2973
    if (!$is_courseAdmin && $tutor) {
2974
        // If we also want to check if the user is a tutor...
2975
        $is_courseAdmin = $is_courseAdmin || api_is_course_tutor();
2976
    }
2977
2978
    if (!$is_courseAdmin && $coach) {
2979
        // If we also want to check if the user is a coach...';
2980
        // Check if session visibility is read only for coaches.
2981
        if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
2982
            $is_allowed_coach_to_edit = false;
2983
        }
2984
2985
        if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
2986
            // Check if coach is allowed to edit a course.
2987
            $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
2988
        }
2989
    }
2990
2991
    if (!$is_courseAdmin && $session_coach) {
2992
        $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
2993
    }
2994
2995
    // Check if the student_view is enabled, and if so, if it is activated.
2996
    if (api_get_setting('student_view_enabled') == 'true') {
2997
        if (!empty($sessionId)) {
2998
            // Check if session visibility is read only for coaches.
2999
            if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
3000
                $is_allowed_coach_to_edit = false;
3001
            }
3002
3003
            if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
3004
                // Check if coach is allowed to edit a course.
3005
                $is_allowed = $is_allowed_coach_to_edit;
3006
            } else {
3007
                $is_allowed = false;
3008
            }
3009
            if ($check_student_view) {
3010
                $is_allowed = $is_allowed && $_SESSION['studentview'] != 'studentview';
3011
            }
3012
        } else {
3013
            if ($check_student_view) {
3014
                $is_allowed = $is_courseAdmin && $_SESSION['studentview'] != 'studentview';
3015
            } else {
3016
                $is_allowed = $is_courseAdmin;
3017
            }
3018
        }
3019
3020
        return $is_allowed;
3021
    } else {
3022
        return $is_courseAdmin;
3023
    }
3024
}
3025
3026
/**
3027
 * Returns true if user is a course coach of at least one course in session
3028
 * @param int $sessionId
3029
 * @return bool
3030
 */
3031
function api_is_coach_of_course_in_session($sessionId)
3032
{
3033
    if (api_is_platform_admin()) {
3034
        return true;
3035
    }
3036
3037
    $userId = api_get_user_id();
3038
    $courseList = UserManager::get_courses_list_by_session(
3039
        $userId,
3040
        $sessionId
3041
    );
3042
3043
    // Session visibility.
3044
    $visibility = api_get_session_visibility(
3045
        $sessionId,
3046
        null,
3047
        false
3048
    );
3049
3050 View Code Duplication
    if ($visibility != SESSION_VISIBLE && !empty($courseList)) {
3051
        // Course Coach session visibility.
3052
        $blockedCourseCount = 0;
3053
        $closedVisibilityList = array(
3054
            COURSE_VISIBILITY_CLOSED,
3055
            COURSE_VISIBILITY_HIDDEN
3056
        );
3057
3058
        foreach ($courseList as $course) {
3059
            // Checking session visibility
3060
            $sessionCourseVisibility = api_get_session_visibility(
3061
                $sessionId,
3062
                $course['real_id']
3063
            );
3064
3065
            $courseIsVisible = !in_array(
3066
                $course['visibility'],
3067
                $closedVisibilityList
3068
            );
3069
            if ($courseIsVisible === false || $sessionCourseVisibility == SESSION_INVISIBLE) {
3070
                $blockedCourseCount++;
3071
            }
3072
        }
3073
3074
        // If all courses are blocked then no show in the list.
3075
        if ($blockedCourseCount === count($courseList)) {
3076
            $visibility = SESSION_INVISIBLE;
3077
        } else {
3078
            $visibility = SESSION_VISIBLE;
3079
        }
3080
    }
3081
3082
    switch ($visibility) {
3083
        case SESSION_VISIBLE_READ_ONLY:
3084
        case SESSION_VISIBLE:
3085
        case SESSION_AVAILABLE:
3086
            return true;
3087
            break;
3088
        case SESSION_INVISIBLE:
3089
            return false;
3090
    }
3091
3092
    return false;
3093
}
3094
3095
/**
3096
* Checks if a student can edit contents in a session depending
3097
* on the session visibility
3098
* @param bool $tutor  Whether to check if the user has the tutor role
3099
* @param bool  $coach Whether to check if the user has the coach role
3100
* @return boolean true: the user has the rights to edit, false: he does not
3101
*/
3102
function api_is_allowed_to_session_edit($tutor = false, $coach = false)
3103
{
3104
    if (api_is_allowed_to_edit($tutor, $coach)) {
3105
        // If I'm a teacher, I will return true in order to not affect the normal behaviour of Chamilo tools.
3106
        return true;
3107
    } else {
3108
        $sessionId = api_get_session_id();
3109
3110
        if ($sessionId == 0) {
3111
            // I'm not in a session so i will return true to not affect the normal behaviour of Chamilo tools.
3112
            return true;
3113
        } else {
3114
            // I'm in a session and I'm a student
3115
            // Get the session visibility
3116
            $session_visibility = api_get_session_visibility($sessionId);
3117
            // if 5 the session is still available
3118
            //@todo We could load the session_rel_course_rel_user permission to increase the level of detail.
3119
            //echo api_get_user_id();
3120
            //echo api_get_course_id();
3121
3122
            switch ($session_visibility) {
3123
                case SESSION_VISIBLE_READ_ONLY: // 1
3124
                    return false;
3125
                case SESSION_VISIBLE:           // 2
3126
                    return true;
3127
                case SESSION_INVISIBLE:         // 3
3128
                    return false;
3129
                case SESSION_AVAILABLE:         //5
3130
                    return true;
3131
            }
3132
        }
3133
    }
3134
}
3135
3136
/**
3137
 * Checks whether the user is allowed in a specific tool for a specific action
3138
 * @param string $tool the tool we are checking if the user has a certain permission
3139
 * @param string $action the action we are checking (add, edit, delete, move, visibility)
3140
 * @return bool
3141
 * @author Patrick Cool <[email protected]>, Ghent University
3142
 * @author Julio Montoya
3143
 * @version 1.0
3144
 */
3145
function api_is_allowed($tool, $action, $task_id = 0)
3146
{
3147
    $_user = api_get_user_info();
3148
    $_course = api_get_course_info();
3149
3150
    if (api_is_course_admin()) {
3151
        return true;
3152
    }
3153
3154
    if (is_array($_course) and count($_course) > 0) {
3155
        require_once api_get_path(SYS_CODE_PATH).'permissions/permissions_functions.inc.php';
3156
3157
        // Getting the permissions of this user.
3158
        if ($task_id == 0) {
3159
            $user_permissions = get_permissions('user', $_user['user_id']);
3160
            $_SESSION['total_permissions'][$_course['code']] = $user_permissions;
3161
        }
3162
3163
        // Getting the permissions of the task.
3164
        if ($task_id != 0) {
3165
            $task_permissions = get_permissions('task', $task_id);
3166
            /* !!! */$_SESSION['total_permissions'][$_course['code']] = $task_permissions;
3167
        }
3168
        //print_r($_SESSION['total_permissions']);
3169
3170
        // Getting the permissions of the groups of the user
3171
        //$groups_of_user = GroupManager::get_group_ids($_course['db_name'], $_user['user_id']);
3172
3173
        //foreach($groups_of_user as $group)
3174
        //   $this_group_permissions = get_permissions('group', $group);
3175
3176
        // Getting the permissions of the courseroles of the user
3177
        $user_courserole_permissions = get_roles_permissions('user', $_user['user_id']);
3178
3179
        // Getting the permissions of the platformroles of the user
3180
        //$user_platformrole_permissions = get_roles_permissions('user', $_user['user_id'], ', platform');
3181
3182
        // Getting the permissions of the roles of the groups of the user
3183
        //foreach($groups_of_user as $group)
3184
        //    $this_group_courserole_permissions = get_roles_permissions('group', $group);
3185
3186
        // Getting the permissions of the platformroles of the groups of the user
3187
        //foreach($groups_of_user as $group)
3188
        //    $this_group_platformrole_permissions = get_roles_permissions('group', $group, 'platform');
3189
    }
3190
3191
    // If the permissions are limited, we have to map the extended ones to the limited ones.
3192
    if (api_get_setting('permissions') == 'limited') {
3193
        if ($action == 'Visibility') {
3194
            $action = 'Edit';
3195
        }
3196
        if ($action == 'Move') {
3197
            $action = 'Edit';
3198
        }
3199
    }
3200
3201
    // The session that contains all the permissions already exists for this course
3202
    // so there is no need to requery everything.
3203
    //my_print_r($_SESSION['total_permissions'][$_course['code']][$tool]);
3204
    if (is_array($_SESSION['total_permissions'][$_course['code']][$tool])) {
3205
        if (in_array($action, $_SESSION['total_permissions'][$_course['code']][$tool])) {
3206
            return true;
3207
        } else {
3208
            return false;
3209
        }
3210
    }
3211
}
3212
3213
/**
3214
 * Tells whether this user is an anonymous user
3215
 * @param int  $user_id      User ID (optional, will take session ID if not provided)
3216
 * @param bool $db_check     Whether to check in the database (true) or simply in
3217
 * the session (false) to see if the current user is the anonymous user
3218
 * @return bool     true if this user is anonymous, false otherwise
3219
 */
3220
function api_is_anonymous($user_id = null, $db_check = false)
3221
{
3222
    if ($db_check) {
3223
         if (!isset($user_id)) {
3224
            $user_id = api_get_user_id();
3225
        }
3226
        $info = api_get_user_info($user_id);
3227
3228
        if ($info['status'] == 6 || $user_id == 0 || empty($info)) {
3229
            return true;
3230
        }
3231
    }
3232
3233
    $checker = Container::getAuthorizationChecker();
3234
    if ($checker) {
3235
        if ($checker->isGranted('IS_AUTHENTICATED_FULLY')) {
3236
            return false;
3237
        }
3238
    }
3239
3240
    return true;
3241
3242
    $_user = Session::read('_user');
0 ignored issues
show
Unused Code introduced by
$_user = \ChamiloSession::read('_user'); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
3243
3244
    if (!isset($_user) || (isset($_user['user_id']) && $_user['user_id'] == 0)) {
3245
        // In some cases, api_set_anonymous doesn't seem to be triggered in local.inc.php. Make sure it is.
3246
        // Occurs in agenda for admin links - YW
3247
        /*global $use_anonymous;
3248
        if (isset($use_anonymous) && $use_anonymous) {*/
3249
        api_set_anonymous();
3250
        //}
3251
        return true;
3252
    }
3253
    return isset($_user['is_anonymous']) && $_user['is_anonymous'] === true;
3254
}
3255
3256
/**
3257
 * Displays message "You are not allowed here..." and exits the entire script.
3258
 * @param bool   $print_headers    Whether or not to print headers (default = false -> does not print them)
3259
 * @param string $message
3260
 */
3261
function api_not_allowed($print_headers = false, $message = null)
3262
{
3263
    if (empty($message)) {
3264
        $message = get_lang('NotAllowed');
3265
    }
3266
    throw new Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException($message);
3267
3268
    if (api_get_setting('sso_authentication') === 'true') {
0 ignored issues
show
Unused Code introduced by
if (api_get_setting('sso...osso->logout(); } } does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
3269
        global $osso;
3270
        if ($osso) {
3271
            $osso->logout();
3272
        }
3273
    }
3274
    $home_url = api_get_path(WEB_PATH);
3275
    $user_id = api_get_user_id();
3276
    $course = api_get_course_id();
3277
3278
    global $this_section;
3279
3280
    if (CustomPages::enabled() && !isset($user_id)) {
3281
        if (empty($user_id)) {
3282
            // Why the CustomPages::enabled() need to be to set the request_uri
3283
            $_SESSION['request_uri'] = $_SERVER['REQUEST_URI'];
3284
        }
3285
        CustomPages::display(CustomPages::INDEX_UNLOGGED);
3286
    }
3287
3288
    $origin = api_get_origin();
3289
3290
    $msg = null;
3291
    if (isset($message)) {
3292
        $msg = $message;
3293
    } else {
3294
        $msg = Display::return_message(
3295
            get_lang('NotAllowedClickBack').'<br/><br/><button onclick="goBack();">'.get_lang('GoBack').'</button><script>function goBack(){window.history.back();}</script>',
3296
            'error',
3297
            false
3298
        );
3299
    }
3300
3301
    $msg = Display::div($msg, array('align'=>'center'));
3302
    $show_headers = 0;
3303
3304
    if ($print_headers && $origin != 'learnpath') {
3305
        $show_headers = 1;
3306
    }
3307
3308
    $tpl = new Template(null, $show_headers, $show_headers);
3309
    $tpl->assign('hide_login_link', 1);
3310
    $tpl->assign('content', $msg);
3311
3312
    if (($user_id != 0 && !api_is_anonymous()) &&
3313
        (!isset($course) || $course == -1) &&
3314
        empty($_GET['cidReq'])
3315
    ) {
3316
        // if the access is not authorized and there is some login information
3317
        // but the cidReq is not found, assume we are missing course data and send the user
3318
        // to the user_portal
3319
        $tpl->display_one_col_template();
3320
        exit;
3321
    }
3322
3323
    if (!empty($_SERVER['REQUEST_URI']) &&
3324
        (!empty($_GET['cidReq']) ||
3325
            $this_section == SECTION_MYPROFILE ||
3326
            $this_section == SECTION_PLATFORM_ADMIN
3327
        )
3328
    ) {
3329
        $courseCode = api_get_course_id();
3330
        // Only display form and return to the previous URL if there was a course ID included
3331
        if ($user_id != 0 && !api_is_anonymous()) {
3332
            //if there is a user ID, then the user is not allowed but the session is still there. Say so and exit
3333
            $tpl->assign('content', $msg);
3334
            $tpl->display_one_col_template();
3335
            exit;
3336
        }
3337
3338
        if (!is_null($courseCode)) {
3339
            api_set_firstpage_parameter($courseCode);
3340
        }
3341
3342
        // If the user has no user ID, then his session has expired
3343
        $action = api_get_self().'?'.Security::remove_XSS($_SERVER['QUERY_STRING']);
3344
        $action = str_replace('&amp;', '&', $action);
3345
        $form = new FormValidator(
3346
            'formLogin',
3347
            'post',
3348
            $action,
3349
            null,
3350
            array(),
3351
            FormValidator::LAYOUT_BOX_NO_LABEL
3352
        );
3353
        $form->addElement(
3354
            'text',
3355
            'login',
3356
            null,
3357
            array('placeholder' => get_lang('UserName'), 'autocapitalize' => 'none')
3358
        );
3359
        $form->addElement(
3360
            'password',
3361
            'password',
3362
            null,
3363
            array('placeholder' => get_lang('Password'), 'autocapitalize' => 'none')
3364
        );
3365
        $form->addButton('submitAuth', get_lang('LoginEnter'), '', 'primary');
3366
3367
        // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (above)
3368
        $content = Display::return_message(get_lang('NotAllowed'), 'error', false);
3369
3370
        if (!empty($courseCode)) {
3371
            $content .= '<h4>'.get_lang('LoginToGoToThisCourse').'</h4>';
3372
        }
3373
3374
        if (api_is_cas_activated()) {
3375
            $content .= Display::return_message(sprintf(get_lang('YouHaveAnInstitutionalAccount'), api_get_setting("Institution")), '', false);
3376
            $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'));
3377
            $content .= Display::return_message(get_lang('YouDontHaveAnInstitutionAccount'));
3378
            $content .= "<p style='text-align:center'><a href='#' onclick='$(this).parent().next().toggle()'>".get_lang('LoginWithExternalAccount')."</a></p>";
3379
            $content .= "<div style='display:none;'>";
3380
        }
3381
        $content .= '<div class="well">';
3382
        $content .= $form->returnForm();
3383
        $content .= '</div>';
3384
        if (api_is_cas_activated()) {
3385
            $content .= "</div>";
3386
        }
3387
3388
        if (!empty($courseCode)) {
3389
            $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
3390
                get_lang('ReturnToCourseHomepage').'</a></p>';
3391
        } else {
3392
            $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
3393
                get_lang('BackHome').'</a></p>';
3394
        }
3395
3396
        $tpl->setLoginBodyClass();
3397
        $tpl->assign('content', $content);
3398
        $tpl->display_one_col_template();
3399
        exit;
3400
    }
3401
3402
    if ($user_id != 0 && !api_is_anonymous()) {
3403
        $tpl->display_one_col_template();
3404
        exit;
3405
    }
3406
3407
    $msg = null;
3408
3409
    // The session is over and we were not in a course,
3410
    // or we try to get directly to a private course without being logged
3411
    $courseId = api_get_course_int_id();
3412
    if (!empty($courseId)) {
3413
        api_set_firstpage_parameter(api_get_course_id());
3414
        $tpl->setLoginBodyClass();
3415
        $action = api_get_self().'?'.Security::remove_XSS($_SERVER['QUERY_STRING']);
3416
        $action = str_replace('&amp;', '&', $action);
3417
        $form = new FormValidator('formLogin', 'post', $action, null, array('class'=>'form-stacked'));
3418
        $form->addElement('text', 'login', null, array('autocapitalize' => 'none', 'placeholder' => get_lang('UserName'), 'class' => 'col-md-3'));
3419
        $form->addElement('password', 'password', null, array('placeholder' => get_lang('Password'), 'class' => 'col-md-3')); //new
3420
        $form->addButtonNext(get_lang('LoginEnter'), 'submitAuth');
3421
3422
        // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (bellow)
3423
        $msg = Display::return_message(get_lang('NotAllowed'), 'error', false);
3424
        $msg .= '<h4>'.get_lang('LoginToGoToThisCourse').'</h4>';
3425
        $casEnabled = api_is_cas_activated();
3426
        if ($casEnabled) {
3427
            $msg .= Display::return_message(sprintf(get_lang('YouHaveAnInstitutionalAccount'), api_get_setting("Institution")), '', false);
3428
            $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'));
3429
            $msg .= Display::return_message(get_lang('YouDontHaveAnInstitutionAccount'));
3430
            $msg .= "<p style='text-align:center'><a href='#' onclick='$(this).parent().next().toggle()'>".get_lang('LoginWithExternalAccount')."</a></p>";
3431
            $msg .= "<div style='display:none;'>";
3432
        }
3433
        $msg .= '<div class="well">';
3434
        $msg .= $form->returnForm();
3435
        $msg .= '</div>';
3436
        if ($casEnabled) {
3437
            $msg .= "</div>";
3438
        }
3439
    } else {
3440
        // we were not in a course, return to home page
3441
        $msg = Display::return_message(
3442
            get_lang('NotAllowed').'<br/><br/><a href="'.$home_url.'">'.get_lang('BackHome').'</a><br />',
3443
            'error',
3444
            false
3445
        );
3446
        if (!empty($message)) {
3447
            $msg = $message;
3448
        }
3449
    }
3450
3451
    $tpl->assign('content', $msg);
3452
    $tpl->display_one_col_template();
3453
    exit;
3454
}
3455
3456
/**
3457
 * Gets a UNIX timestamp from a database (MySQL) datetime format string
3458
 * @param $last_post_datetime standard output date in a sql query
3459
 * @return integer timestamp
3460
 * @author Toon Van Hoecke <[email protected]>
3461
 * @version October 2003
3462
 * @desc convert sql date to unix timestamp
3463
 */
3464
function convert_sql_date($last_post_datetime)
3465
{
3466
    list ($last_post_date, $last_post_time) = explode(' ', $last_post_datetime);
3467
    list ($year, $month, $day) = explode('-', $last_post_date);
3468
    list ($hour, $min, $sec) = explode(':', $last_post_time);
3469
    return mktime((int) $hour, (int) $min, (int) $sec, (int) $month, (int) $day, (int) $year);
3470
}
3471
3472
/**
3473
 * Gets item visibility from the item_property table
3474
 *
3475
 * Getting the visibility is done by getting the last updated visibility entry,
3476
 * using the largest session ID found if session 0 and another was found (meaning
3477
 * the only one that is actually from the session, in case there are results from
3478
 * session 0 *AND* session n).
3479
 * @param array     Course properties array (result of api_get_course_info())
3480
 * @param string    Tool (learnpath, document, etc)
3481
 * @param int       The item ID in the given tool
3482
 * @param int       The session ID (optional)
3483
 * @param string $tool
3484
 * @param integer $user_id
3485
 * @param string $type
3486
 * @return int      -1 on error, 0 if invisible, 1 if visible
3487
 */
3488
function api_get_item_visibility(
3489
    $_course,
3490
    $tool,
3491
    $id,
3492
    $session = 0,
3493
    $user_id = null,
3494
    $type = null,
3495
    $group_id = null
3496
) {
3497
    if (!is_array($_course) || count($_course) == 0 || empty($tool) || empty($id)) {
3498
        return -1;
3499
    }
3500
3501
    $tool = Database::escape_string($tool);
3502
    $id = intval($id);
3503
    $session = (int) $session;
3504
    $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
3505
    $course_id = intval($_course['real_id']);
3506
3507
    $userCondition = '';
3508
    if (!empty($user_id)) {
3509
        $user_id = intval($user_id);
3510
        $userCondition = " AND to_user_id = $user_id ";
3511
    }
3512
3513
    $typeCondition = '';
3514
    if (!empty($type)) {
3515
        $type = Database::escape_string($type);
3516
        $typeCondition = " AND lastedit_type = '$type' ";
3517
    }
3518
3519
    $groupCondition = '';
3520
    if (!empty($group_id)) {
3521
        $group_id = intval($group_id);
3522
        $groupCondition = " AND to_group_id = '$group_id' ";
3523
    }
3524
3525
    $sql = "SELECT visibility
3526
            FROM $TABLE_ITEMPROPERTY
3527
            WHERE
3528
                c_id = $course_id AND
3529
                tool = '$tool' AND
3530
                ref = $id AND
3531
                (session_id = $session OR session_id = 0 OR session_id IS NULL)
3532
                $userCondition $typeCondition $groupCondition
3533
            ORDER BY session_id DESC, lastedit_date DESC
3534
            LIMIT 1";
3535
3536
    $res = Database::query($sql);
3537
    if ($res === false || Database::num_rows($res) == 0) {
3538
        return -1;
3539
    }
3540
    $row = Database::fetch_array($res);
3541
3542
    return $row['visibility'];
3543
}
3544
3545
/**
3546
 * Delete a row in the c_item_property table
3547
 *
3548
 * @param array $courseInfo
3549
 * @param string $tool
3550
 * @param int $itemId
3551
 * @param int $userId
3552
 * @param int $groupId group.iid
3553
 * @param int $sessionId
3554
 * @return false|null
3555
 */
3556
function api_item_property_delete(
3557
    $courseInfo,
3558
    $tool,
3559
    $itemId,
3560
    $userId,
3561
    $groupId = 0,
3562
    $sessionId = 0
3563
) {
3564
    if (empty($courseInfo)) {
3565
        return false;
3566
    }
3567
3568
    $courseId = intval($courseInfo['real_id']);
3569
3570
    if (empty($courseId) || empty($tool) || empty($itemId)) {
3571
        return false;
3572
    }
3573
3574
    $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3575
    $tool = Database::escape_string($tool);
3576
    $itemId = intval($itemId);
3577
    $userId = intval($userId);
3578
    $groupId = intval($groupId);
3579
    $sessionId = intval($sessionId);
3580
3581
    $groupCondition = " AND to_group_id = $groupId ";
3582
    if (empty($groupId)) {
3583
        $groupCondition = " AND (to_group_id is NULL OR to_group_id = 0) ";
3584
    }
3585
3586
    $userCondition = " AND to_user_id = $userId ";
3587
    if (empty($userId)) {
3588
        $userCondition = " AND (to_user_id is NULL OR to_user_id = 0) ";
3589
    }
3590
    $sessionCondition = api_get_session_condition($sessionId, true, false, 'session_id');
3591
    $sql = "DELETE FROM $table
3592
            WHERE
3593
                c_id = $courseId AND
3594
                tool  = '$tool' AND
3595
                ref = $itemId
3596
                $sessionCondition
3597
                $userCondition
3598
                $groupCondition
3599
            ";
3600
3601
    Database::query($sql);
3602
}
3603
3604
/**
3605
 * Updates or adds item properties to the Item_propetry table
3606
 * Tool and lastedit_type are language independant strings (langvars->get_lang!)
3607
 *
3608
 * @param array $_course array with course properties
3609
 * @param string $tool tool id, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
3610
 * @param int $item_id id of the item itself, linked to key of every tool ('id', ...)
3611
 * @param string $last_edit_type add or update action
3612
 * (1) message to be translated (in trad4all) : e.g. DocumentAdded, DocumentUpdated;
3613
 * (2) "delete"
3614
 * (3) "visible"
3615
 * (4) "invisible"
3616
 * @param int $user_id id of the editing/adding user
3617
 * @param array $groupInfo must include group.iid/group.od
3618
 * @param int $to_user_id id of the intended user (always has priority over $to_group_id !), only relevant for $type (1)
3619
 * @param string $start_visible 0000-00-00 00:00:00 format
3620
 * @param string $end_visible 0000-00-00 00:00:00 format
3621
 * @param int $session_id The session ID, if any, otherwise will default to 0
3622
 * @return boolean False if update fails.
3623
 * @author Toon Van Hoecke <[email protected]>, Ghent University
3624
 * @version January 2005
3625
 * @desc update the item_properties table (if entry not exists, insert) of the course
3626
 */
3627
function api_item_property_update(
3628
    $_course,
3629
    $tool,
3630
    $item_id,
3631
    $last_edit_type,
3632
    $user_id,
3633
    $groupInfo = [],
3634
    $to_user_id = null,
3635
    $start_visible = '',
3636
    $end_visible = '',
3637
    $session_id = 0
3638
) {
3639
    if (empty($_course)) {
3640
        return false;
3641
    }
3642
3643
    $course_id = $_course['real_id'];
3644
3645
    if (empty($course_id)) {
3646
        return false;
3647
    }
3648
3649
    $to_group_id = 0;
3650
    if (!empty($groupInfo) && isset($groupInfo['iid'])) {
3651
        $to_group_id = $groupInfo['iid'];
3652
    }
3653
3654
    $em = Database::getManager();
3655
3656
    // Definition of variables.
3657
    $tool = Database::escape_string($tool);
3658
    $item_id = intval($item_id);
3659
    $lastEditTypeNoFilter = $last_edit_type;
3660
    $last_edit_type = Database::escape_string($last_edit_type);
3661
    $user_id = intval($user_id);
3662
3663
    $startVisible = "NULL";
3664
    if (!empty($start_visible)) {
3665
        $start_visible = Database::escape_string($start_visible);
3666
        $startVisible = "'$start_visible'";
3667
    }
3668
3669
    $endVisible = "NULL";
3670
    if (!empty($end_visible)) {
3671
        $end_visible = Database::escape_string($end_visible);
3672
        $endVisible = "'$end_visible'";
3673
    }
3674
3675
    $to_filter = '';
3676
    $time = api_get_utc_datetime();
3677
3678
    if (!empty($session_id)) {
3679
        $session_id = intval($session_id);
3680
    } else {
3681
        $session_id = api_get_session_id();
3682
    }
3683
3684
    // Definition of tables.
3685
    $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
3686
3687
    if ($to_user_id <= 0) {
3688
        $to_user_id = null; // No to_user_id set
3689
    }
3690
3691
    if (!is_null($to_user_id)) {
3692
        // $to_user_id has more priority than $to_group_id
3693
        $to_user_id = intval($to_user_id);
3694
        $to_field = 'to_user_id';
3695
        $to_value = $to_user_id;
3696
    } else {
3697
        // $to_user_id is not set.
3698
        $to_field = 'to_group_id';
3699
        $to_value = $to_group_id;
3700
    }
3701
3702
    $toValueCondition = empty($to_value) ? "NULL" : "'$to_value'";
3703
    // Set filters for $to_user_id and $to_group_id, with priority for $to_user_id
3704
    $condition_session = " AND session_id = $session_id ";
3705
    if (empty($session_id)) {
3706
        $condition_session = " AND (session_id = 0 OR session_id IS NULL) ";
3707
    }
3708
3709
    $filter = " c_id = $course_id AND tool = '$tool' AND ref = $item_id $condition_session ";
3710
3711
    // Check whether $to_user_id and $to_group_id are passed in the function call.
3712
    // If both are not passed (both are null) then it is a message for everybody and $to_group_id should be 0 !
3713
    if (is_null($to_user_id) && is_null($to_group_id)) {
3714
        $to_group_id = 0;
3715
    }
3716
3717
    if (!is_null($to_user_id)) {
3718
        // Set filter to intended user.
3719
        $to_filter = " AND to_user_id = $to_user_id $condition_session";
3720
    } else {
3721
        // Set filter to intended group.
3722
        if (($to_group_id != 0) && $to_group_id == strval(intval($to_group_id))) {
3723
            $to_filter = " AND to_group_id = $to_group_id $condition_session";
3724
        }
3725
    }
3726
3727
    // Adding filter if set.
3728
    $filter .= $to_filter;
3729
3730
    // Update if possible
3731
    $set_type = '';
3732
3733
    switch ($lastEditTypeNoFilter) {
3734 View Code Duplication
        case 'delete':
3735
            // delete = make item only visible for the platform admin.
3736
            $visibility = '2';
3737
            if (!empty($session_id)) {
3738
                // Check whether session id already exist into item_properties for updating visibility or add it.
3739
                $sql = "SELECT session_id FROM $tableItemProperty
3740
                        WHERE
3741
                            c_id = $course_id AND
3742
                            tool = '$tool' AND
3743
                            ref = $item_id AND
3744
                            session_id = $session_id";
3745
                $rs = Database::query($sql);
3746
                if (Database::num_rows($rs) > 0) {
3747
                    $sql = "UPDATE $tableItemProperty
3748
                            SET lastedit_type       = '".str_replace('_', '', ucwords($tool))."Deleted',
3749
                                lastedit_date       = '$time',
3750
                                lastedit_user_id    = $user_id,
3751
                                visibility          = $visibility,
3752
                                session_id          = $session_id $set_type
3753
                            WHERE $filter";
3754
                    $result = Database::query($sql);
3755
                } else {
3756
                    $sql = "INSERT INTO $tableItemProperty (c_id, tool, ref, insert_date, insert_user_id, lastedit_date, lastedit_type, lastedit_user_id, $to_field, visibility, start_visible, end_visible, session_id)
3757
                            VALUES ($course_id, '$tool',$item_id, '$time', $user_id, '$time', '$last_edit_type',$user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3758
                    $result = Database::query($sql);
3759
                    $id = Database::insert_id();
3760
                    if ($id) {
3761
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3762
                        Database::query($sql);
3763
                    }
3764
                }
3765
            } else {
3766
                $sql = "UPDATE $tableItemProperty
3767
                        SET
3768
                            lastedit_type='".str_replace('_', '', ucwords($tool))."Deleted',
3769
                            lastedit_date='$time',
3770
                            lastedit_user_id = $user_id,
3771
                            visibility = $visibility $set_type
3772
                        WHERE $filter";
3773
                $result = Database::query($sql);
3774
            }
3775
            break;
3776 View Code Duplication
        case 'visible': // Change item to visible.
3777
            $visibility = '1';
3778
            if (!empty($session_id)) {
3779
                // Check whether session id already exist into item_properties for updating visibility or add it.
3780
                $sql = "SELECT session_id FROM $tableItemProperty
3781
                        WHERE
3782
                            c_id = $course_id AND
3783
                            tool = '$tool' AND
3784
                            ref = $item_id AND
3785
                            session_id = $session_id";
3786
                $rs = Database::query($sql);
3787
                if (Database::num_rows($rs) > 0) {
3788
                    $sql = "UPDATE $tableItemProperty
3789
                            SET
3790
                                lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
3791
                                lastedit_date='$time',
3792
                                lastedit_user_id = $user_id,
3793
                                visibility = $visibility,
3794
                                session_id = $session_id $set_type
3795
                            WHERE $filter";
3796
                    $result = Database::query($sql);
3797
                } else {
3798
                    $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)
3799
                            VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3800
                    $result = Database::query($sql);
3801
                    $id = Database::insert_id();
3802
                    if ($id) {
3803
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3804
                        Database::query($sql);
3805
                    }
3806
                }
3807
            } else {
3808
                $sql = "UPDATE $tableItemProperty
3809
                        SET
3810
                            lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
3811
                            lastedit_date='$time',
3812
                            lastedit_user_id = $user_id,
3813
                            visibility = $visibility $set_type
3814
                        WHERE $filter";
3815
                $result = Database::query($sql);
3816
            }
3817
            break;
3818 View Code Duplication
        case 'invisible': // Change item to invisible.
3819
            $visibility = '0';
3820
            if (!empty($session_id)) {
3821
                // Check whether session id already exist into item_properties for updating visibility or add it
3822
                $sql = "SELECT session_id FROM $tableItemProperty
3823
                        WHERE
3824
                            c_id = $course_id AND
3825
                            tool = '$tool' AND
3826
                            ref = $item_id AND
3827
                            session_id = $session_id";
3828
                $rs = Database::query($sql);
3829
                if (Database::num_rows($rs) > 0) {
3830
                    $sql = "UPDATE $tableItemProperty
3831
                            SET
3832
                                lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
3833
                                lastedit_date = '$time',
3834
                                lastedit_user_id = $user_id,
3835
                                visibility = $visibility,
3836
                                session_id = $session_id $set_type
3837
                            WHERE $filter";
3838
                    $result = Database::query($sql);
3839
                } else {
3840
                    $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)
3841
                            VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3842
                    $result = Database::query($sql);
3843
                    $id = Database::insert_id();
3844
                    if ($id) {
3845
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3846
                        Database::query($sql);
3847
                    }
3848
                }
3849
            } else {
3850
                $sql = "UPDATE $tableItemProperty
3851
                        SET
3852
                            lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
3853
                            lastedit_date = '$time',
3854
                            lastedit_user_id = $user_id,
3855
                            visibility = $visibility $set_type
3856
                        WHERE $filter";
3857
                $result = Database::query($sql);
3858
            }
3859
            break;
3860
        default: // The item will be added or updated.
3861
            $set_type = ", lastedit_type = '$last_edit_type' ";
3862
            $visibility = '1';
3863
            //$filter .= $to_filter; already added
3864
            $sql = "UPDATE $tableItemProperty
3865
                    SET
3866
                      lastedit_date = '$time',
3867
                      lastedit_user_id = $user_id $set_type
3868
                    WHERE $filter";
3869
            $result = Database::query($sql);
3870
    }
3871
3872
    // Insert if no entries are found (can only happen in case of $last_edit_type switch is 'default').
3873
    if ($result == false || Database::affected_rows($result) == 0) {
3874
        $objCourse = $em->find('ChamiloCoreBundle:Course', intval($course_id));
3875
        $objTime = new DateTime('now', new DateTimeZone('UTC'));
3876
        $objUser = $em->find('ChamiloUserBundle:User', intval($user_id));
3877
        $objGroup = $em->find('ChamiloCourseBundle:CGroupInfo', intval($to_group_id));
3878
        $objToUser = $em->find('ChamiloUserBundle:User', intval($to_user_id));
3879
        $objSession = $em->find('ChamiloCoreBundle:Session', intval($session_id));
3880
3881
        $startVisibleDate = !empty($start_visible) ? new DateTime($start_visible, new DateTimeZone('UTC')) : null;
3882
        $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...
3883
3884
        $cItemProperty = new CItemProperty($objCourse);
3885
        $cItemProperty
3886
            ->setTool($tool)
3887
            ->setRef($item_id)
3888
            ->setInsertDate($objTime)
3889
            ->setInsertUser($objUser)
3890
            ->setLasteditDate($objTime)
3891
            ->setLasteditType($last_edit_type)
3892
            ->setGroup($objGroup)
3893
            ->setToUser($objToUser)
3894
            ->setVisibility($visibility)
3895
            ->setStartVisible($startVisibleDate)
3896
            ->setEndVisible($endVisibleDate)
3897
            ->setSession($objSession);
3898
3899
        $em->persist($cItemProperty);
3900
        $em->flush();
3901
3902
        $id = $cItemProperty->getIid();
3903
3904
        if ($id) {
3905
            $cItemProperty->setId($id);
3906
            $em->merge($cItemProperty);
3907
            $em->flush();
3908
3909
            return false;
3910
        }
3911
    }
3912
3913
    return true;
3914
}
3915
3916
/**
3917
 * Gets item property by tool
3918
 * @param string    course code
3919
 * @param string    tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
3920
 * @param int       id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
3921
 * @param int $session_id
3922
 * @param string $tool
3923
 * @param string $course_code
3924
 * @return array All fields from c_item_property (all rows found) or empty array
3925
 */
3926 View Code Duplication
function api_get_item_property_by_tool($tool, $course_code, $session_id = null)
3927
{
3928
    $course_info = api_get_course_info($course_code);
3929
    $tool = Database::escape_string($tool);
3930
3931
    // Definition of tables.
3932
    $item_property_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3933
    $session_id = intval($session_id);
3934
    $session_condition = ' AND session_id = '.$session_id;
3935
    if (empty($session_id)) {
3936
        $session_condition = " AND (session_id = 0 OR session_id IS NULL) ";
3937
    }
3938
    $course_id = $course_info['real_id'];
3939
3940
    $sql = "SELECT * FROM $item_property_table
3941
            WHERE
3942
                c_id = $course_id AND
3943
                tool = '$tool'
3944
                $session_condition ";
3945
    $rs = Database::query($sql);
3946
    $list = array();
3947
    if (Database::num_rows($rs) > 0) {
3948
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
3949
            $list[] = $row;
3950
        }
3951
    }
3952
    return $list;
3953
}
3954
3955
/**
3956
 * Gets item property by tool and user
3957
 * @param int $userId
3958
 * @param int $tool
3959
 * @param int $courseId
3960
 * @param int $session_id
3961
 * @return array
3962
 */
3963 View Code Duplication
function api_get_item_property_list_by_tool_by_user(
3964
    $userId,
3965
    $tool,
3966
    $courseId,
3967
    $session_id = 0
3968
) {
3969
    $userId = intval($userId);
3970
    $tool = Database::escape_string($tool);
3971
    $session_id = intval($session_id);
3972
    $courseId = intval($courseId);
3973
3974
    // Definition of tables.
3975
    $item_property_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3976
    $session_condition = ' AND session_id = '.$session_id;
3977
    if (empty($session_id)) {
3978
        $session_condition = " AND (session_id = 0 OR session_id IS NULL) ";
3979
    }
3980
    $sql = "SELECT * FROM $item_property_table
3981
            WHERE
3982
                insert_user_id = $userId AND
3983
                c_id = $courseId AND
3984
                tool = '$tool'
3985
                $session_condition ";
3986
3987
    $rs = Database::query($sql);
3988
    $list = array();
3989
    if (Database::num_rows($rs) > 0) {
3990
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
3991
            $list[] = $row;
3992
        }
3993
    }
3994
3995
    return $list;
3996
}
3997
3998
/**
3999
 * Gets item property id from tool of a course
4000
 * @param string $course_code course code
4001
 * @param string $tool tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
4002
 * @param int $ref id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
4003
 * @param int $sessionId Session ID (optional)
4004
 * @return int
4005
 */
4006
function api_get_item_property_id($course_code, $tool, $ref, $sessionId = 0)
4007
{
4008
    $course_info = api_get_course_info($course_code);
4009
    $tool = Database::escape_string($tool);
4010
    $ref = intval($ref);
4011
4012
    // Definition of tables.
4013
    $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
4014
    $course_id = $course_info['real_id'];
4015
    $sessionId = (int) $sessionId;
4016
    $sessionCondition = " AND session_id = $sessionId ";
4017
    if (empty($sessionId)) {
4018
        $sessionCondition = " AND (session_id = 0 OR session_id IS NULL) ";
4019
    }
4020
    $sql = "SELECT id FROM $tableItemProperty
4021
            WHERE
4022
                c_id = $course_id AND
4023
                tool = '$tool' AND
4024
                ref = $ref
4025
                $sessionCondition";
4026
    $rs = Database::query($sql);
4027
    $item_property_id = '';
4028
    if (Database::num_rows($rs) > 0) {
4029
        $row = Database::fetch_array($rs);
4030
        $item_property_id = $row['id'];
4031
    }
4032
    return $item_property_id;
4033
}
4034
4035
/**
4036
 * Inserts a record in the track_e_item_property table (No update)
4037
 * @param string $tool
4038
 * @param int $ref
4039
 * @param string $title
4040
 * @param string $content
4041
 * @param int $progress
4042
 * @return bool|int
4043
 */
4044
function api_track_item_property_update($tool, $ref, $title, $content, $progress)
4045
{
4046
    $tbl_stats_item_property = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY);
4047
    $course_id = api_get_course_int_id(); //numeric
4048
    $course_code = api_get_course_id(); //alphanumeric
4049
    $item_property_id = api_get_item_property_id($course_code, $tool, $ref);
4050
    if (!empty($item_property_id)) {
4051
        $sql = "INSERT IGNORE INTO $tbl_stats_item_property SET
4052
                course_id           = '$course_id',
4053
                item_property_id    = '$item_property_id',
4054
                title               = '".Database::escape_string($title)."',
4055
                content             = '".Database::escape_string($content)."',
4056
                progress            = '".intval($progress)."',
4057
                lastedit_date       = '".api_get_utc_datetime()."',
4058
                lastedit_user_id    = '".api_get_user_id()."',
4059
                session_id          = '".api_get_session_id()."'";
4060
        $result = Database::query($sql);
4061
        $affected_rows = Database::affected_rows($result);
4062
4063
        return $affected_rows;
4064
    }
4065
4066
    return false;
4067
}
4068
4069
/**
4070
 * @param string $tool
4071
 * @param int $ref
4072
 * @return array|resource
4073
 */
4074
function api_get_track_item_property_history($tool, $ref)
4075
{
4076
    $tbl_stats_item_property = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY);
4077
    $course_id = api_get_course_int_id(); //numeric
4078
    $course_code = api_get_course_id(); //alphanumeric
4079
    $item_property_id = api_get_item_property_id($course_code, $tool, $ref);
4080
    $sql = "SELECT * FROM $tbl_stats_item_property
4081
            WHERE item_property_id = $item_property_id AND course_id = $course_id
4082
            ORDER BY lastedit_date DESC";
4083
    $result = Database::query($sql);
4084
    if ($result === false or $result === null) {
4085
        $result = array();
4086
    } else {
4087
        $result = Database::store_result($result, 'ASSOC');
4088
    }
4089
4090
    return $result;
4091
}
4092
4093
/**
4094
 * Gets item property data from tool of a course id
4095
 * @param int $course_id
4096
 * @param string $tool   tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
4097
 * @param int $ref id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
4098
 * @param int $session_id
4099
 * @param int $groupId
4100
 *
4101
 * @return array Array with all fields from c_item_property, empty array if not found or false if course could not be found
4102
 */
4103
function api_get_item_property_info($course_id, $tool, $ref, $session_id = 0, $groupId = 0)
4104
{
4105
    $courseInfo = api_get_course_info_by_id($course_id);
4106
4107
    if (empty($courseInfo)) {
4108
        return false;
4109
    }
4110
4111
    $tool = Database::escape_string($tool);
4112
    $ref = intval($ref);
4113
    $course_id = $courseInfo['real_id'];
4114
    $session_id = intval($session_id);
4115
4116
    $sessionCondition = " session_id = $session_id";
4117
    if (empty($session_id)) {
4118
        $sessionCondition = " (session_id = 0 OR session_id IS NULL) ";
4119
    }
4120
4121
    // Definition of tables.
4122
    $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
4123
4124
    $sql = "SELECT * FROM $table
4125
            WHERE
4126
                c_id = $course_id AND
4127
                tool = '$tool' AND
4128
                ref = $ref AND
4129
                $sessionCondition ";
4130
4131
    if (!empty($groupId)) {
4132
        $groupId = intval($groupId);
4133
        $sql .= " AND to_group_id = $groupId ";
4134
    }
4135
4136
    $rs  = Database::query($sql);
4137
    $row = array();
4138
    if (Database::num_rows($rs) > 0) {
4139
        $row = Database::fetch_array($rs, 'ASSOC');
4140
    }
4141
4142
    return $row;
4143
}
4144
4145
/**
4146
 * Displays a combo box so the user can select his/her preferred language.
4147
 * @param string The desired name= value for the select
4148
 * @param bool Whether we use the JQuery Chozen library or not
4149
 * (in some cases, like the indexing language picker, it can alter the presentation)
4150
 * @return string
4151
 */
4152
function api_get_languages_combo($name = 'language')
4153
{
4154
    $ret = '';
4155
    $platformLanguage = api_get_setting('platformLanguage');
4156
4157
    // Retrieve a complete list of all the languages.
4158
    $language_list = api_get_languages();
4159
4160
    if (count($language_list['name']) < 2) {
4161
        return $ret;
4162
    }
4163
4164
    // The the current language of the user so that his/her language occurs as selected in the dropdown menu.
4165
    if (isset($_SESSION['user_language_choice'])) {
4166
        $default = $_SESSION['user_language_choice'];
4167
    } else {
4168
        $default = $platformLanguage;
4169
    }
4170
4171
    $languages = $language_list['name'];
4172
    $folder = $language_list['folder'];
4173
4174
    $ret .= '<select name="'.$name.'" id="language_chosen" class="selectpicker show-tick form-control">';
4175
    foreach ($languages as $key => $value) {
4176
        if ($folder[$key] == $default) {
4177
            $selected = ' selected="selected"';
4178
        } else {
4179
            $selected = '';
4180
        }
4181
        $ret .= sprintf('<option value=%s" %s>%s</option>', $folder[$key], $selected, $value);
4182
    }
4183
    $ret .= '</select>';
4184
4185
    return $ret;
4186
}
4187
4188
/**
4189
 * Displays a form (drop down menu) so the user can select his/her preferred language.
4190
 * The form works with or without javascript
4191
 * @param  boolean Hide form if only one language available (defaults to false = show the box anyway)
4192
 * @return null|string Display the box directly
4193
 */
4194
function api_display_language_form($hide_if_no_choice = false)
4195
{
4196
    // Retrieve a complete list of all the languages.
4197
    $language_list = api_get_languages();
4198
4199
    if (count($language_list) <= 1 && $hide_if_no_choice) {
4200
        return; //don't show any form
4201
    }
4202
4203
    // The the current language of the user so that his/her language occurs as selected in the dropdown menu.
4204
    if (isset($_SESSION['user_language_choice'])) {
4205
        $user_selected_language = $_SESSION['user_language_choice'];
4206
    }
4207
    if (empty($user_selected_language)) {
4208
        $user_selected_language = api_get_setting('platformLanguage');
4209
    }
4210
4211
    $original_languages = $language_list;
4212
    $folder = $language_list; // This line is probably no longer needed.
4213
    $html = '<script>    
4214
    $(document).ready(function() {
4215
        $("#language_list").change(function() {
4216
            jumpMenu("parent",this,0);
4217
        });
4218
    });
4219
4220
    function jumpMenu(targ,selObj,restore){ // v3.0
4221
        eval(targ+".location=\'"+selObj.options[selObj.selectedIndex].value+"\'");
4222
        if (restore) selObj.selectedIndex=0;
4223
    }
4224
    </script>';
4225
    $html .= '<form id="lang_form" name="lang_form" method="post" action="'.api_get_self().'">';
4226
    $html .= '<label style="display: none;" for="language_list">'.get_lang('Language').'</label>';
4227
    $html .= '<select id="language_list" class="selectpicker show-tick form-control" name="language_list" >';
4228
4229
    foreach ($original_languages as $key => $value) {
4230
        if ($folder[$key] == $user_selected_language) {
4231
            $option_end = ' selected="selected" >';
4232
        } else {
4233
            $option_end = '>';
4234
        }
4235
        $html .= '<option value="'.api_get_self().'?language='.$folder[$key].'"'.$option_end;
4236
        //echo substr($value, 0, 16); // Cut string to keep 800x600 aspect.
4237
        $html .= $value.'</option>';
4238
    }
4239
    $html .= '</select>';
4240
    $html .= '<noscript><input type="submit" name="user_select_language" value="'.get_lang('Ok').'" /></noscript>';
4241
    $html .= '</form>';
4242
    return $html;
4243
}
4244
4245
/**
4246
 * Returns a list of all the languages that are made available by the admin.
4247
 * @return array An array with all languages. Structure of the array is
4248
 *  array['name'] = An array with the name of every language
4249
 *  array['folder'] = An array with the corresponding names of the language-folders in the filesystem
4250
 */
4251
function api_get_languages()
4252
{
4253
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4254
    $sql = "SELECT * FROM $tbl_language WHERE available='1' 
4255
            ORDER BY original_name ASC";
4256
    $result = Database::query($sql);
4257
    $language_list = array();
4258
   while ($row = Database::fetch_array($result)) {
4259
        $language_list[$row['isocode']] = $row['original_name'];
4260
    }
4261
    return $language_list;
4262
}
4263
4264
/**
4265
 * Returns a list of all the languages that are made available by the admin.
4266
 * @return array
4267
 */
4268 View Code Duplication
function api_get_languages_to_array()
4269
{
4270
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4271
    $sql = "SELECT * FROM $tbl_language WHERE available='1' ORDER BY original_name ASC";
4272
    $result = Database::query($sql);
4273
    $languages = array();
4274
    while ($row = Database::fetch_array($result)) {
4275
        $languages[$row['dokeos_folder']] = $row['original_name'];
4276
    }
4277
    return $languages;
4278
}
4279
4280
/**
4281
 * Returns the id (the database id) of a language
4282
 * @param   string  language name (the corresponding name of the language-folder in the filesystem)
4283
 * @return  int     id of the language
4284
 */
4285 View Code Duplication
function api_get_language_id($language)
4286
{
4287
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4288
    if (empty($language)) {
4289
        return null;
4290
    }
4291
    $language = Database::escape_string($language);
4292
    $sql = "SELECT id FROM $tbl_language
4293
            WHERE dokeos_folder = '$language' LIMIT 1";
4294
    $result = Database::query($sql);
4295
    $row = Database::fetch_array($result);
4296
    return $row['id'];
4297
}
4298
4299
/**
4300
 * Gets language of the requested type for the current user. Types are :
4301
 * user_profil_lang : profile language of current user
4302
 * user_select_lang : language selected by user at login
4303
 * course_lang : language of the current course
4304
 * platform_lang : default platform language
4305
 * @param string $lang_type
4306
 * @return string
4307
 **/
4308
function api_get_language_from_type($lang_type)
4309
{
4310
    $return = false;
4311
    switch ($lang_type) {
4312
        case 'platform_lang':
4313
            $temp_lang = api_get_setting('platformLanguage');
4314
            if (!empty($temp_lang))
4315
                $return = $temp_lang;
4316
            break;
4317
        case 'user_profil_lang':
4318
            $_user = api_get_user_info();
4319
4320
            if (isset($_user['language']) && !empty($_user['language']))
4321
                $return = $_user['language'];
4322
            break;
4323
        case 'user_selected_lang':
4324 View Code Duplication
            if (isset($_SESSION['user_language_choice']) && !empty($_SESSION['user_language_choice']))
4325
                $return = $_SESSION['user_language_choice'];
4326
            break;
4327
        case 'course_lang':
4328
            global $_course;
4329
            $cidReq = null;
4330
            if (empty($_course)) {
4331
4332
                // Code modified because the local.inc.php file it's declarated after this work
4333
                // causing the function api_get_course_info() returns a null value
4334
                $cidReq = isset($_GET["cidReq"]) ? Database::escape_string($_GET["cidReq"]) : null;
4335
                $cDir = (!empty($_GET['cDir']) ? $_GET['cDir'] : null);
4336
                if (empty($cidReq) && !empty($cDir)) {
4337
                    $c = CourseManager::get_course_id_from_path($cDir);
4338
                    if ($c) {
4339
                        $cidReq = $c;
4340
                    }
4341
                }
4342
            }
4343
            $_course = api_get_course_info($cidReq);
4344
            if (isset($_course['language']) && !empty($_course['language'])) {
4345
                $return = $_course['language'];
4346
                $showCourseInUserLanguage = api_get_course_setting('show_course_in_user_language');
4347
                if ($showCourseInUserLanguage == 1) {
4348
                    $userInfo = api_get_user_info();
4349
                    if (isset($userInfo['language'])) {
4350
                        $return = $userInfo['language'];
4351
                    }
4352
                }
4353
            }
4354
            break;
4355
        default:
4356
            $return = false;
4357
        break;
4358
    }
4359
4360
    return $return;
4361
}
4362
4363
/**
4364
 * Get the language information by its id
4365
 * @param int $languageId
4366
 * @return array
4367
 */
4368
function api_get_language_info($languageId)
4369
{
4370
    $language = Database::getManager()
4371
        ->find('ChamiloCoreBundle:Language', intval($languageId));
4372
4373
    if (!$language) {
4374
        return [];
4375
    }
4376
4377
    return [
4378
        'id' => $language->getId(),
4379
        'original_name' => $language->getOriginalName(),
4380
        'english_name' => $language->getEnglishName(),
4381
        'isocode' => $language->getIsocode(),
4382
        'dokeos_folder' => $language->getDokeosFolder(),
4383
        'available' => $language->getAvailable(),
4384
        'parent_id' => $language->getParent() ? $language->getParent()->getId() : null
4385
    ];
4386
}
4387
4388
/**
4389
 * Returns the name of the visual (CSS) theme to be applied on the current page.
4390
 * The returned name depends on the platform, course or user -wide settings.
4391
 * @return string The visual theme's name, it is the name of a folder inside web/css/themes
4392
 */
4393
function api_get_visual_theme()
4394
{
4395
    static $visual_theme;
4396
    if (!isset($visual_theme)) {
4397
4398
        $platform_theme = api_get_setting('stylesheets');
4399
4400
        // Platform's theme.
4401
        $visual_theme = $platform_theme;
4402
4403
        if (api_get_setting('profile.user_selected_theme') == 'true') {
4404
            $user_info = api_get_user_info();
4405
            if (isset($user_info['theme'])) {
4406
                $user_theme = $user_info['theme'];
4407
4408
                if (!empty($user_theme)) {
4409
                    $visual_theme = $user_theme;
4410
                    // User's theme.
4411
                }
4412
            }
4413
        }
4414
4415
        $course_id = api_get_course_id();
4416
        if (!empty($course_id) && $course_id != -1) {
4417
            if (api_get_setting('course.allow_course_theme') == 'true') {
4418
                $course_theme = api_get_course_setting('course_theme');
4419
4420
                if (!empty($course_theme) && $course_theme != -1) {
4421
                    if (!empty($course_theme)) {
4422
                        // Course's theme.
4423
                        $visual_theme = $course_theme;
4424
                    }
4425
                }
4426
4427
                $allow_lp_theme = api_get_course_setting('allow_learning_path_theme');
4428
                if ($allow_lp_theme == 1) {
4429
                    global $lp_theme_css, $lp_theme_config;
4430
                    // These variables come from the file lp_controller.php.
4431
                    if (!$lp_theme_config) {
4432
                        if (!empty($lp_theme_css)) {
4433
                            // LP's theme.
4434
                            $visual_theme = $lp_theme_css;
4435
                        }
4436
                    }
4437
                }
4438
            }
4439
        }
4440
4441
        if (empty($visual_theme)) {
4442
            $visual_theme = 'chamilo';
4443
        }
4444
4445
        global $lp_theme_log;
4446
        if ($lp_theme_log) {
4447
            $visual_theme = $platform_theme;
4448
        }
4449
    }
4450
4451
    return $visual_theme;
4452
}
4453
4454
/**
4455
 * Returns a list of CSS themes currently available in the CSS folder
4456
 * The folder must have a default.css file
4457
 * @param bool $getOnlyThemeFromVirtualInstance Used by the vchamilo plugin
4458
 * @return array        List of themes directories from the css folder
4459
 * Note: Directory names (names of themes) in the file system should contain ASCII-characters only.
4460
 */
4461
function api_get_themes($getOnlyThemeFromVirtualInstance = false)
4462
{
4463
    // This configuration value is set by the vchamilo plugin
4464
    $virtualTheme = api_get_configuration_value('virtual_css_theme_folder');
4465
4466
    $readCssFolder = function ($dir) use ($virtualTheme) {
4467
        $finder = new Finder();
4468
        $themes = $finder->directories()->in($dir)->depth(0)->sortByName();
4469
        $list = [];
4470
        /** @var Symfony\Component\Finder\SplFileInfo $theme */
4471
        foreach ($themes as $theme) {
4472
            $folder = $theme->getFilename();
4473
            // A theme folder is consider if there's a default.css file
4474
            if (!file_exists($theme->getPathname().'/default.css')) {
4475
                continue;
4476
            }
4477
            $name = ucwords(str_replace('_', ' ', $folder));
4478
            if ($folder == $virtualTheme) {
4479
                continue;
4480
            }
4481
            $list[$folder] = $name;
4482
        }
4483
        return $list;
4484
    };
4485
4486
    $dir = api_get_path(SYS_CSS_PATH).'themes/';
4487
    $list = $readCssFolder($dir);
4488
4489
    if (!empty($virtualTheme)) {
4490
        $newList = $readCssFolder($dir.'/'.$virtualTheme);
4491
        if ($getOnlyThemeFromVirtualInstance) {
4492
            return $newList;
4493
        }
4494
        $list = $list + $newList;
4495
        asort($list);
4496
    }
4497
4498
    return $list;
4499
}
4500
4501
/**
4502
 * Find the largest sort value in a given user_course_category
4503
 * This function is used when we are moving a course to a different category
4504
 * and also when a user subscribes to courses (the new course is added at the end of the main category
4505
 * @author Patrick Cool <[email protected]>, Ghent University
4506
 * @param int $user_course_category the id of the user_course_category
4507
 * @param integer $user_id
4508
 * @return int the value of the highest sort of the user_course_category
4509
 */
4510 View Code Duplication
function api_max_sort_value($user_course_category, $user_id)
4511
{
4512
    $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4513
    $sql = "SELECT max(sort) as max_sort FROM $tbl_course_user
4514
            WHERE
4515
                user_id='".intval($user_id)."' AND
4516
                relation_type<>".COURSE_RELATION_TYPE_RRHH." AND
4517
                user_course_cat='".intval($user_course_category)."'";
4518
    $result_max = Database::query($sql);
4519
    if (Database::num_rows($result_max) == 1) {
4520
        $row_max = Database::fetch_array($result_max);
4521
        return $row_max['max_sort'];
4522
    }
4523
    return 0;
4524
}
4525
4526
/**
4527
 * Transforms a number of seconds in hh:mm:ss format
4528
 * @author Julian Prud'homme
4529
 * @param integer the number of seconds
4530
 * @return string the formated time
4531
 */
4532
function api_time_to_hms($seconds)
4533
{
4534
    // $seconds = -1 means that we have wrong data in the db.
4535
    if ($seconds == -1) {
4536
        return
4537
            get_lang('Unknown').
4538
            Display::return_icon(
4539
                'info2.gif',
4540
                get_lang('WrongDatasForTimeSpentOnThePlatform'),
4541
                array('align' => 'absmiddle', 'hspace' => '3px')
4542
            );
4543
    }
4544
4545
    // How many hours ?
4546
    $hours = floor($seconds / 3600);
4547
4548
    // How many minutes ?
4549
    $min = floor(($seconds - ($hours * 3600)) / 60);
4550
4551
    // How many seconds
4552
    $sec = floor($seconds - ($hours * 3600) - ($min * 60));
4553
4554
    if ($sec < 10) {
4555
        $sec = "0$sec";
4556
    }
4557
4558
    if ($min < 10) {
4559
        $min = "0$min";
4560
    }
4561
4562
    return "$hours:$min:$sec";
4563
}
4564
4565
/* FILE SYSTEM RELATED FUNCTIONS */
4566
4567
/**
4568
 * Returns the permissions to be assigned to every newly created directory by the web-server.
4569
 * The return value is based on the platform administrator's setting
4570
 * "Administration > Configuration settings > Security > Permissions for new directories".
4571
 * @return int  Returns the permissions in the format "Owner-Group-Others, Read-Write-Execute", as an integer value.
4572
 */
4573 View Code Duplication
function api_get_permissions_for_new_directories()
4574
{
4575
    static $permissions;
4576
    if (!isset($permissions)) {
4577
        $permissions = trim(api_get_setting('permissions_for_new_directories'));
4578
        // The default value 0777 is according to that in the platform administration panel after fresh system installation.
4579
        $permissions = octdec(!empty($permissions) ? $permissions : '0777');
4580
    }
4581
    return $permissions;
4582
}
4583
4584
/**
4585
 * Returns the permissions to be assigned to every newly created directory by the web-server.
4586
 * The return value is based on the platform administrator's setting
4587
 * "Administration > Configuration settings > Security > Permissions for new files".
4588
 * @return int Returns the permissions in the format
4589
 * "Owner-Group-Others, Read-Write-Execute", as an integer value.
4590
 */
4591 View Code Duplication
function api_get_permissions_for_new_files()
4592
{
4593
    static $permissions;
4594
    if (!isset($permissions)) {
4595
        $permissions = trim(api_get_setting('permissions_for_new_files'));
4596
        // The default value 0666 is according to that in the platform
4597
        // administration panel after fresh system installation.
4598
        $permissions = octdec(!empty($permissions) ? $permissions : '0666');
4599
    }
4600
    return $permissions;
4601
}
4602
4603
/**
4604
 * Deletes a file, or a folder and its contents
4605
 *
4606
 * @author      Aidan Lister <[email protected]>
4607
 * @version     1.0.3
4608
 * @param       string   $dirname    Directory to delete
4609
 * @param       bool     Deletes only the content or not
4610
 * @param       bool     $strict if one folder/file fails stop the loop
4611
 * @return      bool     Returns TRUE on success, FALSE on failure
4612
 * @link http://aidanlister.com/2004/04/recursively-deleting-a-folder-in-php/
4613
 * @author      Yannick Warnier, adaptation for the Chamilo LMS, April, 2008
4614
 * @author      Ivan Tcholakov, a sanity check about Directory class creation has been added, September, 2009
4615
 */
4616
function rmdirr($dirname, $delete_only_content_in_folder = false, $strict = false) {
4617
    $res = true;
4618
    // A sanity check.
4619
    if (!file_exists($dirname)) {
4620
        return false;
4621
    }
4622
    $php_errormsg = '';
4623
    // Simple delete for a file.
4624
    if (is_file($dirname) || is_link($dirname)) {
4625
        $res = unlink($dirname);
4626 View Code Duplication
        if ($res === false) {
4627
            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);
4628
        }
4629
        return $res;
4630
    }
4631
4632
    // Loop through the folder.
4633
    $dir = dir($dirname);
4634
    // A sanity check.
4635
    $is_object_dir = is_object($dir);
4636 View Code Duplication
    if ($is_object_dir) {
4637
        while (false !== $entry = $dir->read()) {
4638
            // Skip pointers.
4639
            if ($entry == '.' || $entry == '..') {
4640
                continue;
4641
            }
4642
4643
            // Recurse.
4644
            if ($strict) {
4645
                $result = rmdirr("$dirname/$entry");
4646
                if ($result == false) {
4647
                    $res = false;
4648
                    break;
4649
                }
4650
            } else {
4651
                rmdirr("$dirname/$entry");
4652
            }
4653
        }
4654
    }
4655
4656
    // Clean up.
4657
    if ($is_object_dir) {
4658
        $dir->close();
4659
    }
4660
4661
    if ($delete_only_content_in_folder == false) {
4662
        $res = rmdir($dirname);
4663 View Code Duplication
        if ($res === false) {
4664
            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);
4665
        }
4666
    }
4667
    return $res;
4668
}
4669
4670
// TODO: This function is to be simplified. File access modes to be implemented.
4671
/**
4672
 * function adapted from a php.net comment
4673
 * copy recursively a folder
4674
 * @param the source folder
4675
 * @param the dest folder
4676
 * @param an array of excluded file_name (without extension)
4677
 * @param copied_files the returned array of copied files
4678
 * @param string $source
4679
 * @param string $dest
4680
 */
4681
function copyr($source, $dest, $exclude = array(), $copied_files = array()) {
4682
    if (empty($dest)) { return false; }
4683
    // Simple copy for a file
4684
    if (is_file($source)) {
4685
        $path_info = pathinfo($source);
4686
        if (!in_array($path_info['filename'], $exclude)) {
4687
            copy($source, $dest);
4688
        }
4689
        return true;
4690
    } elseif (!is_dir($source)) {
4691
        //then source is not a dir nor a file, return
4692
        return false;
4693
    }
4694
4695
    // Make destination directory.
4696
    if (!is_dir($dest)) {
4697
        mkdir($dest, api_get_permissions_for_new_directories());
4698
    }
4699
4700
    // Loop through the folder.
4701
    $dir = dir($source);
4702
    while (false !== $entry = $dir->read()) {
4703
        // Skip pointers
4704
        if ($entry == '.' || $entry == '..') {
4705
            continue;
4706
        }
4707
4708
        // Deep copy directories.
4709
        if ($dest !== "$source/$entry") {
4710
            $files = copyr("$source/$entry", "$dest/$entry", $exclude, $copied_files);
4711
        }
4712
    }
4713
    // Clean up.
4714
    $dir->close();
4715
    return true;
4716
}
4717
4718
// TODO: Using DIRECTORY_SEPARATOR is not recommended, this is an obsolete approach. Documentation header to be added here.
4719
/**
4720
 * @param string $pathname
4721
 * @param string $base_path_document
4722
 * @param integer $session_id
4723
 */
4724
function copy_folder_course_session(
4725
    $pathname,
4726
    $base_path_document,
4727
    $session_id,
4728
    $course_info,
4729
    $document,
4730
    $source_course_id
4731
) {
4732
    $table = Database::get_course_table(TABLE_DOCUMENT);
4733
    $session_id = intval($session_id);
4734
    $source_course_id = intval($source_course_id);
4735
4736
    // Check whether directory already exists.
4737
    if (is_dir($pathname) || empty($pathname)) {
4738
        return true;
4739
    }
4740
4741
    // Ensure that a file with the same name does not already exist.
4742
    if (is_file($pathname)) {
4743
        trigger_error('copy_folder_course_session(): File exists', E_USER_WARNING);
4744
        return false;
4745
    }
4746
4747
    $course_id = $course_info['real_id'];
4748
4749
    $folders = explode(DIRECTORY_SEPARATOR, str_replace($base_path_document.DIRECTORY_SEPARATOR, '', $pathname));
4750
4751
    $new_pathname = $base_path_document;
4752
    $path = '';
4753
4754
    foreach ($folders as $folder) {
4755
        $new_pathname .= DIRECTORY_SEPARATOR.$folder;
4756
        $path .= DIRECTORY_SEPARATOR.$folder;
4757
4758
        if (!file_exists($new_pathname)) {
4759
            $path = Database::escape_string($path);
4760
4761
            $sql = "SELECT * FROM $table
4762
                    WHERE
4763
                        c_id = $source_course_id AND
4764
                        path = '$path' AND
4765
                        filetype = 'folder' AND
4766
                        session_id = '$session_id'";
4767
            $rs1 = Database::query($sql);
4768
            $num_rows = Database::num_rows($rs1);
4769
4770
            if ($num_rows == 0) {
4771
                mkdir($new_pathname, api_get_permissions_for_new_directories());
4772
4773
                // Insert new folder with destination session_id.
4774
                $params = [
4775
                    'c_id' => $course_id,
4776
                    'path' => $path,
4777
                    'comment' => $document->comment,
4778
                    'title' => basename($new_pathname),
4779
                    'filetype' => 'folder',
4780
                    'size' => '0',
4781
                    'session_id' => $session_id
4782
                ];
4783
                $document_id = Database::insert($table, $params);
4784 View Code Duplication
                if ($document_id) {
4785
4786
                    $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
4787
                    Database::query($sql);
4788
4789
                    api_item_property_update(
4790
                        $course_info,
4791
                        TOOL_DOCUMENT,
4792
                        $document_id,
4793
                        'FolderCreated',
4794
                        api_get_user_id(),
4795
                        0,
4796
                        0,
4797
                        null,
4798
                        null,
4799
                        $session_id
4800
                    );
4801
                }
4802
            }
4803
        }
4804
4805
    } // en foreach
4806
}
4807
4808
// TODO: chmodr() is a better name. Some corrections are needed. Documentation header to be added here.
4809
/**
4810
 * @param string $path
4811
 */
4812
function api_chmod_R($path, $filemode) {
4813
    if (!is_dir($path)) {
4814
        return chmod($path, $filemode);
4815
    }
4816
4817
    $handler = opendir($path);
4818
    while ($file = readdir($handler)) {
4819
        if ($file != '.' && $file != '..') {
4820
            $fullpath = "$path/$file";
4821
            if (!is_dir($fullpath)) {
4822
                if (!chmod($fullpath, $filemode)) {
4823
                    return false;
4824
                }
4825
            } else {
4826
                if (!api_chmod_R($fullpath, $filemode)) {
4827
                    return false;
4828
                }
4829
            }
4830
        }
4831
    }
4832
4833
    closedir($handler);
4834
    return chmod($path, $filemode);
4835
}
4836
4837
4838
// TODO: Where the following function has been copy/pased from? There is no information about author and license. Style, coding conventions...
4839
/**
4840
 * Parse info file format. (e.g: file.info)
4841
 *
4842
 * Files should use an ini-like format to specify values.
4843
 * White-space generally doesn't matter, except inside values.
4844
 * e.g.
4845
 *
4846
 * @verbatim
4847
 *   key = value
4848
 *   key = "value"
4849
 *   key = 'value'
4850
 *   key = "multi-line
4851
 *
4852
 *   value"
4853
 *   key = 'multi-line
4854
 *
4855
 *   value'
4856
 *   key
4857
 *   =
4858
 *   'value'
4859
 * @endverbatim
4860
 *
4861
 * Arrays are created using a GET-like syntax:
4862
 *
4863
 * @verbatim
4864
 *   key[] = "numeric array"
4865
 *   key[index] = "associative array"
4866
 *   key[index][] = "nested numeric array"
4867
 *   key[index][index] = "nested associative array"
4868
 * @endverbatim
4869
 *
4870
 * PHP constants are substituted in, but only when used as the entire value:
4871
 *
4872
 * Comments should start with a semi-colon at the beginning of a line.
4873
 *
4874
 * This function is NOT for placing arbitrary module-specific settings. Use
4875
 * variable_get() and variable_set() for that.
4876
 *
4877
 * Information stored in the module.info file:
4878
 * - name: The real name of the module for display purposes.
4879
 * - description: A brief description of the module.
4880
 * - dependencies: An array of shortnames of other modules this module depends on.
4881
 * - package: The name of the package of modules this module belongs to.
4882
 *
4883
 * Example of .info file:
4884
 * <code>
4885
 * @verbatim
4886
 *   name = Forum
4887
 *   description = Enables threaded discussions about general topics.
4888
 *   dependencies[] = taxonomy
4889
 *   dependencies[] = comment
4890
 *   package = Core - optional
4891
 *   version = VERSION
4892
 * @endverbatim
4893
 * </code>
4894
 * @param string $filename
4895
 *   The file we are parsing. Accepts file with relative or absolute path.
4896
 * @return
4897
 *   The info array.
4898
 */
4899
function api_parse_info_file($filename) {
4900
    $info = array();
4901
4902
    if (!file_exists($filename)) {
4903
        return $info;
4904
    }
4905
4906
    $data = file_get_contents($filename);
4907
    if (preg_match_all('
4908
        @^\s*                           # Start at the beginning of a line, ignoring leading whitespace
4909
        ((?:
4910
          [^=;\[\]]|                    # Key names cannot contain equal signs, semi-colons or square brackets,
4911
          \[[^\[\]]*\]                  # unless they are balanced and not nested
4912
        )+?)
4913
        \s*=\s*                         # Key/value pairs are separated by equal signs (ignoring white-space)
4914
        (?:
4915
          ("(?:[^"]|(?<=\\\\)")*")|     # Double-quoted string, which may contain slash-escaped quotes/slashes
4916
          (\'(?:[^\']|(?<=\\\\)\')*\')| # Single-quoted string, which may contain slash-escaped quotes/slashes
4917
          ([^\r\n]*?)                   # Non-quoted string
4918
        )\s*$                           # Stop at the next end of a line, ignoring trailing whitespace
4919
        @msx', $data, $matches, PREG_SET_ORDER)) {
4920
        $key = $value1 = $value2 = $value3 = '';
4921
        foreach ($matches as $match) {
4922
            // Fetch the key and value string.
4923
            $i = 0;
4924
            foreach (array('key', 'value1', 'value2', 'value3') as $var) {
4925
                $$var = isset($match[++$i]) ? $match[$i] : '';
4926
            }
4927
            $value = stripslashes(substr($value1, 1, -1)).stripslashes(substr($value2, 1, -1)).$value3;
4928
4929
            // Parse array syntax.
4930
            $keys = preg_split('/\]?\[/', rtrim($key, ']'));
4931
            $last = array_pop($keys);
4932
            $parent = &$info;
4933
4934
            // Create nested arrays.
4935
            foreach ($keys as $key) {
4936
                if ($key == '') {
4937
                    $key = count($parent);
4938
                }
4939
                if (!isset($parent[$key]) || !is_array($parent[$key])) {
4940
                    $parent[$key] = array();
4941
                }
4942
                $parent = &$parent[$key];
4943
            }
4944
4945
            // Handle PHP constants.
4946
            if (defined($value)) {
4947
                $value = constant($value);
4948
            }
4949
4950
            // Insert actual value.
4951
            if ($last == '') {
4952
                $last = count($parent);
4953
            }
4954
            $parent[$last] = $value;
4955
        }
4956
    }
4957
    return $info;
4958
}
4959
4960
/**
4961
 * Gets Chamilo version from the configuration files
4962
 * @return string   A string of type "1.8.4", or an empty string if the version could not be found
4963
 */
4964
function api_get_version()
4965
{
4966
    return (string) api_get_configuration_value('system_version');
4967
}
4968
4969
/**
4970
 * Gets the software name (the name/brand of the Chamilo-based customized system)
4971
 * @return string
4972
 */
4973
function api_get_software_name()
4974
{
4975
    $name = api_get_configuration_value('software_name');
4976
    if (!empty($name)) {
4977
        return $name;
4978
    } else {
4979
        return 'Chamilo';
4980
    }
4981
}
4982
4983
/**
4984
 * Checks whether status given in parameter exists in the platform
4985
 * @param mixed the status (can be either int either string)
4986
 * @return boolean if the status exists, else returns false
4987
 */
4988
function api_status_exists($status_asked) {
4989
    global $_status_list;
4990
    return in_array($status_asked, $_status_list) ? true : isset($_status_list[$status_asked]);
4991
}
4992
4993
/**
4994
 * Checks whether status given in parameter exists in the platform. The function
4995
 * returns the status ID or false if it does not exist, but given the fact there
4996
 * is no "0" status, the return value can be checked against
4997
 * if(api_status_key()) to know if it exists.
4998
 * @param   mixed   The status (can be either int or string)
4999
 * @return  mixed   Status ID if exists, false otherwise
5000
 */
5001
function api_status_key($status) {
5002
    global $_status_list;
5003
    return isset($_status_list[$status]) ? $status : array_search($status, $_status_list);
5004
}
5005
5006
/**
5007
 * Gets the status langvars list
5008
 * @return string[] the list of status with their translations
5009
 */
5010
function api_get_status_langvars() {
5011
    return array(
5012
        COURSEMANAGER   => get_lang('Teacher', ''),
5013
        SESSIONADMIN    => get_lang('SessionsAdmin', ''),
5014
        DRH             => get_lang('Drh', ''),
5015
        STUDENT         => get_lang('Student', ''),
5016
        ANONYMOUS       => get_lang('Anonymous', ''),
5017
        STUDENT_BOSS    => get_lang('RoleStudentBoss', ''),
5018
        INVITEE         => get_lang('Invited'),
5019
    );
5020
}
5021
5022
/**
5023
* The function that retrieves all the possible settings for a certain config setting
5024
* @author Patrick Cool <[email protected]>, Ghent University
5025
*/
5026 View Code Duplication
function api_get_settings_options($var)
5027
{
5028
    $table_settings_options = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
5029
    $var = Database::escape_string($var);
5030
    $sql = "SELECT * FROM $table_settings_options
5031
            WHERE variable = '$var'
5032
            ORDER BY id";
5033
    $result = Database::query($sql);
5034
    $settings_options_array = array();
5035
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5036
        $settings_options_array[] = $row;
5037
    }
5038
    return $settings_options_array;
5039
}
5040
5041
/**
5042
 * @param array $params
5043
 */
5044
function api_set_setting_option($params)
5045
{
5046
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
5047 View Code Duplication
    if (empty($params['id'])) {
5048
        Database::insert($table, $params);
5049
    } else {
5050
        Database::update($table, $params, array('id = ? '=> $params['id']));
5051
    }
5052
}
5053
5054
/**
5055
 * @param array $params
5056
 */
5057
function api_set_setting_simple($params)
5058
{
5059
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5060
    $url_id = api_get_current_access_url_id();
5061
5062 View Code Duplication
    if (empty($params['id'])) {
5063
        $params['access_url'] = $url_id;
5064
        Database::insert($table, $params);
5065
    } else {
5066
        Database::update($table, $params, array('id = ? '=> array($params['id'])));
5067
    }
5068
}
5069
5070
/**
5071
 * @param int $id
5072
 */
5073
function api_delete_setting_option($id)
5074
{
5075
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
5076
    if (!empty($id)) {
5077
        Database::delete($table, array('id = ? '=> $id));
5078
    }
5079
}
5080
5081
/**
5082
 * Sets a platform configuration setting to a given value
5083
 * @param string    The variable we want to update
5084
 * @param string    The value we want to record
5085
 * @param string    The sub-variable if any (in most cases, this will remain null)
5086
 * @param string    The category if any (in most cases, this will remain null)
5087
 * @param int       The access_url for which this parameter is valid
5088
 * @param string $cat
5089
 * @return bool|null
5090
 */
5091
function api_set_setting($var, $value, $subvar = null, $cat = null, $access_url = 1)
5092
{
5093
    if (empty($var)) {
5094
        return false;
5095
    }
5096
    $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5097
    $var = Database::escape_string($var);
5098
    $value = Database::escape_string($value);
5099
    $access_url = (int) $access_url;
5100
    if (empty($access_url)) { $access_url = 1; }
5101
    $select = "SELECT id FROM $t_settings WHERE variable = '$var' ";
5102
    if (!empty($subvar)) {
5103
        $subvar = Database::escape_string($subvar);
5104
        $select .= " AND subkey = '$subvar'";
5105
    }
5106
    if (!empty($cat)) {
5107
        $cat = Database::escape_string($cat);
5108
        $select .= " AND category = '$cat'";
5109
    }
5110
    if ($access_url > 1) {
5111
        $select .= " AND access_url = $access_url";
5112
    } else {
5113
        $select .= " AND access_url = 1 ";
5114
    }
5115
    $res = Database::query($select);
5116
    if (Database::num_rows($res) > 0) {
5117
        // Found item for this access_url.
5118
        $row = Database::fetch_array($res);
5119
        $sql = "UPDATE $t_settings SET selected_value = '$value'
5120
                WHERE id = ".$row['id'];
5121
        Database::query($sql);
5122
    } else {
5123
        // Item not found for this access_url, we have to check if it exist with access_url = 1
5124
        $select = "SELECT * FROM $t_settings
5125
                   WHERE variable = '$var' AND access_url = 1 ";
5126
        // Just in case
5127
        if ($access_url == 1) {
5128
            if (!empty($subvar)) {
5129
                $select .= " AND subkey = '$subvar'";
5130
            }
5131
            if (!empty($cat)) {
5132
                $select .= " AND category = '$cat'";
5133
            }
5134
            $res = Database::query($select);
5135
            if (Database::num_rows($res) > 0) {
5136
                // We have a setting for access_url 1, but none for the current one, so create one.
5137
                $row = Database::fetch_array($res);
5138
                $insert = "INSERT INTO $t_settings (variable, subkey, type,category, selected_value, title, comment, scope, subkeytext, access_url)
5139
                        VALUES
5140
                        ('".$row['variable']."',".(!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL").",".
5141
                        "'".$row['type']."','".$row['category']."',".
5142
                        "'$value','".$row['title']."',".
5143
                        "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".(!empty($row['scope']) ? "'".$row['scope']."'" : "NULL").",".
5144
                        "".(!empty($row['subkeytext']) ? "'".$row['subkeytext']."'" : "NULL").",$access_url)";
5145
                Database::query($insert);
5146
            } 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...
5147
                // Such a setting does not exist.
5148
                //error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all', 0);
5149
            }
5150
        } else {
5151
            // Other access url.
5152
            if (!empty($subvar)) {
5153
                $select .= " AND subkey = '$subvar'";
5154
            }
5155
            if (!empty($cat)) {
5156
                $select .= " AND category = '$cat'";
5157
            }
5158
            $res = Database::query($select);
5159
5160
            if (Database::num_rows($res) > 0) {
5161
                // We have a setting for access_url 1, but none for the current one, so create one.
5162
                $row = Database::fetch_array($res);
5163
                if ($row['access_url_changeable'] == 1) {
5164
                    $insert = "INSERT INTO $t_settings (variable,subkey, type,category, selected_value,title, comment,scope, subkeytext,access_url, access_url_changeable) VALUES
5165
                            ('".$row['variable']."',".
5166
                            (!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL").",".
5167
                            "'".$row['type']."','".$row['category']."',".
5168
                            "'$value','".$row['title']."',".
5169
                            "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".
5170
                            (!empty($row['scope']) ? "'".$row['scope']."'" : "NULL").",".
5171
                            "".(!empty($row['subkeytext']) ? "'".$row['subkeytext']."'" : "NULL").",$access_url,".$row['access_url_changeable'].")";
5172
                    Database::query($insert);
5173
                }
5174
            } 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...
5175
                //error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all. The access_url is: '.$access_url.' ',0);
5176
            }
5177
        }
5178
    }
5179
}
5180
5181
/**
5182
 * Sets a whole category of settings to one specific value
5183
 * @param string    Category
5184
 * @param string    Value
5185
 * @param int       Access URL. Optional. Defaults to 1
5186
 * @param array     Optional array of filters on field type
5187
 * @param string $category
5188
 * @param string $value
5189
 * @return bool
5190
 */
5191
function api_set_settings_category($category, $value = null, $access_url = 1, $fieldtype = array())
5192
{
5193
    if (empty($category)) {
5194
        return false;
5195
    }
5196
    $category = Database::escape_string($category);
5197
    $t_s = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5198
    $access_url = (int) $access_url;
5199
    if (empty($access_url)) { $access_url = 1; }
5200
    if (isset($value)) {
5201
        $value = Database::escape_string($value);
5202
        $sql = "UPDATE $t_s SET selected_value = '$value'
5203
                WHERE category = '$category' AND access_url = $access_url";
5204 View Code Duplication
        if (is_array($fieldtype) && count($fieldtype) > 0) {
5205
            $sql .= " AND ( ";
5206
            $i = 0;
5207
            foreach ($fieldtype as $type) {
5208
                if ($i > 0) {
5209
                    $sql .= ' OR ';
5210
                }
5211
                $type = Database::escape_string($type);
5212
                $sql .= " type='".$type."' ";
5213
                $i++;
5214
            }
5215
            $sql .= ")";
5216
        }
5217
        $res = Database::query($sql);
5218
        return $res !== false;
5219
    } else {
5220
        $sql = "UPDATE $t_s SET selected_value = NULL
5221
                WHERE category = '$category' AND access_url = $access_url";
5222 View Code Duplication
        if (is_array($fieldtype) && count($fieldtype) > 0) {
5223
            $sql .= " AND ( ";
5224
            $i = 0;
5225
            foreach ($fieldtype as $type) {
5226
                if ($i > 0) {
5227
                    $sql .= ' OR ';
5228
                }
5229
                $type = Database::escape_string($type);
5230
                $sql .= " type='".$type."' ";
5231
                $i++;
5232
            }
5233
            $sql .= ")";
5234
        }
5235
        $res = Database::query($sql);
5236
        return $res !== false;
5237
    }
5238
}
5239
5240
/**
5241
 * Gets all available access urls in an array (as in the database)
5242
 * @return array    An array of database records
5243
 */
5244
function api_get_access_urls($from = 0, $to = 1000000, $order = 'url', $direction = 'ASC')
5245
{
5246
    $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5247
    $from = (int) $from;
5248
    $to = (int) $to;
5249
    $order = Database::escape_string($order, null, false);
5250
    $direction = Database::escape_string($direction, null, false);
5251
    $sql = "SELECT id, url, description, active, created_by, tms
5252
            FROM $table
5253
            ORDER BY $order $direction
5254
            LIMIT $to OFFSET $from";
5255
    $res = Database::query($sql);
5256
    return Database::store_result($res);
5257
}
5258
5259
/**
5260
 * Gets the access url info in an array
5261
 * @param int $id Id of the access url
5262
 * @param bool $returnDefault Set to false if you want the real URL if URL 1 is still 'http://localhost/'
5263
 * @return array All the info (url, description, active, created_by, tms)
5264
 * from the access_url table
5265
 * @author Julio Montoya
5266
 */
5267
function api_get_access_url($id, $returnDefault = true)
5268
{
5269
    static $staticResult;
5270
    $id = intval($id);
5271
5272
    if (isset($staticResult[$id])) {
5273
        $result = $staticResult[$id];
5274
    } else {
5275
        // Calling the Database:: library dont work this is handmade.
5276
        $table_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5277
        $sql = "SELECT url, description, active, created_by, tms
5278
                FROM $table_access_url WHERE id = '$id' ";
5279
        $res = Database::query($sql);
5280
        $result = @Database::fetch_array($res);
5281
        $staticResult[$id] = $result;
5282
    }
5283
5284
    // If the result url is 'http://localhost/' (the default) and the root_web
5285
    // (=current url) is different, and the $id is = 1 (which might mean
5286
    // api_get_current_access_url_id() returned 1 by default), then return the
5287
    // root_web setting instead of the current URL
5288
    // This is provided as an option to avoid breaking the storage of URL-specific
5289
    // homepages in home/localhost/
5290
    if ($id === 1 && $returnDefault === false) {
5291
        $currentUrl = api_get_current_access_url_id();
5292
        // only do this if we are on the main URL (=1), otherwise we could get
5293
        // information on another URL instead of the one asked as parameter
5294
        if ($currentUrl === 1) {
5295
            $rootWeb = api_get_path(WEB_PATH);
5296
            $default = 'http://localhost/';
5297
            if ($result['url'] === $default && $rootWeb != $default) {
5298
                $result['url'] = $rootWeb;
5299
            }
5300
        }
5301
    }
5302
5303
    return $result;
5304
}
5305
5306
/**
5307
 * Gets all the current settings for a specific access url
5308
 * @param string    The category, if any, that we want to get
5309
 * @param string    Whether we want a simple list (display a category) or
5310
 * a grouped list (group by variable as in settings.php default). Values: 'list' or 'group'
5311
 * @param int       Access URL's ID. Optional. Uses 1 by default, which is the unique URL
5312
 * @return array    Array of database results for the current settings of the current access URL
5313
 */
5314
function &api_get_settings($cat = null, $ordering = 'list', $access_url = 1, $url_changeable = 0)
5315
{
5316
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5317
    $access_url = (int) $access_url;
5318
    $where_condition = '';
5319
    if ($url_changeable == 1) {
5320
        $where_condition = " AND access_url_changeable= '1' ";
5321
    }
5322
    if (empty($access_url) || $access_url == -1) {
5323
        $access_url = 1;
5324
    }
5325
    $sql = "SELECT * FROM $table
5326
            WHERE access_url = $access_url  $where_condition ";
5327
5328
    if (!empty($cat)) {
5329
        $cat = Database::escape_string($cat);
5330
        $sql .= " AND category='$cat' ";
5331
    }
5332
    if ($ordering == 'group') {
5333
        $sql .= " ORDER BY id ASC";
5334
    } else {
5335
        $sql .= " ORDER BY 1,2 ASC";
5336
    }
5337
    $result = Database::query($sql);
5338
    if ($result === null) {
5339
        return [];
5340
    }
5341
    $result = Database::store_result($result, 'ASSOC');
5342
5343
    return $result;
5344
}
5345
5346
/**
5347
 * @param string $value The value we want to record
5348
 * @param string $variable The variable name we want to insert
5349
 * @param string $subKey The subkey for the variable we want to insert
5350
 * @param string $type The type for the variable we want to insert
5351
 * @param string $category The category for the variable we want to insert
5352
 * @param string $title The title
5353
 * @param string $comment The comment
5354
 * @param string $scope The scope
5355
 * @param string $subKeyText The subkey text
5356
 * @param int $accessUrlId The access_url for which this parameter is valid
5357
 * @param int $visibility The changeability of this setting for non-master urls
5358
 * @return int The setting ID
5359
 */
5360
function api_add_setting(
5361
    $value,
5362
    $variable,
5363
    $subKey = '',
5364
    $type = 'textfield',
5365
    $category = '',
5366
    $title = '',
5367
    $comment = '',
5368
    $scope = '',
5369
    $subKeyText = '',
5370
    $accessUrlId = 1,
5371
    $visibility = 0
5372
) {
5373
    $em = Database::getManager();
5374
    $settingRepo = $em->getRepository('ChamiloCoreBundle:SettingsCurrent');
5375
    $accessUrlId = (int) $accessUrlId ?: 1;
5376
5377
    $criteria = ['variable' => $variable, 'accessUrl' => $accessUrlId];
5378
5379
    if (!empty($subKey)) {
5380
        $criteria['subkey'] = $subKey;
5381
    }
5382
5383
    // Check if this variable doesn't exist already
5384
    /** @var SettingsCurrent $setting */
5385
    $setting = $settingRepo->findOneBy($criteria);
5386
5387
    if ($setting) {
5388
        $setting->setSelectedValue($value);
5389
5390
        $em->persist($setting);
5391
        $em->flush();
5392
5393
        return $setting->getId();
5394
    }
5395
5396
    // Item not found for this access_url, we have to check if the whole thing is missing
5397
    // (in which case we ignore the insert) or if there *is* a record but just for access_url = 1
5398
    $setting = new SettingsCurrent();
5399
    $setting
5400
        ->setVariable($variable)
5401
        ->setSelectedValue($value)
5402
        ->setType($type)
5403
        ->setCategory($category)
5404
        ->setSubkey($subKey)
5405
        ->setTitle($title)
5406
        ->setComment($comment)
5407
        ->setScope($scope)
5408
        ->setSubkeytext($subKeyText)
5409
        ->setAccessUrl($accessUrlId)
5410
        ->setAccessUrlChangeable($visibility);
5411
5412
    $em->persist($setting);
5413
    $em->flush();
5414
5415
    return $setting->getId();
5416
}
5417
5418
/**
5419
 * Checks wether a user can or can't view the contents of a course.
5420
 * @deprecated use CourseManager::is_user_subscribed_in_course
5421
 * @param   int $userid     User id or NULL to get it from $_SESSION
5422
 * @param   int $cid        Course id to check whether the user is allowed.
5423
 * @return  bool
5424
 */
5425
function api_is_course_visible_for_user($userid = null, $cid = null) {
5426
    if ($userid === null) {
5427
        $userid = api_get_user_id();
5428
    }
5429
    if (empty($userid) || strval(intval($userid)) != $userid) {
5430
        if (api_is_anonymous()) {
5431
            $userid = api_get_anonymous_id();
5432
        } else {
5433
            return false;
5434
        }
5435
    }
5436
    $cid = Database::escape_string($cid);
5437
5438
    $courseInfo = api_get_course_info($cid);
5439
    $courseId = $courseInfo['real_id'];
5440
    $is_platformAdmin = api_is_platform_admin();
5441
5442
    $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
5443
    $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
5444
5445
    $sql = "SELECT
5446
                $course_table.category_code,
5447
                $course_table.visibility,
5448
                $course_table.code,
5449
                $course_cat_table.code
5450
            FROM $course_table
5451
            LEFT JOIN $course_cat_table
5452
                ON $course_table.category_code = $course_cat_table.code
5453
            WHERE
5454
                $course_table.code = '$cid'
5455
            LIMIT 1";
5456
5457
    $result = Database::query($sql);
5458
5459
    if (Database::num_rows($result) > 0) {
5460
        $visibility = Database::fetch_array($result);
5461
        $visibility = $visibility['visibility'];
5462
    } else {
5463
        $visibility = 0;
5464
    }
5465
    // Shortcut permissions in case the visibility is "open to the world".
5466
    if ($visibility === COURSE_VISIBILITY_OPEN_WORLD) {
5467
        return true;
5468
    }
5469
5470
    $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5471
5472
    $sql = "SELECT
5473
                is_tutor, status
5474
            FROM $tbl_course_user
5475
            WHERE
5476
                user_id  = '$userid' AND
5477
                relation_type <> '".COURSE_RELATION_TYPE_RRHH."' AND
5478
                c_id = $courseId
5479
            LIMIT 1";
5480
5481
    $result = Database::query($sql);
5482
5483 View Code Duplication
    if (Database::num_rows($result) > 0) {
5484
        // This user has got a recorded state for this course.
5485
        $cuData = Database::fetch_array($result);
5486
        $is_courseMember = true;
5487
        $is_courseTutor = ($cuData['is_tutor'] == 1);
5488
        $is_courseAdmin = ($cuData['status'] == 1);
5489
    }
5490
5491
    if (!$is_courseAdmin) {
5492
        // This user has no status related to this course.
5493
        // Is it the session coach or the session admin?
5494
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
5495
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
5496
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
5497
5498
        $sql = "SELECT
5499
                    session.id_coach, session_admin_id, session.id
5500
                FROM
5501
                    $tbl_session as session
5502
                INNER JOIN $tbl_session_course
5503
                    ON session_rel_course.session_id = session.id
5504
                    AND session_rel_course.c_id = '$courseId'
5505
                LIMIT 1";
5506
5507
        $result = Database::query($sql);
5508
        $row = Database::store_result($result);
5509
5510
        if ($row[0]['id_coach'] == $userid) {
5511
            $is_courseMember = true;
5512
            $is_courseTutor = true;
5513
            $is_courseAdmin = false;
5514
            $is_courseCoach = true;
5515
            $is_sessionAdmin = false;
5516
        }
5517
        elseif ($row[0]['session_admin_id'] == $userid) {
5518
            $is_courseMember = false;
5519
            $is_courseTutor = false;
5520
            $is_courseAdmin = false;
5521
            $is_courseCoach = false;
5522
            $is_sessionAdmin = true;
5523
        } else {
5524
            // Check if the current user is the course coach.
5525
            $sql = "SELECT 1
5526
                    FROM $tbl_session_course
5527
                    WHERE session_rel_course.c_id = '$courseId'
5528
                    AND session_rel_course.id_coach = '$userid'
5529
                    LIMIT 1";
5530
5531
            $result = Database::query($sql);
5532
5533
            //if ($row = Database::fetch_array($result)) {
5534
            if (Database::num_rows($result) > 0) {
5535
                $is_courseMember = true;
5536
                $is_courseTutor = true;
5537
                $is_courseCoach = true;
5538
                $is_sessionAdmin = false;
5539
5540
                $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
5541
5542
                $sql = "SELECT status FROM $tbl_user
5543
                        WHERE user_id = $userid
5544
                        LIMIT 1";
5545
5546
                $result = Database::query($sql);
5547
5548
                if (Database::result($result, 0, 0) == 1) {
5549
                    $is_courseAdmin = true;
5550
                } else {
5551
                    $is_courseAdmin = false;
5552
                }
5553
            } else {
5554
                // Check if the user is a student is this session.
5555
                $sql = "SELECT  id
5556
                        FROM $tbl_session_course_user
5557
                        WHERE
5558
                            user_id  = '$userid' AND
5559
                            c_id = '$courseId'
5560
                        LIMIT 1";
5561
5562
                if (Database::num_rows($result) > 0) {
5563
                    // This user haa got a recorded state for this course.
5564
                    while ($row = Database::fetch_array($result)) {
5565
                        $is_courseMember = true;
5566
                        $is_courseTutor = false;
5567
                        $is_courseAdmin = false;
5568
                        $is_sessionAdmin = false;
5569
                    }
5570
                }
5571
            }
5572
        }
5573
    }
5574
5575
    switch ($visibility) {
5576
        case COURSE_VISIBILITY_OPEN_WORLD:
5577
            return true;
5578
        case COURSE_VISIBILITY_OPEN_PLATFORM:
5579
            return isset($userid);
5580
        case COURSE_VISIBILITY_REGISTERED:
5581
        case COURSE_VISIBILITY_CLOSED:
5582
            return $is_platformAdmin || $is_courseMember || $is_courseAdmin;
5583
        case COURSE_VISIBILITY_HIDDEN:
5584
            return $is_platformAdmin;
5585
    }
5586
5587
    return false;
5588
}
5589
5590
/**
5591
 * Returns whether an element (forum, message, survey ...) belongs to a session or not
5592
 * @param String the tool of the element
5593
 * @param int the element id in database
5594
 * @param int the session_id to compare with element session id
5595
 * @param string $tool
5596
 * @return boolean true if the element is in the session, false else
5597
 */
5598
function api_is_element_in_the_session($tool, $element_id, $session_id = null) {
5599
    if (is_null($session_id)) {
5600
        $session_id = api_get_session_id();
5601
    }
5602
5603
    // Get information to build query depending of the tool.
5604
    switch ($tool) {
5605
        case TOOL_SURVEY :
5606
            $table_tool = Database::get_course_table(TABLE_SURVEY);
5607
            $key_field = 'survey_id';
5608
            break;
5609
        case TOOL_ANNOUNCEMENT :
5610
            $table_tool = Database::get_course_table(TABLE_ANNOUNCEMENT);
5611
            $key_field = 'id';
5612
            break;
5613
        case TOOL_AGENDA :
5614
            $table_tool = Database::get_course_table(TABLE_AGENDA);
5615
            $key_field = 'id';
5616
            break;
5617
        case TOOL_GROUP :
5618
            $table_tool = Database::get_course_table(TABLE_GROUP);
5619
            $key_field = 'id';
5620
            break;
5621
        default:
5622
            return false;
5623
    }
5624
    $course_id = api_get_course_int_id();
5625
5626
    $sql = "SELECT session_id FROM $table_tool 
5627
            WHERE c_id = $course_id AND $key_field =  ".intval($element_id);
5628
    $rs = Database::query($sql);
5629
    if ($element_session_id = Database::result($rs, 0, 0)) {
5630
        if ($element_session_id == intval($session_id)) {
5631
            // The element belongs to the session.
5632
            return true;
5633
        }
5634
    }
5635
    return false;
5636
}
5637
5638
/**
5639
 * Replaces "forbidden" characters in a filename string.
5640
 *
5641
 * @param string $filename
5642
 * @param bool $treat_spaces_as_hyphens
5643
 *
5644
 * @return string
5645
 */
5646
function api_replace_dangerous_char($filename, $treat_spaces_as_hyphens = true)
5647
{
5648
    return URLify::filter(
5649
        $filename,
5650
        250,
5651
        '',
5652
        true,
5653
        true,
5654
        false,
5655
        false,
5656
        $treat_spaces_as_hyphens
5657
    );
5658
}
5659
5660
/**
5661
 * Fixes the $_SERVER['REQUEST_URI'] that is empty in IIS6.
5662
 * @author Ivan Tcholakov, 28-JUN-2006.
5663
 */
5664
function api_request_uri() {
5665
    if (!empty($_SERVER['REQUEST_URI'])) {
5666
        return $_SERVER['REQUEST_URI'];
5667
    }
5668
    $uri = $_SERVER['SCRIPT_NAME'];
5669
    if (!empty($_SERVER['QUERY_STRING'])) {
5670
        $uri .= '?'.$_SERVER['QUERY_STRING'];
5671
    }
5672
    $_SERVER['REQUEST_URI'] = $uri;
5673
    return $uri;
5674
}
5675
5676
5677
/** Gets the current access_url id of the Chamilo Platform
5678
 * @author Julio Montoya <[email protected]>
5679
 * @return int access_url_id of the current Chamilo Installation
5680
 */
5681 View Code Duplication
function api_get_current_access_url_id() {
5682
    $access_url_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5683
    $path = Database::escape_string(api_get_path(WEB_PATH));
5684
    $sql = "SELECT id FROM $access_url_table WHERE url = '".$path."'";
5685
    $result = Database::query($sql);
5686
    if (Database::num_rows($result) > 0) {
5687
        $access_url_id = Database::result($result, 0, 0);
5688
        return $access_url_id;
5689
    }
5690
    //if the url in WEB_PATH was not found, it can only mean that there is
5691
    // either a configuration problem or the first URL has not been defined yet
5692
    // (by default it is http://localhost/). Thus the more sensible thing we can
5693
    // do is return 1 (the main URL) as the user cannot hack this value anyway
5694
    return 1;
5695
}
5696
5697
/**
5698
 * Gets the registered urls from a given user id
5699
 * @author Julio Montoya <[email protected]>
5700
 * @return int user id
5701
 */
5702 View Code Duplication
function api_get_access_url_from_user($user_id) {
5703
    $user_id = intval($user_id);
5704
    $table_url_rel_user = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
5705
    $table_url          = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5706
    $sql = "SELECT access_url_id
5707
            FROM $table_url_rel_user url_rel_user
5708
            INNER JOIN $table_url u
5709
            ON (url_rel_user.access_url_id = u.id)
5710
            WHERE user_id = ".intval($user_id);
5711
    $result = Database::query($sql);
5712
    $list = array();
5713
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5714
        $list[] = $row['access_url_id'];
5715
    }
5716
    return $list;
5717
}
5718
5719
/**
5720
 * Gets the status of a user in a course
5721
 * @param int       $user_id
5722
 * @param int    $courseId
5723
 * @return int      user status
5724
 */
5725
function api_get_status_of_user_in_course($user_id, $courseId)
5726
{
5727
    $tbl_rel_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5728
    if (!empty($user_id) && !empty($courseId)) {
5729
        $user_id = intval($user_id);
5730
        $courseId = intval($courseId);
5731
        $sql = 'SELECT status
5732
                FROM '.$tbl_rel_course_user.'
5733
                WHERE user_id='.$user_id.' AND c_id = '.$courseId;
5734
        $result = Database::query($sql);
5735
        $row_status = Database::fetch_array($result, 'ASSOC');
5736
        return $row_status['status'];
5737
    } else {
5738
        return 0;
5739
    }
5740
}
5741
5742
/**
5743
 * Checks whether the curent user is in a group or not.
5744
 *
5745
 * @param string        The group id - optional (takes it from session if not given)
5746
 * @param string        The course code - optional (no additional check by course if course code is not given)
5747
 * @return boolean
5748
 * @author Ivan Tcholakov
5749
 */
5750
function api_is_in_group($groupIdParam = null, $courseCodeParam = null)
5751
{
5752
    if (!empty($courseCodeParam)) {
5753
        $courseCode = api_get_course_id();
5754
        if (!empty($courseCode)) {
5755
            if ($courseCodeParam != $courseCode) {
5756
                return false;
5757
            }
5758
        } else {
5759
            return false;
5760
        }
5761
    }
5762
5763
    $groupId = api_get_group_id();
5764
5765
    if (isset($groupId) && $groupId != '') {
5766
        if (!empty($groupIdParam)) {
5767
            return $groupIdParam == $groupId;
5768
        } else {
5769
            return true;
5770
        }
5771
    }
5772
5773
    return false;
5774
}
5775
5776
/**
5777
 * Checks whether a secret key is valid
5778
 * @param string $original_key_secret  - secret key from (webservice) client
5779
 * @param string $security_key - security key from Chamilo
5780
 * @return boolean - true if secret key is valid, false otherwise
5781
 */
5782
function api_is_valid_secret_key($original_key_secret, $security_key) {
5783
    return $original_key_secret == sha1($security_key);
5784
}
5785
5786
/**
5787
 * Checks whether a user is into course
5788
 * @param int $course_id - the course id
5789
 * @param int $user_id - the user id
5790
 */
5791
function api_is_user_of_course($course_id, $user_id) {
5792
    $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5793
    $sql = 'SELECT user_id FROM '.$tbl_course_rel_user.'
5794
            WHERE
5795
                c_id ="'.intval($course_id).'" AND
5796
                user_id = "'.intval($user_id).'" AND
5797
                relation_type <> '.COURSE_RELATION_TYPE_RRHH.' ';
5798
    $result = Database::query($sql);
5799
    return Database::num_rows($result) == 1;
5800
}
5801
5802
/**
5803
 * Checks whether the server's operating system is Windows (TM).
5804
 * @return boolean - true if the operating system is Windows, false otherwise
5805
 */
5806
function api_is_windows_os() {
5807
    if (function_exists('php_uname')) {
5808
        // php_uname() exists as of PHP 4.0.2, according to the documentation.
5809
        // We expect that this function will always work for Chamilo 1.8.x.
5810
        $os = php_uname();
5811
    }
5812
    // The following methods are not needed, but let them stay, just in case.
5813
    elseif (isset($_ENV['OS'])) {
5814
        // Sometimes $_ENV['OS'] may not be present (bugs?)
5815
        $os = $_ENV['OS'];
5816
    }
5817
    elseif (defined('PHP_OS')) {
5818
        // PHP_OS means on which OS PHP was compiled, this is why
5819
        // using PHP_OS is the last choice for detection.
5820
        $os = PHP_OS;
5821
    } else {
5822
        return false;
5823
    }
5824
    return strtolower(substr((string) $os, 0, 3)) == 'win';
5825
}
5826
5827
/**
5828
 * This function informs whether the sent request is XMLHttpRequest
5829
 */
5830
function api_is_xml_http_request() {
5831
    return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
5832
}
5833
5834
/**
5835
 * This wrapper function has been implemented for avoiding some known problems about the function getimagesize().
5836
 * @link http://php.net/manual/en/function.getimagesize.php
5837
 * @link http://www.dokeos.com/forum/viewtopic.php?t=12345
5838
 * @link http://www.dokeos.com/forum/viewtopic.php?t=16355
5839
 * @return integer
5840
 */
5841
function api_getimagesize($path) {
5842
    $image = new Image($path);
5843
    return $image->get_image_size();
5844
}
5845
5846
/**
5847
 * This function resizes an image, with preserving its proportions (or aspect ratio).
5848
 * @author Ivan Tcholakov, MAY-2009.
5849
 * @param int $image            System path or URL of the image
5850
 * @param int $target_width     Targeted width
5851
 * @param int $target_height    Targeted height
5852
 * @return array                Calculated new width and height
5853
 */
5854
function api_resize_image($image, $target_width, $target_height) {
5855
    $image_properties = api_getimagesize($image);
5856
    return api_calculate_image_size($image_properties['width'], $image_properties['height'], $target_width, $target_height);
5857
}
5858
5859
/**
5860
 * This function calculates new image size, with preserving image's proportions (or aspect ratio).
5861
 * @author Ivan Tcholakov, MAY-2009.
5862
 * @author The initial idea has been taken from code by Patrick Cool, MAY-2004.
5863
 * @param int $image_width      Initial width
5864
 * @param int $image_height     Initial height
5865
 * @param int $target_width     Targeted width
5866
 * @param int $target_height    Targeted height
5867
 * @return array                Calculated new width and height
5868
 */
5869
function api_calculate_image_size($image_width, $image_height, $target_width, $target_height) {
5870
    // Only maths is here.
5871
    $result = array('width' => $image_width, 'height' => $image_height);
5872
    if ($image_width <= 0 || $image_height <= 0) {
5873
        return $result;
5874
    }
5875
    $resize_factor_width = $target_width / $image_width;
5876
    $resize_factor_height = $target_height / $image_height;
5877
    $delta_width = $target_width - $image_width * $resize_factor_height;
5878
    $delta_height = $target_height - $image_height * $resize_factor_width;
5879
    if ($delta_width > $delta_height) {
5880
        $result['width'] = ceil($image_width * $resize_factor_height);
5881
        $result['height'] = ceil($image_height * $resize_factor_height);
5882
    }
5883
    elseif ($delta_width < $delta_height) {
5884
        $result['width'] = ceil($image_width * $resize_factor_width);
5885
        $result['height'] = ceil($image_height * $resize_factor_width);
5886
    }
5887
    else {
5888
        $result['width'] = ceil($target_width);
5889
        $result['height'] = ceil($target_height);
5890
    }
5891
    return $result;
5892
}
5893
5894
/**
5895
 * Returns a list of Chamilo's tools or
5896
 * checks whether a given identificator is a valid Chamilo's tool.
5897
 * @author Isaac flores paz
5898
 * @param string The tool name to filter
5899
 * @return mixed Filtered string or array
5900
 */
5901
function api_get_tools_lists($my_tool = null) {
5902
    $tools_list = array(
5903
        TOOL_DOCUMENT,
5904
        TOOL_THUMBNAIL,
5905
        TOOL_HOTPOTATOES,
5906
        TOOL_CALENDAR_EVENT,
5907
        TOOL_LINK,
5908
        TOOL_COURSE_DESCRIPTION,
5909
        TOOL_SEARCH,
5910
        TOOL_LEARNPATH,
5911
        TOOL_ANNOUNCEMENT,
5912
        TOOL_FORUM,
5913
        TOOL_THREAD,
5914
        TOOL_POST,
5915
        TOOL_DROPBOX,
5916
        TOOL_QUIZ,
5917
        TOOL_USER,
5918
        TOOL_GROUP,
5919
        TOOL_BLOGS,
5920
        TOOL_CHAT,
5921
        TOOL_STUDENTPUBLICATION,
5922
        TOOL_TRACKING,
5923
        TOOL_HOMEPAGE_LINK,
5924
        TOOL_COURSE_SETTING,
5925
        TOOL_BACKUP,
5926
        TOOL_COPY_COURSE_CONTENT,
5927
        TOOL_RECYCLE_COURSE,
5928
        TOOL_COURSE_HOMEPAGE,
5929
        TOOL_COURSE_RIGHTS_OVERVIEW,
5930
        TOOL_UPLOAD,
5931
        TOOL_COURSE_MAINTENANCE,
5932
        TOOL_SURVEY,
5933
        TOOL_WIKI,
5934
        TOOL_GLOSSARY,
5935
        TOOL_GRADEBOOK,
5936
        TOOL_NOTEBOOK,
5937
        TOOL_ATTENDANCE,
5938
        TOOL_COURSE_PROGRESS,
5939
    );
5940
    if (empty($my_tool)) {
5941
        return $tools_list;
5942
    }
5943
    return in_array($my_tool, $tools_list) ? $my_tool : '';
5944
}
5945
5946
/**
5947
 * Checks whether we already approved the last version term and condition
5948
 * @param int user id
5949
 * @return bool true if we pass false otherwise
5950
 */
5951
function api_check_term_condition($user_id)
5952
{
5953
    if (api_get_setting('allow_terms_conditions') == 'true') {
5954
        //check if exists terms and conditions
5955
        if (LegalManager::count() == 0) {
5956
5957
            return true;
5958
        }
5959
5960
        $extraFieldValue = new ExtraFieldValue('user');
5961
        $data = $extraFieldValue->get_values_by_handler_and_field_variable(
5962
            $user_id,
5963
            'legal_accept'
5964
        );
5965
5966
        if (!empty($data) && isset($data['value'])) {
5967
            $rowv = $data['value'];
5968
            $user_conditions = explode(':', $rowv);
5969
            $version = $user_conditions[0];
5970
            $lang_id = $user_conditions[1];
5971
            $real_version = LegalManager::get_last_version($lang_id);
5972
5973
            return $version >= $real_version;
5974
        }
5975
        return false;
5976
    }
5977
    return false;
5978
}
5979
5980
/**
5981
 * Gets all information of a tool into course
5982
 * @param int The tool id
5983
 * @return array
5984
 */
5985 View Code Duplication
function api_get_tool_information_by_name($name)
5986
{
5987
    $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
5988
    $course_id = api_get_course_int_id();
5989
    $sql = "SELECT * FROM $t_tool
5990
            WHERE c_id = $course_id  AND name = '".Database::escape_string($name)."' ";
5991
    $rs  = Database::query($sql);
5992
    return Database::fetch_array($rs, 'ASSOC');
5993
}
5994
5995
/**
5996
 * Function used to protect a "global" admin script.
5997
 * The function blocks access when the user has no global platform admin rights.
5998
 * Global admins are the admins that are registered in the main.admin table
5999
 * AND the users who have access to the "principal" portal.
6000
 * That means that there is a record in the main.access_url_rel_user table
6001
 * with his user id and the access_url_id=1
6002
 *
6003
 * @author Julio Montoya
6004
 * @param integer $user_id
6005
 * @return bool
6006
 */
6007
function api_is_global_platform_admin($user_id = null)
6008
{
6009
    $user_id = intval($user_id);
6010
    if (empty($user_id)) {
6011
        $user_id = api_get_user_id();
6012
    }
6013
    if (api_is_platform_admin_by_id($user_id)) {
6014
        $urlList = api_get_access_url_from_user($user_id);
6015
        // The admin is registered in the first "main" site with access_url_id = 1
6016
        if (in_array(1, $urlList)) {
6017
            return true;
6018
        } else {
6019
            return false;
6020
        }
6021
    }
6022
    return false;
6023
}
6024
6025
/**
6026
 * @param int $admin_id_to_check
6027
 * @param int  $my_user_id
6028
 * @param bool $allow_session_admin
6029
 * @return bool
6030
 */
6031
function api_global_admin_can_edit_admin(
6032
    $admin_id_to_check,
6033
    $my_user_id = null,
6034
    $allow_session_admin = false
6035
) {
6036
    if (empty($my_user_id)) {
6037
        $my_user_id = api_get_user_id();
6038
    }
6039
6040
    $iam_a_global_admin = api_is_global_platform_admin($my_user_id);
6041
    $user_is_global_admin = api_is_global_platform_admin($admin_id_to_check);
6042
6043
    if ($iam_a_global_admin) {
6044
        // Global admin can edit everything
6045
        return true;
6046
    } else {
6047
        // If i'm a simple admin
6048
        $is_platform_admin = api_is_platform_admin_by_id($my_user_id);
6049
6050
        if ($allow_session_admin) {
6051
            $is_platform_admin = api_is_platform_admin_by_id($my_user_id) || (api_get_user_status($my_user_id) == SESSIONADMIN);
6052
        }
6053
6054
        if ($is_platform_admin) {
6055
            if ($user_is_global_admin) {
6056
                return false;
6057
            } else {
6058
                return true;
6059
            }
6060
        } else {
6061
            return false;
6062
        }
6063
    }
6064
}
6065
6066
/**
6067
 * @param int $admin_id_to_check
6068
 * @param int  $my_user_id
6069
 * @param bool $allow_session_admin
6070
 * @return boolean|null
6071
 */
6072
function api_protect_super_admin($admin_id_to_check, $my_user_id = null, $allow_session_admin = false)
6073
{
6074
    if (api_global_admin_can_edit_admin($admin_id_to_check, $my_user_id, $allow_session_admin)) {
6075
        return true;
6076
    } else {
6077
        api_not_allowed();
6078
    }
6079
}
6080
6081
/**
6082
 * Function used to protect a global admin script.
6083
 * The function blocks access when the user has no global platform admin rights.
6084
 * See also the api_is_global_platform_admin() function wich defines who's a "global" admin
6085
 *
6086
 * @author Julio Montoya
6087
 */
6088
function api_protect_global_admin_script() {
6089
    if (!api_is_global_platform_admin()) {
6090
        api_not_allowed();
6091
        return false;
6092
    }
6093
    return true;
6094
}
6095
6096
/**
6097
 * Get active template
6098
 * @param string    theme type (optional: default)
6099
 * @param string    path absolute(abs) or relative(rel) (optional:rel)
6100
 * @return string   actived template path
6101
 */
6102
function api_get_template($path_type = 'rel')
6103
{
6104
    $path_types = array('rel', 'abs');
6105
    $template_path = '';
6106
    if (in_array($path_type, $path_types)) {
6107
        if ($path_type == 'rel') {
6108
            $template_path = api_get_path(SYS_TEMPLATE_PATH);
6109
        } else {
6110
            $template_path = api_get_path(WEB_TEMPLATE_PATH);
6111
        }
6112
    }
6113
    $actived_theme = 'default';
6114
    /*if (api_get_setting('active_template')) {
6115
        $actived_theme = api_get_setting('active_template');
6116
    }*/
6117
    $actived_theme_path = $template_path.$actived_theme.DIRECTORY_SEPARATOR;
6118
    return $actived_theme_path;
6119
}
6120
6121
/**
6122
 * Check browser support for type files
6123
 * This function check if the users browser support a file format or
6124
 * return the current browser and major ver when $format=check_browser
6125
 * @param string $format
6126
 *
6127
 * @return bool or return text array if $format=check_browser
6128
 * @author Juan Carlos Raña Trabado
6129
 */
6130
function api_browser_support($format = '')
6131
{
6132
    $browser = new Browser();
6133
    $current_browser = $browser->getBrowser();
6134
    $a_versiontemp = explode('.', $browser->getVersion());
6135
    $current_majorver = $a_versiontemp[0];
6136
6137
    static $result;
6138
6139
    if (isset($result[$format])) {
6140
        return $result[$format];
6141
    }
6142
6143
    // Native svg support
6144
    if ($format == 'svg') {
6145
        if (($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6146
            ($current_browser == 'Firefox' && $current_majorver > 1) ||
6147
            ($current_browser == 'Safari' && $current_majorver >= 4) ||
6148
            ($current_browser == 'Chrome' && $current_majorver >= 1) ||
6149
            ($current_browser == 'Opera' && $current_majorver >= 9)
6150
        ) {
6151
            $result[$format] = true;
6152
            return true;
6153
        } else {
6154
            $result[$format] = false;
6155
            return false;
6156
        }
6157
    } elseif ($format == 'pdf') {
6158
        //native pdf support
6159
        if ($current_browser == 'Chrome' && $current_majorver >= 6) {
6160
            $result[$format] = true;
6161
            return true;
6162
        } else {
6163
            $result[$format] = false;
6164
            return false;
6165
        }
6166
    } elseif ($format == 'tif' || $format == 'tiff') {
6167
        //native tif support
6168
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6169
            $result[$format] = true;
6170
            return true;
6171
        } else {
6172
            $result[$format] = false;
6173
            return false;
6174
        }
6175
    } elseif ($format == 'ogg' || $format == 'ogx' || $format == 'ogv' || $format == 'oga') {
6176
        //native ogg, ogv,oga support
6177
        if (($current_browser == 'Firefox' && $current_majorver >= 3) ||
6178
            ($current_browser == 'Chrome' && $current_majorver >= 3) ||
6179
            ($current_browser == 'Opera' && $current_majorver >= 9)) {
6180
            $result[$format] = true;
6181
            return true;
6182
        } else {
6183
            $result[$format] = false;
6184
            return false;
6185
        }
6186
    } elseif ($format == 'mpg' || $format == 'mpeg') {
6187
        //native mpg support
6188
        if (($current_browser == 'Safari' && $current_majorver >= 5)) {
6189
            $result[$format] = true;
6190
            return true;
6191
        } else {
6192
            $result[$format] = false;
6193
            return false;
6194
        }
6195
    } elseif ($format == 'mp4') {
6196
        //native mp4 support (TODO: Android, iPhone)
6197
        if ($current_browser == 'Android' || $current_browser == 'iPhone') {
6198
            $result[$format] = true;
6199
            return true;
6200
        } else {
6201
            $result[$format] = false;
6202
            return false;
6203
        }
6204
    } elseif ($format == 'mov') {
6205
        //native mov support( TODO:check iPhone)
6206
        if ($current_browser == 'Safari' && $current_majorver >= 5 || $current_browser == 'iPhone') {
6207
            $result[$format] = true;
6208
            return true;
6209
        } else {
6210
            $result[$format] = false;
6211
            return false;
6212
        }
6213
    } elseif ($format == 'avi') {
6214
        //native avi support
6215
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6216
            $result[$format] = true;
6217
            return true;
6218
        } else {
6219
            $result[$format] = false;
6220
            return false;
6221
        }
6222
    } elseif ($format == 'wmv') {
6223
        //native wmv support
6224
        if ($current_browser == 'Firefox' && $current_majorver >= 4) {
6225
            $result[$format] = true;
6226
            return true;
6227
        } else {
6228
            $result[$format] = false;
6229
            return false;
6230
        }
6231 View Code Duplication
    } elseif ($format == 'webm') {
6232
        //native webm support (TODO:check IE9, Chrome9, Android)
6233
        if (($current_browser == 'Firefox' && $current_majorver >= 4) ||
6234
            ($current_browser == 'Opera' && $current_majorver >= 9) ||
6235
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6236
            ($current_browser == 'Chrome' && $current_majorver >= 9) ||
6237
            $current_browser == 'Android'
6238
        ) {
6239
            $result[$format] = true;
6240
            return true;
6241
        } else {
6242
            $result[$format] = false;
6243
            return false;
6244
        }
6245
    } elseif ($format == 'wav') {
6246
        //native wav support (only some codecs !)
6247
        if (($current_browser == 'Firefox' && $current_majorver >= 4) ||
6248
            ($current_browser == 'Safari' && $current_majorver >= 5) ||
6249
            ($current_browser == 'Opera' && $current_majorver >= 9) ||
6250
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6251
            ($current_browser == 'Chrome' && $current_majorver > 9) ||
6252
            $current_browser == 'Android' ||
6253
            $current_browser == 'iPhone'
6254
        ) {
6255
            $result[$format] = true;
6256
            return true;
6257
        } else {
6258
            $result[$format] = false;
6259
            return false;
6260
        }
6261
    } elseif ($format == 'mid' || $format == 'kar') {
6262
        //native midi support (TODO:check Android)
6263
        if ($current_browser == 'Opera' && $current_majorver >= 9 || $current_browser == 'Android') {
6264
            $result[$format] = true;
6265
            return true;
6266
        } else {
6267
            $result[$format] = false;
6268
            return false;
6269
        }
6270
    } elseif ($format == 'wma') {
6271
        //native wma support
6272
        if ($current_browser == 'Firefox' && $current_majorver >= 4) {
6273
            $result[$format] = true;
6274
            return true;
6275
        } else {
6276
            $result[$format] = false;
6277
            return false;
6278
        }
6279
    } elseif ($format == 'au') {
6280
        //native au support
6281
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6282
            $result[$format] = true;
6283
            return true;
6284
        } else {
6285
            $result[$format] = false;
6286
            return false;
6287
        }
6288 View Code Duplication
    } elseif ($format == 'mp3') {
6289
        //native mp3 support (TODO:check Android, iPhone)
6290
        if (($current_browser == 'Safari' && $current_majorver >= 5) ||
6291
            ($current_browser == 'Chrome' && $current_majorver >= 6) ||
6292
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6293
            $current_browser == 'Android' ||
6294
            $current_browser == 'iPhone' ||
6295
            $current_browser == 'Firefox'
6296
        ) {
6297
            $result[$format] = true;
6298
            return true;
6299
        } else {
6300
            $result[$format] = false;
6301
            return false;
6302
        }
6303
    } elseif ($format == "check_browser") {
6304
        $array_check_browser = array($current_browser, $current_majorver);
6305
        return $array_check_browser;
6306
    } else {
6307
        $result[$format] = false;
6308
        return false;
6309
    }
6310
}
6311
6312
/**
6313
 * This function checks if exist path and file browscap.ini
6314
 * In order for this to work, your browscap configuration setting in php.ini
6315
 * must point to the correct location of the browscap.ini file on your system
6316
 * http://php.net/manual/en/function.get-browser.php
6317
 *
6318
 * @return bool
6319
 *
6320
 * @author Juan Carlos Raña Trabado
6321
 */
6322
function api_check_browscap() {
6323
    $setting = ini_get('browscap');
6324
    if ($setting) {
6325
        $browser = get_browser($_SERVER['HTTP_USER_AGENT'], true);
6326
        if (strpos($setting, 'browscap.ini') && !empty($browser)) {
6327
            return true;
6328
        }
6329
    }
6330
    return false;
6331
}
6332
6333
/**
6334
 * Returns the <script> HTML tag
6335
 * @param string $file
6336
 * @param bool $getURL
6337
 * @return string
6338
 */
6339 View Code Duplication
function api_get_js($file, $getURL = false)
6340
{
6341
    $url = Container::getAsset()->getUrl($file);
6342
6343
    if ($getURL) {
6344
        return $url;
6345
    }
6346
6347
    return '<script type="text/javascript" src="'.$url.'"></script>'."\n";
6348
}
6349
6350
/**
6351
 * Returns the <script> HTML tag
6352
 *
6353
 * @param string $file
6354
 * @param bool $getURL only returns the URL without the <script> tag
6355
 * @return string
6356
 */
6357 View Code Duplication
function api_get_asset($file, $getURL = false)
6358
{
6359
    $url = Container::getAsset()->getUrl("assets/".$file);
6360
6361
    if ($getURL) {
6362
        return $url;
6363
    }
6364
6365
    return '<script type="text/javascript" src="'.$url.'"></script>'."\n";
6366
}
6367
6368
/**
6369
 * Returns the <link> HTML tag
6370
 *
6371
 * @param string $file
6372
 * @param string $media
6373
 *
6374
 * @return string
6375
 */
6376
function api_get_css($file, $media = 'screen')
6377
{
6378
    $url = Container::getAsset()->getUrl($file);
6379
6380
    return '<link href="'.$url.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
6381
}
6382
6383
/**
6384
 *
6385
 * Returns the <link> HTML tag
6386
 *
6387
 * @param $file
6388
 * @param string $media
6389
 * @return string
6390
 */
6391
function api_get_css_asset($file, $media = 'screen')
6392
{
6393
    $url = Container::getAsset()->getUrl("assets/".$file);
6394
    return '<link href="'.$url.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
6395
}
6396
6397
/**
6398
 * Get jsPlumb lib
6399
 * @return string
6400
 */
6401
function api_get_js_plumb()
6402
{
6403
    return api_get_asset('jsPlumb/build/1.3.7/js/jquery.jsPlumb-1.3.7-all.js');
6404
}
6405
6406
/**
6407
 * Return epiclock js and css
6408
 * @return string
6409
 */
6410
function api_get_js_epiclock()
6411
{
6412
    $html = api_get_css('js/epiclock/stylesheet/jquery.epiclock.css');
6413
    $html .= api_get_css('js/epiclock/renderers/minute/epiclock.minute.css');
6414
    $html .= api_get_js('js/epiclock/javascript/jquery.dateformat.min.js');
6415
    $html .= api_get_js('js/epiclock/javascript/jquery.epiclock.min.js');
6416
    $html .= api_get_js('js/epiclock/renderers/minute/epiclock.minute.js');
6417
6418
    return $html;
6419
}
6420
6421
/**
6422
 * Returns the js header to include the jquery library
6423
 */
6424
function api_get_jquery_js()
6425
{
6426
    return api_get_asset('jquery/dist/jquery.min.js');
6427
}
6428
6429
/**
6430
 * Returns the jquery path
6431
 * @return string
6432
 */
6433
function api_get_jquery_web_path()
6434
{
6435
    return api_get_asset('jquery/dist/jquery.min.js', true);
6436
}
6437
6438
/**
6439
 * @return string
6440
 */
6441
function api_get_jquery_ui_js_web_path()
6442
{
6443
    return api_get_asset('jquery-ui/jquery-ui.min.js', true);
6444
}
6445
6446
/**
6447
 * @return string
6448
 */
6449
function api_get_jquery_ui_css_web_path()
6450
{
6451
    return api_get_asset('jquery-ui/themes/smoothness/jquery-ui.min.css', true);
6452
}
6453
6454
/**
6455
 * Returns the jquery-ui library js headers
6456
 * @param   bool    add the jqgrid library
6457
 * @return  string  html tags
6458
 *
6459
 */
6460
function api_get_jquery_ui_js($include_jqgrid = false) {
6461
    $libraries = array();
6462
    if ($include_jqgrid) {
6463
       $libraries[] = 'jqgrid';
6464
    }
6465
    return api_get_jquery_libraries_js($libraries);
6466
}
6467
6468
function api_get_jqgrid_js() {
6469
    return api_get_jquery_libraries_js(array('jqgrid'));
6470
}
6471
6472
/**
6473
 * Returns the jquery library js and css headers
6474
 *
6475
 * @param   array   list of jquery libraries supported jquery-ui, jqgrid
6476
 * @param   bool    add the jquery library
6477
 * @return  string  html tags
6478
 *
6479
 */
6480
function api_get_jquery_libraries_js($libraries) {
6481
    $js = '';
6482
    //jqgrid js and css
6483
    if (in_array('jqgrid', $libraries)) {
6484
        $language = 'en';
6485
        $platform_isocode = strtolower(api_get_language_isocode());
6486
6487
        //languages supported by jqgrid see files in main/inc/lib/javascript/jqgrid/js/i18n
6488
        $jqgrid_langs = array(
6489
            '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'
6490
        );
6491
6492
        if (in_array($platform_isocode, $jqgrid_langs)) {
6493
            $language = $platform_isocode;
6494
        }
6495
        //$js .= '<link rel="stylesheet" href="'.$js_path.'jqgrid/css/ui.jqgrid.css" type="text/css">';
6496
        /*$js .= api_get_css($js_path.'jqgrid/css/ui.jqgrid.css');
6497
        $js .= api_get_js('jqgrid/js/i18n/grid.locale-'.$languaje.'.js');
6498
        $j
6499
6500
        s .= api_get_js('jqgrid/js/jquery.jqGrid.min.js');*/
6501
6502
        $js .= api_get_css_asset('jqgrid/css/ui.jqgrid.css');
6503
        $js .= api_get_asset('jqgrid/js/minified/jquery.jqGrid.min.js');
6504
        $js .= api_get_asset('jqgrid/js/i18n/grid.locale-'.$language.'.js');
6505
    }
6506
6507
    //Document multiple upload funcionality
6508
    if (in_array('jquery-upload', $libraries)) {
6509
        $js .= api_get_asset('blueimp-load-image/js/load-image.all.min.js');
6510
        $js .= api_get_asset('blueimp-canvas-to-blob/js/canvas-to-blob.min.js');
6511
        $js .= api_get_asset('jquery-file-upload/js/jquery.iframe-transport.js');
6512
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload.js');
6513
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-process.js');
6514
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-image.js');
6515
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-audio.js');
6516
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-video.js');
6517
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-validate.js');
6518
        $js .= api_get_css_asset('jquery-file-upload/css/jquery.fileupload.css');
6519
        $js .= api_get_css_asset('jquery-file-upload/css/jquery.fileupload-ui.css');
6520
    }
6521
6522
    // jquery datepicker
6523
    if (in_array('datepicker', $libraries)) {
6524
        $languaje   = 'en-GB';
6525
        $platform_isocode = strtolower(api_get_language_isocode());
6526
6527
        // languages supported by jqgrid see files in main/inc/lib/javascript/jqgrid/js/i18n
6528
        $datapicker_langs = array(
6529
            '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'
6530
        );
6531
        if (in_array($platform_isocode, $datapicker_langs)) {
6532
            $languaje = $platform_isocode;
6533
        }
6534
6535
        $js .= api_get_js('jquery-ui/jquery-ui-i18n.min.js');
6536
        $script = '<script>
6537
        $(function(){
6538
            $.datepicker.setDefaults($.datepicker.regional["'.$languaje.'"]);
6539
            $.datepicker.regional["local"] = $.datepicker.regional["'.$languaje.'"];
6540
        });
6541
        </script>
6542
        ';
6543
        $js .= $script;
6544
    }
6545
    return $js;
6546
}
6547
6548
/**
6549
 * Returns the course's URL
6550
 *
6551
 * This function relies on api_get_course_info()
6552
 * @param   string  The course code - optional (takes it from session if not given)
6553
 * @param   int     The session id  - optional (takes it from session if not given)
6554
 * @param integer $session_id
6555
 * @return  string|null   The URL of the course or null if something does not work
6556
 * @author  Julio Montoya <[email protected]>
6557
 */
6558
function api_get_course_url($course_code = null, $session_id = null)
6559
{
6560
    if (empty($course_code)) {
6561
        $course_info = api_get_course_info();
6562
    } else {
6563
        $course_info = api_get_course_info($course_code);
6564
    }
6565
    if (empty($session_id)) {
6566
        $session_url = '?id_session='.api_get_session_id();
6567
    } else {
6568
        $session_url = '?id_session='.intval($session_id);
6569
    }
6570
    /*
6571
    if (empty($group_id)) {
6572
        $group_url = '&gidReq='.api_get_group_id();
6573
    } else {
6574
        $group_url = '&gidReq='.intval($group_id);
6575
    }*/
6576
    if (!empty($course_info['path'])) {
6577
        return api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php'.$session_url;
6578
    }
6579
    return null;
6580
}
6581
6582
/**
6583
 *
6584
 * Check if the current portal has the $_configuration['multiple_access_urls'] parameter on
6585
 * @return bool true if multi site is enabled
6586
 *
6587
 **/
6588
function api_get_multiple_access_url()
6589
{
6590
    return api_get_configuration_value('multiple_access_urls');
6591
}
6592
6593
/**
6594
 * @return bool
6595
 */
6596
function api_is_multiple_url_enabled() {
6597
    return api_get_multiple_access_url();
6598
}
6599
6600
/**
6601
 * Returns a md5 unique id
6602
 * @todo add more parameters
6603
 */
6604
function api_get_unique_id()
6605
{
6606
    $id = md5(time().uniqid().api_get_user_id().api_get_course_id().api_get_session_id());
6607
    return $id;
6608
}
6609
6610
/**
6611
 * Get home path
6612
 * @return string
6613
 */
6614
function api_get_home_path()
6615
{
6616
    // FIX : Start the routing determination from central path definition
6617
    $home = api_get_path(SYS_HOME_PATH);
6618
    if (api_get_multiple_access_url()) {
6619
        $access_url_id = api_get_current_access_url_id();
6620
        $url_info = api_get_access_url($access_url_id);
6621
        $url = api_remove_trailing_slash(preg_replace('/https?:\/\//i', '', $url_info['url']));
6622
        $clean_url = api_replace_dangerous_char($url);
6623
        $clean_url = str_replace('/', '-', $clean_url);
6624
        $clean_url .= '/';
6625
        if ($clean_url != 'localhost/') {
6626
            // means that the multiple URL was not well configured we don't rename the $home variable
6627
            return "{$home}{$clean_url}";
6628
        }
6629
    }
6630
6631
    return $home;
6632
}
6633
6634
/**
6635
 *
6636
 * @param int Course id
6637
 * @param int tool id: TOOL_QUIZ, TOOL_FORUM, TOOL_STUDENTPUBLICATION, TOOL_LEARNPATH
6638
 * @param int the item id (tool id, exercise id, lp id)
6639
 * @return bool
6640
 */
6641
function api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code = null)
6642
{
6643
    if (api_is_platform_admin()) {
6644
        return false;
6645
    }
6646
    if (api_get_setting('gradebook_locking_enabled') == 'true') {
6647
        if (empty($course_code)) {
6648
            $course_code = api_get_course_id();
6649
        }
6650
        $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
6651
        $item_id = intval($item_id);
6652
        $link_type = intval($link_type);
6653
        $course_code = Database::escape_string($course_code);
6654
        $sql = "SELECT locked FROM $table
6655
                WHERE locked = 1 AND ref_id = $item_id AND type = $link_type AND course_code = '$course_code' ";
6656
        $result = Database::query($sql);
6657
        if (Database::num_rows($result)) {
6658
            return true;
6659
        }
6660
    }
6661
    return false;
6662
}
6663
6664
/**
6665
 * Blocks a page if the item was added in a gradebook
6666
 *
6667
 * @param int       exercise id, work id, thread id,
6668
 * @param int       LINK_EXERCISE, LINK_STUDENTPUBLICATION, LINK_LEARNPATH LINK_FORUM_THREAD, LINK_ATTENDANCE
6669
 * see gradebook/lib/be/linkfactory
6670
 * @param string    course code
6671
 * @return false|null
6672
 */
6673
function api_block_course_item_locked_by_gradebook($item_id, $link_type, $course_code = null)
6674
{
6675
    if (api_is_platform_admin()) {
6676
        return false;
6677
    }
6678
6679
    if (api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code)) {
6680
        $message = Display::return_message(get_lang('ResourceLockedByGradebook'), 'warning');
6681
        api_not_allowed(true, $message);
6682
    }
6683
}
6684
6685
/**
6686
 * Checks the PHP version installed is enough to run Chamilo
6687
 * @param string Include path (used to load the error page)
6688
 * @return void
6689
 */
6690
function api_check_php_version($my_inc_path = null)
6691
{
6692
    if (!function_exists('version_compare') || version_compare(phpversion(), REQUIRED_PHP_VERSION, '<')) {
6693
        $global_error_code = 1;
6694
        // Incorrect PHP version
6695
        $global_page = $my_inc_path.'global_error_message.inc.php';
6696
        if (file_exists($global_page)) {
6697
            require $global_page;
6698
        }
6699
        exit;
6700
    }
6701
}
6702
6703
/**
6704
 * Checks whether the Archive directory is present and writeable. If not,
6705
 * prints a warning message.
6706
 */
6707
function api_check_archive_dir()
6708
{
6709 View Code Duplication
    if (is_dir(api_get_path(SYS_ARCHIVE_PATH)) && !is_writable(api_get_path(SYS_ARCHIVE_PATH))) {
6710
        $message = Display::return_message(get_lang('ArchivesDirectoryNotWriteableContactAdmin'), 'warning');
6711
        api_not_allowed(true, $message);
6712
    }
6713
}
6714
6715
/**
6716
 * Returns an array of global configuration settings which should be ignored
6717
 * when printing the configuration settings screens
6718
 * @return array Array of strings, each identifying one of the excluded settings
6719
 */
6720
function api_get_locked_settings() {
6721
    return array(
6722
        'server_type',
6723
        'permanently_remove_deleted_files',
6724
        'account_valid_duration',
6725
        'service_ppt2lp',
6726
        'wcag_anysurfer_public_pages',
6727
        'upload_extensions_list_type',
6728
        'upload_extensions_blacklist',
6729
        'upload_extensions_whitelist',
6730
        'upload_extensions_skip',
6731
        'upload_extensions_replace_by',
6732
        'hide_dltt_markup',
6733
        'split_users_upload_directory',
6734
        'permissions_for_new_directories',
6735
        'permissions_for_new_files',
6736
        'platform_charset',
6737
        'ldap_description',
6738
        'cas_activate',
6739
        'cas_server',
6740
        'cas_server_uri',
6741
        'cas_port',
6742
        'cas_protocol',
6743
        'cas_add_user_activate',
6744
        'update_user_info_cas_with_ldap',
6745
        'languagePriority1',
6746
        'languagePriority2',
6747
        'languagePriority3',
6748
        'languagePriority4',
6749
        'login_is_email',
6750
        'chamilo_database_version'
6751
    );
6752
}
6753
6754
/**
6755
 * Checks if the user is corrently logged in. Returns the user ID if he is, or
6756
 * false if he isn't. If the user ID is given and is an integer, then the same
6757
 * ID is simply returned
6758
 * @param  integer User ID
6759
 * @return boolean Integer User ID is logged in, or false otherwise
6760
 */
6761
function api_user_is_login($user_id = null) {
6762
    $user_id = empty($user_id) ? api_get_user_id() : intval($user_id);
6763
    return $user_id && !api_is_anonymous();
6764
}
6765
6766
/**
6767
 * Guess the real ip for register in the database, even in reverse proxy cases.
6768
 * To be recognized, the IP has to be found in either $_SERVER['REMOTE_ADDR'] or
6769
 * in $_SERVER['HTTP_X_FORWARDED_FOR'], which is in common use with rproxies.
6770
 * @return string the user's real ip (unsafe - escape it before inserting to db)
6771
 * @author Jorge Frisancho Jibaja <[email protected]>, USIL - Some changes to allow the use of real IP using reverse proxy
6772
 * @version CEV CHANGE 24APR2012
6773
 */
6774
function api_get_real_ip()
6775
{
6776
    // Guess the IP if behind a reverse proxy
6777
    global $debug;
6778
    $ip = trim($_SERVER['REMOTE_ADDR']);
6779
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
6780
        if (preg_match('/,/', $_SERVER['HTTP_X_FORWARDED_FOR'])) {
6781
            @list($ip1, $ip2) = @explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
6782
        } else {
6783
            $ip1 = $_SERVER['HTTP_X_FORWARDED_FOR'];
6784
        }
6785
        $ip = trim($ip1);
6786
    }
6787
    if (!empty($debug)) error_log('Real IP: '.$ip);
6788
    return $ip;
6789
}
6790
6791
/**
6792
 * Checks whether an IP is included inside an IP range
6793
 * @param string IP address
6794
 * @param string IP range
6795
 * @param string $ip
6796
 * @return bool True if IP is in the range, false otherwise
6797
 * @author claudiu at cnixs dot com  on http://www.php.net/manual/fr/ref.network.php#55230
6798
 * @author Yannick Warnier for improvements and managment of multiple ranges
6799
 * @todo check for IPv6 support
6800
 */
6801
function api_check_ip_in_range($ip, $range)
6802
{
6803
    if (empty($ip) or empty($range)) {
6804
        return false;
6805
    }
6806
    $ip_ip = ip2long($ip);
6807
    // divide range param into array of elements
6808
    if (strpos($range, ',') !== false) {
6809
        $ranges = explode(',', $range);
6810
    } else {
6811
        $ranges = array($range);
6812
    }
6813
    foreach ($ranges as $range) {
6814
        $range = trim($range);
6815
        if (empty($range)) { continue; }
6816
        if (strpos($range, '/') === false) {
6817
            if (strcmp($ip, $range) === 0) {
6818
                return true; // there is a direct IP match, return OK
6819
            }
6820
            continue; //otherwise, get to the next range
6821
        }
6822
        // the range contains a "/", so analyse completely
6823
        list ($net, $mask) = explode("/", $range);
6824
6825
        $ip_net = ip2long($net);
6826
        // mask binary magic
6827
        $ip_mask = ~((1 << (32 - $mask)) - 1);
6828
6829
        $ip_ip_net = $ip_ip & $ip_mask;
6830
        if ($ip_ip_net == $ip_net) {
6831
            return true;
6832
        }
6833
    }
6834
6835
    return false;
6836
}
6837
6838
function api_check_user_access_to_legal($course_visibility)
6839
{
6840
    $course_visibility_list = array(COURSE_VISIBILITY_OPEN_WORLD, COURSE_VISIBILITY_OPEN_PLATFORM);
6841
    return in_array($course_visibility, $course_visibility_list) || api_is_drh();
6842
}
6843
6844
/**
6845
 * Checks if the global chat is enabled or not
6846
 *
6847
 * @return bool
6848
 */
6849
function api_is_global_chat_enabled()
6850
{
6851
    return
6852
        !api_is_anonymous() &&
6853
        api_get_setting('allow_global_chat') == 'true' &&
6854
        api_get_setting('allow_social_tool') == 'true';
6855
}
6856
6857
/**
6858
 * @todo Fix tool_visible_by_default_at_creation labels
6859
 * @todo Add sessionId parameter to avoid using context
6860
 *
6861
 * @param int $item_id
6862
 * @param int $tool_id
6863
 * @param int $group_id id
6864
 * @param array $courseInfo
6865
 * @param int $sessionId
6866
 * @param int $userId
6867
 */
6868
function api_set_default_visibility(
6869
    $item_id,
6870
    $tool_id,
6871
    $group_id = 0,
6872
    $courseInfo = array(),
6873
    $sessionId = 0,
6874
    $userId = 0
6875
) {
6876
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
6877
    $courseId = $courseInfo['real_id'];
6878
    $courseCode = $courseInfo['code'];
6879
    $sessionId = empty($sessionId) ? api_get_session_id() : $sessionId;
6880
    $userId = empty($userId) ? api_get_user_id() : $userId;
6881
6882
    if (empty($group_id)) {
6883
        $group_id = api_get_group_id();
6884
    }
6885
6886
    $groupInfo = GroupManager::get_group_properties($group_id);
6887
    $groupIid = 0;
6888
    if ($groupInfo) {
6889
        $groupIid = $groupInfo['iid'];
6890
    }
6891
6892
    $original_tool_id = $tool_id;
6893
6894
    switch ($tool_id) {
6895
        case TOOL_LINK:
6896
        case TOOL_LINK_CATEGORY:
6897
            $tool_id = 'links';
6898
            break;
6899
        case TOOL_DOCUMENT:
6900
            $tool_id = 'documents';
6901
            break;
6902
        case TOOL_LEARNPATH:
6903
            $tool_id = 'learning';
6904
            break;
6905
        case TOOL_ANNOUNCEMENT:
6906
            $tool_id = 'announcements';
6907
            break;
6908
        case TOOL_FORUM:
6909
        case TOOL_FORUM_CATEGORY:
6910
        case TOOL_FORUM_THREAD:
6911
            $tool_id = 'forums';
6912
            break;
6913
        case TOOL_QUIZ:
6914
            $tool_id = 'quiz';
6915
            break;
6916
    }
6917
    $setting = api_get_setting('tool_visible_by_default_at_creation');
6918
6919
    if (isset($setting[$tool_id])) {
6920
        $visibility = 'invisible';
6921
        if ($setting[$tool_id] == 'true') {
6922
            $visibility = 'visible';
6923
        }
6924
6925
        // Read the portal and course default visibility
6926
        if ($tool_id == 'documents') {
6927
            $visibility = DocumentManager::getDocumentDefaultVisibility($courseCode);
6928
        }
6929
6930
        api_item_property_update(
6931
            $courseInfo,
6932
            $original_tool_id,
6933
            $item_id,
6934
            $visibility,
6935
            $userId,
6936
            $groupInfo,
0 ignored issues
show
Bug introduced by
It seems like $groupInfo defined by \GroupManager::get_group_properties($group_id) on line 6886 can also be of type null; however, api_item_property_update() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
6937
            null,
6938
            null,
6939
            null,
6940
            api_get_session_id()
6941
        );
6942
6943
        // Fixes default visibility for tests
6944
        switch ($original_tool_id) {
6945
            case TOOL_QUIZ:
6946
                if (empty($sessionId)) {
6947
                    $objExerciseTmp = new Exercise($courseId);
6948
                    $objExerciseTmp->read($item_id);
6949
                    if ($visibility == 'visible') {
6950
                        $objExerciseTmp->enable();
6951
                        $objExerciseTmp->save();
6952
                    } else {
6953
                        $objExerciseTmp->disable();
6954
                        $objExerciseTmp->save();
6955
                    }
6956
                }
6957
                break;
6958
        }
6959
    }
6960
}
6961
6962
/**
6963
 * @return string
6964
 */
6965
function api_get_security_key()
6966
{
6967
    return api_get_configuration_value('security_key');
6968
}
6969
6970
/**
6971
 * @param int $user_id
6972
 * @param int $courseId
6973
 * @param int $session_id
6974
 * @return array
6975
 */
6976
function api_detect_user_roles($user_id, $courseId, $session_id = 0)
6977
{
6978
    $user_roles = array();
6979
    $courseInfo = api_get_course_info_by_id($courseId);
6980
    $course_code = $courseInfo['code'];
6981
6982
    $url_id = api_get_current_access_url_id();
6983
    if (api_is_platform_admin_by_id($user_id, $url_id)) {
6984
        $user_roles[] = PLATFORM_ADMIN;
6985
    }
6986
6987
    /*if (api_is_drh()) {
6988
        $user_roles[] = DRH;
6989
    }*/
6990
6991
    if (!empty($session_id)) {
6992
        if (SessionManager::user_is_general_coach($user_id, $session_id)) {
6993
            $user_roles[] = SESSION_GENERAL_COACH;
6994
        }
6995
    }
6996
6997
    if (!empty($course_code)) {
6998
        if (empty($session_id)) {
6999
            if (CourseManager::is_course_teacher($user_id, $course_code)) {
7000
                $user_roles[] = COURSEMANAGER;
7001
            }
7002
            if (CourseManager::get_tutor_in_course_status($user_id, $courseInfo['real_id'])) {
7003
                $user_roles[] = COURSE_TUTOR;
7004
            }
7005
7006
            if (CourseManager::is_user_subscribed_in_course($user_id, $course_code)) {
7007
                $user_roles[] = COURSE_STUDENT;
7008
            }
7009
        } else {
7010
            $user_status_in_session = SessionManager::get_user_status_in_course_session(
7011
                $user_id,
7012
                $courseId,
7013
                $session_id
7014
            );
7015
7016
            if (!empty($user_status_in_session)) {
7017
                if ($user_status_in_session == 0) {
7018
                    $user_roles[] = SESSION_STUDENT;
7019
                }
7020
                if ($user_status_in_session == 2) {
7021
                    $user_roles[] = SESSION_COURSE_COACH;
7022
                }
7023
            }
7024
7025
            /*if (api_is_course_session_coach($user_id, $course_code, $session_id)) {
7026
               $user_roles[] = SESSION_COURSE_COACH;
7027
            }*/
7028
        }
7029
    }
7030
    return $user_roles;
7031
}
7032
7033
/**
7034
 * @param int $courseId
7035
 * @param int $session_id
7036
 * @return bool
7037
 */
7038
function api_coach_can_edit_view_results($courseId = null, $session_id = null)
7039
{
7040
    if (api_is_platform_admin()) {
7041
        return true;
7042
    }
7043
7044
    $user_id = api_get_user_id();
7045
7046
    if (empty($courseId)) {
7047
        $courseId = api_get_course_int_id();
7048
    }
7049
7050
    if (empty($session_id)) {
7051
        $session_id = api_get_session_id();
7052
    }
7053
7054
    $roles = api_detect_user_roles($user_id, $courseId, $session_id);
7055
7056
    if (in_array(SESSION_COURSE_COACH, $roles)) {
7057
        //return api_get_setting('session_tutor_reports_visibility') == 'true';
7058
        return true;
7059
    } else {
7060
        if (in_array(COURSEMANAGER, $roles)) {
7061
            return true;
7062
        }
7063
        return false;
7064
    }
7065
}
7066
7067
function api_get_js_simple($file)
7068
{
7069
    return '<script type="text/javascript" src="'.$file.'"></script>'."\n";
7070
}
7071
7072
function api_set_settings_and_plugins()
7073
{
7074
    global $_configuration;
7075
    $_setting = array();
7076
    $_plugins = array();
7077
7078
    // access_url == 1 is the default chamilo location
7079
    $settings_by_access_list = array();
7080
    $access_url_id = api_get_current_access_url_id();
7081 View Code Duplication
    if ($access_url_id != 1) {
7082
        $url_info = api_get_access_url($_configuration['access_url']);
7083
        if ($url_info['active'] == 1) {
7084
            $settings_by_access = & api_get_settings(null, 'list', $_configuration['access_url'], 1);
7085
            foreach ($settings_by_access as & $row) {
7086
                if (empty($row['variable'])) {
7087
                    $row['variable'] = 0;
7088
                }
7089
                if (empty($row['subkey'])) {
7090
                    $row['subkey'] = 0;
7091
                }
7092
                if (empty($row['category'])) {
7093
                    $row['category'] = 0;
7094
                }
7095
                $settings_by_access_list[$row['variable']][$row['subkey']][$row['category']] = $row;
7096
            }
7097
        }
7098
    }
7099
7100
    $result = api_get_settings(null, 'list', 1);
7101
7102
    foreach ($result as & $row) {
7103
        if ($access_url_id != 1) {
7104
            if ($url_info['active'] == 1) {
7105
                $var = empty($row['variable']) ? 0 : $row['variable'];
7106
                $subkey = empty($row['subkey']) ? 0 : $row['subkey'];
7107
                $category = empty($row['category']) ? 0 : $row['category'];
7108
            }
7109
7110
            if ($row['access_url_changeable'] == 1 && $url_info['active'] == 1) {
7111
                if (isset($settings_by_access_list[$var]) &&
7112
                    $settings_by_access_list[$var][$subkey][$category]['selected_value'] != '') {
7113
                    if ($row['subkey'] == null) {
7114
                        $_setting[$row['variable']] = $settings_by_access_list[$var][$subkey][$category]['selected_value'];
7115
                    } else {
7116
                        $_setting[$row['variable']][$row['subkey']] = $settings_by_access_list[$var][$subkey][$category]['selected_value'];
7117
                    }
7118
                } else {
7119
                    if ($row['subkey'] == null) {
7120
                        $_setting[$row['variable']] = $row['selected_value'];
7121
                    } else {
7122
                        $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7123
                    }
7124
                }
7125
            } else {
7126
                if ($row['subkey'] == null) {
7127
                    $_setting[$row['variable']] = $row['selected_value'];
7128
                } else {
7129
                    $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7130
                }
7131
            }
7132
        } else {
7133
            if ($row['subkey'] == null) {
7134
                $_setting[$row['variable']] = $row['selected_value'];
7135
            } else {
7136
                $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7137
            }
7138
        }
7139
    }
7140
7141
    $result = api_get_settings('Plugins', 'list', $access_url_id);
7142
    $_plugins = array();
7143 View Code Duplication
    foreach ($result as & $row) {
7144
        $key = & $row['variable'];
7145
        if (is_string($_setting[$key])) {
7146
            $_setting[$key] = array();
7147
        }
7148
        $_setting[$key][] = $row['selected_value'];
7149
        $_plugins[$key][] = $row['selected_value'];
7150
    }
7151
7152
    $_SESSION['_setting'] = $_setting;
7153
    $_SESSION['_plugins'] = $_plugins;
7154
}
7155
7156
/**
7157
 * Tries to set memory limit, if authorized and new limit is higher than current
7158
 * @param string New memory limit
7159
 * @param string $mem
7160
 * @return bool True on success, false on failure or current is higher than suggested
7161
 * @assert (null) === false
7162
 * @assert (-1) === false
7163
 * @assert (0) === true
7164
 * @assert ('1G') === true
7165
 */
7166
function api_set_memory_limit($mem)
7167
{
7168
    //if ini_set() not available, this function is useless
7169
    if (!function_exists('ini_set') || is_null($mem) || $mem == -1) {
7170
        return false;
7171
    }
7172
7173
    $memory_limit = ini_get('memory_limit');
7174
    if (api_get_bytes_memory_limit($mem) > api_get_bytes_memory_limit($memory_limit)) {
7175
        ini_set('memory_limit', $mem);
7176
        return true;
7177
    }
7178
    return false;
7179
}
7180
7181
/**
7182
 * Gets memory limit in bytes
7183
 * @param string The memory size (128M, 1G, 1000K, etc)
7184
 * @return int
7185
 * @assert (null) === false
7186
 * @assert ('1t')  === 1099511627776
7187
 * @assert ('1g')  === 1073741824
7188
 * @assert ('1m')  === 1048576
7189
 * @assert ('100k') === 102400
7190
 */
7191
function api_get_bytes_memory_limit($mem)
7192
{
7193
    $size = strtolower(substr($mem, -1));
7194
7195
    switch ($size) {
7196
        case 't':
7197
            $mem = intval(substr($mem, -1)) * 1024 * 1024 * 1024 * 1024;
7198
            break;
7199
        case 'g':
7200
            $mem = intval(substr($mem, 0, -1)) * 1024 * 1024 * 1024;
7201
            break;
7202
        case 'm':
7203
            $mem = intval(substr($mem, 0, -1)) * 1024 * 1024;
7204
            break;
7205
        case 'k':
7206
            $mem = intval(substr($mem, 0, -1)) * 1024;
7207
            break;
7208
        default:
7209
            // we assume it's integer only
7210
            $mem = intval($mem);
7211
            break;
7212
    }
7213
    return $mem;
7214
}
7215
7216
/**
7217
 * Finds all the information about a user from username instead of user id
7218
 *
7219
 * @param string $officialCode
7220
 * @return array $user_info user_id, lastname, firstname, username, email, ...
7221
 * @author Yannick Warnier <[email protected]>
7222
 */
7223 View Code Duplication
function api_get_user_info_from_official_code($officialCode)
7224
{
7225
    if (empty($officialCode)) {
7226
        return false;
7227
    }
7228
7229
    $user = UserManager::getManager()->findUserByOfficialCode($officialCode);
7230
    if ($user) {
7231
        return _api_format_user($user);
7232
    }
7233
7234
    return false;
7235
}
7236
7237
/**
7238
 * @param string $usernameInputId
7239
 * @param string $passwordInputId
7240
 * @return null|string
7241
 */
7242
function api_get_password_checker_js($usernameInputId, $passwordInputId)
7243
{
7244
    $checkPass = api_get_setting('allow_strength_pass_checker');
7245
    $useStrengthPassChecker = $checkPass === 'true';
7246
7247
    if ($useStrengthPassChecker === false) {
7248
        return null;
7249
    }
7250
7251
    $translations = [
7252
        'wordLength' => get_lang('PasswordIsTooShort'),
7253
        'wordNotEmail' => get_lang('YourPasswordCannotBeTheSameAsYourEmail'),
7254
        'wordSimilarToUsername' => get_lang('YourPasswordCannotContainYourUsername'),
7255
        'wordTwoCharacterClasses' => get_lang('WordTwoCharacterClasses'),
7256
        'wordRepetitions' => get_lang('TooManyRepetitions'),
7257
        'wordSequences' => get_lang('YourPasswordContainsSequences'),
7258
        'errorList' => get_lang('ErrorsFound'),
7259
        'veryWeak' => get_lang('PasswordVeryWeak'),
7260
        'weak' => get_lang('PasswordWeak'),
7261
        'normal' => get_lang('PasswordNormal'),
7262
        'medium' => get_lang('PasswordMedium'),
7263
        'strong' => get_lang('PasswordStrong'),
7264
        'veryStrong' => get_lang('PasswordVeryStrong')
7265
    ];
7266
7267
    $js = api_get_asset('pwstrength-bootstrap/dist/pwstrength-bootstrap.min.js');
7268
    $js .= "<script>    
7269
    var errorMessages = {
7270
        password_to_short : \"" . get_lang('PasswordIsTooShort')."\",
7271
        same_as_username : \"".get_lang('YourPasswordCannotBeTheSameAsYourUsername')."\"
7272
    };
7273
7274
    $(document).ready(function() {
7275
        var lang = ".json_encode($translations).";     
7276
        var options = {        
7277
            onLoad : function () {
7278
                //$('#messages').text('Start typing password');
7279
            },
7280
            onKeyUp: function (evt) {
7281
                $(evt.target).pwstrength('outputErrorList');
7282
            },
7283
            errorMessages : errorMessages,
7284
            viewports: {
7285
                progress: '#password_progress',
7286
                verdict: '#password-verdict',
7287
                errors: '#password-errors'
7288
            },
7289
            usernameField: '$usernameInputId'
7290
        };
7291
        options.i18n = {
7292
            t: function (key) {
7293
                var result = lang[key];
7294
                return result === key ? '' : result; // This assumes you return the                
7295
            }
7296
        };
7297
        $('".$passwordInputId."').pwstrength(options);
7298
    });
7299
    </script>";
7300
7301
    return $js;
7302
}
7303
7304
/**
7305
 * create an user extra field called 'captcha_blocked_until_date'
7306
 * @param string $username
7307
 * @return bool
7308
 */
7309
function api_block_account_captcha($username)
7310
{
7311
    $userInfo = api_get_user_info_from_username($username);
7312
    if (empty($userInfo)) {
7313
        return false;
7314
    }
7315
    $minutesToBlock = api_get_setting('captcha_time_to_block');
7316
    $time = time() + $minutesToBlock * 60;
7317
    UserManager::update_extra_field_value(
7318
        $userInfo['user_id'],
7319
        'captcha_blocked_until_date',
7320
        api_get_utc_datetime($time)
0 ignored issues
show
Bug introduced by
It seems like api_get_utc_datetime($time) targeting api_get_utc_datetime() can also be of type null or object<DateTime>; however, UserManager::update_extra_field_value() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
7321
    );
7322
    return true;
7323
}
7324
7325
/**
7326
 * @param string $username
7327
 * @return bool
7328
 */
7329
function api_clean_account_captcha($username)
7330
{
7331
    $userInfo = api_get_user_info_from_username($username);
7332
    if (empty($userInfo)) {
7333
        return false;
7334
    }
7335
    Session::erase('loginFailedCount');
7336
    UserManager::update_extra_field_value(
7337
        $userInfo['user_id'],
7338
        'captcha_blocked_until_date',
7339
        null
7340
    );
7341
    return true;
7342
}
7343
7344
/**
7345
 * @param string $username
7346
 * @return bool
7347
 */
7348
function api_get_user_blocked_by_captcha($username)
7349
{
7350
    $userInfo = api_get_user_info_from_username($username);
7351
    if (empty($userInfo)) {
7352
        return false;
7353
    }
7354
    $data = UserManager::get_extra_user_data_by_field(
7355
        $userInfo['user_id'],
7356
        'captcha_blocked_until_date'
7357
    );
7358
    if (isset($data) && isset($data['captcha_blocked_until_date'])) {
7359
        return $data['captcha_blocked_until_date'];
7360
    }
7361
    return false;
7362
}
7363
7364
/**
7365
 * Remove tags from HTML anf return the $in_number_char first non-HTML char
7366
 * Postfix the text with "..." if it has been truncated.
7367
 * @param integer $in_number_char
7368
 * @return string
7369
 * @author hubert borderiou
7370
 */
7371
function api_get_short_text_from_html($in_html, $in_number_char)
7372
{
7373
    $out_res = api_remove_tags_with_space($in_html, false);
7374
    $postfix = "...";
7375
    if (strlen($out_res) > $in_number_char) {
7376
        $out_res = substr($out_res, 0, $in_number_char).$postfix;
7377
    }
7378
    return $out_res;
7379
}
7380
7381
/**
7382
 * Replace tags with a space in a text.
7383
 * If $in_double_quote_replace, replace " with '' (for HTML attribute purpose, for exemple)
7384
 * @return string
7385
 * @author hubert borderiou
7386
 */
7387
function api_remove_tags_with_space($in_html, $in_double_quote_replace = true)
7388
{
7389
    $out_res = $in_html;
7390
    if ($in_double_quote_replace) {
7391
        $out_res = str_replace('"', "''", $out_res);
7392
    }
7393
    // avoid text stuck together when tags are removed, adding a space after >
7394
    $out_res = str_replace(">", "> ", $out_res);
7395
    $out_res = strip_tags($out_res);
7396
7397
    return $out_res;
7398
}
7399
7400
/**
7401
 * If true, the drh can access all content (courses, users) inside a session
7402
 * @return bool
7403
 */
7404
function api_drh_can_access_all_session_content()
7405
{
7406
    $value = api_get_setting('drh_can_access_all_session_content');
7407
7408
    return $value === 'true';
7409
}
7410
7411
/**
7412
 * @param string $tool
7413
 * @param string $setting
7414
 * @param integer $defaultValue
7415
 * @return string
7416
 */
7417
function api_get_default_tool_setting($tool, $setting, $defaultValue)
7418
{
7419
    global $_configuration;
7420
    if (isset($_configuration[$tool]) &&
7421
        isset($_configuration[$tool]['default_settings']) &&
7422
        isset($_configuration[$tool]['default_settings'][$setting])
7423
    ) {
7424
        return $_configuration[$tool]['default_settings'][$setting];
7425
    }
7426
7427
    return $defaultValue;
7428
}
7429
7430
/**
7431
 * Checks if user can login as another user
7432
 *
7433
 * @param int $loginAsUserId the user id to log in
7434
 * @param int $userId my user id
7435
 * @return bool
7436
 */
7437
function api_can_login_as($loginAsUserId, $userId = null)
7438
{
7439
    if (empty($userId)) {
7440
        $userId = api_get_user_id();
7441
    }
7442
    if ($loginAsUserId == $userId) {
7443
        return false;
7444
    }
7445
7446
    if (empty($loginAsUserId)) {
7447
        return false;
7448
    }
7449
7450
    if ($loginAsUserId != strval(intval($loginAsUserId))) {
7451
        return false;
7452
    }
7453
7454
    // Check if the user to login is an admin
7455
    if (api_is_platform_admin_by_id($loginAsUserId)) {
7456
        // Only super admins can login to admin accounts
7457
        if (!api_global_admin_can_edit_admin($loginAsUserId)) {
7458
            return false;
7459
        }
7460
    }
7461
7462
    $userInfo = api_get_user_info($userId);
7463
    $isDrh = function() use($loginAsUserId) {
7464
        if (api_is_drh()) {
7465
            if (api_drh_can_access_all_session_content()) {
7466
                $users = SessionManager::getAllUsersFromCoursesFromAllSessionFromStatus('drh_all', api_get_user_id());
7467
                $userList = array();
7468
                if (is_array($users)) {
7469
                    foreach ($users as $user) {
7470
                        $userList[] = $user['user_id'];
7471
                    }
7472
                }
7473
                if (in_array($loginAsUserId, $userList)) {
7474
                    return true;
7475
                }
7476
            } else {
7477
                if (api_is_drh() && UserManager::is_user_followed_by_drh($loginAsUserId, api_get_user_id())) {
7478
                    return true;
7479
                }
7480
            }
7481
        }
7482
        return false;
7483
    };
7484
7485
    return api_is_platform_admin() || (api_is_session_admin() && $userInfo['status'] == 5) || $isDrh();
7486
}
7487
7488
/**
7489
 * @return bool
7490
 */
7491
function api_is_allowed_in_course()
7492
{
7493
    if (api_is_platform_admin()) {
7494
        return true;
7495
    }
7496
7497
    return Session::read('is_allowed_in_course');
7498
}
7499
7500
/**
7501
 * Set the cookie to go directly to the course code $in_firstpage
7502
 * after login
7503
 * @param string $in_firstpage is the course code of the course to go
7504
 */
7505
function api_set_firstpage_parameter($in_firstpage)
7506
{
7507
    setcookie('GotoCourse', $in_firstpage);
7508
}
7509
7510
/**
7511
 * Delete the cookie to go directly to the course code $in_firstpage
7512
 * after login
7513
 */
7514
function api_delete_firstpage_parameter()
7515
{
7516
    setcookie('GotoCourse', '', time() - 3600);
7517
}
7518
7519
/**
7520
 * @return boolean if course_code for direct course access after login is set
7521
 */
7522
function exist_firstpage_parameter()
7523
{
7524
    return (isset($_COOKIE['GotoCourse']) && $_COOKIE['GotoCourse'] != "");
7525
}
7526
7527
/**
7528
 * @return return the course_code of the course where user login
7529
 */
7530
function api_get_firstpage_parameter()
7531
{
7532
    return $_COOKIE['GotoCourse'];
7533
}
7534
7535
/**
7536
 * Return true on https install
7537
 * @return boolean
7538
 */
7539
function api_is_https()
7540
{
7541
    return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off');
7542
}
7543
7544
/**
7545
 * Return protocol (http or https)
7546
 * @return string
7547
 */
7548
function api_get_protocol()
7549
{
7550
    return api_is_https() ? 'https' : 'http';
7551
}
7552
7553
/**
7554
 * Return a string where " are replaced with 2 '
7555
 * It is useful when you pass a PHP variable in a Javascript browser dialog
7556
 * e.g. : alert("<?php get_lang('Message') ?>");
7557
 * and message contains character "
7558
 *
7559
 * @param string $in_text
7560
 * @return string
7561
 */
7562
function convert_double_quote_to_single($in_text)
7563
{
7564
    return api_preg_replace('/"/', "''", $in_text);
7565
}
7566
7567
/**
7568
 * Get origin
7569
 *
7570
 * @param string
7571
 * @return string
7572
 **/
7573
function api_get_origin()
7574
{
7575
    if (isset($_REQUEST['origin'])) {
7576
        return $_REQUEST['origin'] === 'learnpath' ? 'learnpath' : '';
7577
    }
7578
7579
    return '';
7580
}
7581
7582
/**
7583
 * Warns an user that the portal reach certain limit.
7584
 * @param string $limitName
7585
 */
7586
function api_warn_hosting_contact($limitName)
7587
{
7588
    $hostingParams = api_get_configuration_value(1);
7589
    $email = null;
7590
7591
    if (!empty($hostingParams)) {
7592
        if (isset($hostingParams['hosting_contact_mail'])) {
7593
            $email = $hostingParams['hosting_contact_mail'];
7594
        }
7595
    }
7596
7597
    if (!empty($email)) {
7598
        $subject = get_lang('HostingWarningReached');
7599
        $body = get_lang('PortalName').': '.api_get_path(WEB_PATH)." \n ";
7600
        $body .= get_lang('PortalLimitType').': '.$limitName." \n ";
7601
        if (isset($hostingParams[$limitName])) {
7602
            $body .= get_lang('Value').': '.$hostingParams[$limitName];
7603
        }
7604
        api_mail_html(null, $email, $subject, $body);
7605
    }
7606
}
7607
7608
/**
7609
 * Gets value of a variable from app/config/configuration.php
7610
 * Variables that are not set in the configuration.php file but set elsewhere:
7611
 * - virtual_css_theme_folder (vchamilo plugin)
7612
 * - access_url (global.inc.php)
7613
 * - apc/apc_prefix (global.inc.php)
7614
 *
7615
 * @param string $variable
7616
 *
7617
 * @return bool|mixed
7618
 */
7619
function api_get_configuration_value($variable)
7620
{
7621
    return Container::getParameter($variable);
7622
}
7623
7624
/**
7625
 * Returns supported image extensions in the portal
7626
 * @param   bool    $supportVectors Whether vector images should also be accepted or not
7627
 * @return  array   Supported image extensions in the portal
7628
 */
7629
function api_get_supported_image_extensions($supportVectors = true)
7630
{
7631
    // jpg can also be called jpeg, jpe, jfif and jif. See https://en.wikipedia.org/wiki/JPEG#JPEG_filename_extensions
7632
    $supportedImageExtensions = array('jpg', 'jpeg', 'png', 'gif', 'jpe', 'jfif', 'jif');
7633
    if ($supportVectors) {
7634
        array_push($supportedImageExtensions, 'svg');
7635
    }
7636
    if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
7637
        array_push($supportedImageExtensions, 'webp');
7638
    }
7639
    return $supportedImageExtensions;
7640
}
7641
7642
/**
7643
 * This setting changes the registration status for the campus
7644
 *
7645
 * @author Patrick Cool <[email protected]>, Ghent University
7646
 * @version August 2006
7647
 * @param   bool    $listCampus Whether we authorize
7648
 * @todo the $_settings should be reloaded here. => write api function for this and use this in global.inc.php also.
7649
 */
7650 View Code Duplication
function api_register_campus($listCampus = true) {
7651
    $tbl_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
7652
7653
    $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='registered'";
7654
    Database::query($sql);
7655
7656
    if (!$listCampus) {
7657
        $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='donotlistcampus'";
7658
        Database::query($sql);
7659
    }
7660
}
7661
7662
/**
7663
 * Checks whether current user is a student boss
7664
 * @global array $_user
7665
 * @return boolean
7666
 */
7667
function api_is_student_boss()
7668
{
7669
    $_user = api_get_user_info();
7670
7671
    return isset($_user['status']) && $_user['status'] == STUDENT_BOSS;
7672
}
7673
7674
/**
7675
 * Check whether the user type should be exclude.
7676
 * Such as invited or anonymous users
7677
 * @param boolean $checkDB Optional. Whether check the user status
7678
 * @param int $userId Options. The user id
7679
 *
7680
 * @return boolean
7681
 */
7682
function api_is_excluded_user_type($checkDB = false, $userId = 0)
7683
{
7684
    if ($checkDB) {
7685
        $userId = empty($userId) ? api_get_user_id() : intval($userId);
7686
7687
        if ($userId == 0) {
7688
            return true;
7689
        }
7690
7691
        $userInfo = api_get_user_info($userId);
7692
7693
        switch ($userInfo['status']) {
7694
            case INVITEE:
7695
                //no break;
7696
            case ANONYMOUS:
7697
                return true;
7698
            default:
7699
                return false;
7700
        }
7701
    }
7702
7703
    $isInvited = api_is_invitee();
7704
    $isAnonymous = api_is_anonymous();
7705
7706
    if ($isInvited || $isAnonymous) {
7707
        return true;
7708
    }
7709
7710
    return false;
7711
}
7712
7713
/**
7714
 * Get the user status to ignore in reports
7715
 * @param string $format Optional. The result type (array or string)
7716
 * @return array|string
7717
 */
7718
function api_get_users_status_ignored_in_reports($format = 'array')
7719
{
7720
    $excludedTypes = array(
7721
        INVITEE,
7722
        ANONYMOUS
7723
    );
7724
7725
    if ($format == 'string') {
7726
        return implode(', ', $excludedTypes);
7727
    }
7728
7729
    return $excludedTypes;
7730
}
7731
7732
/**
7733
 * Set the Site Use Cookie Warning for 1 year
7734
 */
7735
function api_set_site_use_cookie_warning_cookie()
7736
{
7737
    setcookie('ChamiloUsesCookies', 'ok', time() + 31556926);
7738
}
7739
7740
/**
7741
 * Return true if the Site Use Cookie Warning Cookie warning exists
7742
 * @return bool
7743
 */
7744
function api_site_use_cookie_warning_cookie_exist()
7745
{
7746
    return isset($_COOKIE['ChamiloUsesCookies']);
7747
}
7748
7749
/**
7750
 * Given a number of seconds, format the time to show hours, minutes and seconds
7751
 * @param int $time The time in seconds
7752
 * @param string $originFormat Optional. PHP o JS
7753
 * @return string (00h00'00")
7754
 */
7755
function api_format_time($time, $originFormat = 'php')
7756
{
7757
    $h = get_lang('h');
7758
    $hours = $time / 3600;
7759
    $mins = ($time % 3600) / 60;
7760
    $secs = ($time % 60);
7761
7762
    if ($time < 0) {
7763
        $hours = 0;
7764
        $mins = 0;
7765
        $secs = 0;
7766
    }
7767
7768
    if ($originFormat == 'js') {
7769
        $formattedTime = trim(sprintf("%02d : %02d : %02d", $hours, $mins, $secs));
7770
    } else {
7771
        $formattedTime = trim(sprintf("%02d$h%02d'%02d\"", $hours, $mins, $secs));
7772
    }
7773
7774
    return $formattedTime;
7775
}
7776
7777
/**
7778
 * Create a new empty directory with index.html file
7779
 * @param string $name The new directory name
7780
 * @param string $parentDirectory Directory parent directory name
7781
 * @return boolean Return true if the directory was create. Otherwise return false
7782
 */
7783
function api_create_protected_dir($name, $parentDirectory)
7784
{
7785
    $isCreated = false;
7786
7787
    if (!is_writable($parentDirectory)) {
7788
        return false;
7789
    }
7790
7791
    $fullPath = $parentDirectory.api_replace_dangerous_char($name);
7792
7793
    if (mkdir($fullPath, api_get_permissions_for_new_directories(), true)) {
7794
        $fp = fopen($fullPath.'/index.html', 'w');
7795
7796
        if ($fp) {
7797
            if (fwrite($fp, '<html><head></head><body></body></html>')) {
7798
                $isCreated = true;
7799
            }
7800
        }
7801
7802
        fclose($fp);
7803
    }
7804
7805
    return $isCreated;
7806
}
7807
7808
/**
7809
 * Sends an HTML email using the phpmailer class (and multipart/alternative to downgrade gracefully)
7810
 * Sender name and email can be specified, if not specified
7811
 * name and email of the platform admin are used
7812
 *
7813
 * @author Bert Vanderkimpen ICT&O UGent
7814
 * @author Yannick Warnier <[email protected]>
7815
 *
7816
 * @param string    name of recipient
7817
 * @param string    email of recipient
7818
 * @param string    email subject
7819
 * @param string    email body
7820
 * @param string    sender name
7821
 * @param string    sender e-mail
7822
 * @param array     extra headers in form $headers = array($name => $value) to allow parsing
7823
 * @param array     data file (path and filename)
7824
 * @param bool      True for attaching a embedded file inside content html (optional)
7825
 * @param array     Additional parameters
7826
 * @return          integer true if mail was sent
7827
 * @see             class.phpmailer.php
7828
 */
7829
function api_mail_html(
7830
    $recipient_name,
7831
    $recipient_email,
7832
    $subject,
7833
    $message,
7834
    $senderName = '',
7835
    $senderEmail = '',
7836
    $extra_headers = array(),
7837
    $data_file = array(),
7838
    $embedded_image = false,
7839
    $additionalParameters = array()
7840
) {
7841
    // Default values
7842
    $notification = new Notification();
7843
    $defaultEmail = $notification->getDefaultPlatformSenderEmail();
7844
    $defaultName = $notification->getDefaultPlatformSenderName();
7845
7846
    // If the parameter is set don't use the admin.
7847
    $senderName = !empty($senderName) ? $senderName : $defaultName;
7848
    $senderEmail = !empty($senderEmail) ? $senderEmail : $defaultEmail;
7849
7850
    $link = isset($additionalParameters['link']) ? $additionalParameters['link'] : '';
7851
7852
    $swiftMessage = \Swift_Message::newInstance()
7853
        ->setSubject($subject)
7854
        ->setFrom($senderEmail, $senderName)
0 ignored issues
show
Bug introduced by
It seems like $senderName defined by !empty($senderName) ? $senderName : $defaultName on line 7847 can also be of type boolean; however, Swift_Mime_SimpleMessage::setFrom() does only seem to accept string|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
7855
        ->setTo($recipient_email, $recipient_name)
7856
        ->setBody(
7857
            Container::getTemplating()->render(
7858
                'ChamiloCoreBundle:default/mail:mail.html.twig',
7859
                array('content' => $message, 'link' => $link)
7860
            ),
7861
            'text/html'
7862
        )/*
7863
         * If you also want to include a plaintext version of the message
7864
        ->addPart(
7865
            $this->renderView(
7866
                'Emails/registration.txt.twig',
7867
                array('name' => $name)
7868
            ),
7869
            'text/plain'
7870
        )
7871
        */
7872
    ;
7873
7874
    if (!empty($additionalParameters)) {
7875
        $plugin = new AppPlugin();
7876
        $smsPlugin = $plugin->getSMSPluginLibrary();
7877
        if ($smsPlugin) {
7878
            $smsPlugin->send($additionalParameters);
7879
        }
7880
    }
7881
7882
    Container::getMailer()->send($swiftMessage);
7883
7884
    return 1;    
7885
}
7886
7887
/**
7888
 * @param string $tool Possible values:
7889
 * GroupManager::GROUP_TOOL_*
7890
 *
7891
 */
7892
function api_protect_course_group($tool, $showHeader = true)
7893
{
7894
    $userId = api_get_user_id();
7895
    $groupId = api_get_group_id();
7896
    $groupInfo = GroupManager::get_group_properties($groupId);
7897
7898
    if (!empty($groupInfo)) {
7899
        $allow = GroupManager::user_has_access(
7900
            $userId,
7901
            $groupInfo['iid'],
7902
            $tool
7903
        );
7904
7905
        if (!$allow) {
7906
            api_not_allowed($showHeader);
7907
        }
7908
    }
7909
}
7910
7911
/**
7912
 * Check if a date is in a date range
7913
 *
7914
 * @param datetime $startDate
7915
 * @param datetime $endDate
7916
 * @param datetime $currentDate
7917
 * @return bool true if date is in rage, false otherwise
7918
 */
7919
function api_is_date_in_date_range($startDate, $endDate, $currentDate = null)
7920
{
7921
    $startDate = strtotime(api_get_local_time($startDate));
7922
    $endDate = strtotime(api_get_local_time($endDate));
7923
    $currentDate = strtotime(api_get_local_time($currentDate));
7924
7925
    if ($currentDate >= $startDate && $currentDate <= $endDate) {
7926
        return true;
7927
    }
7928
7929
    return false;
7930
}
7931
7932
/**
7933
 * Eliminate the duplicates of a multidimensional array by sending the key
7934
 *
7935
 * @param array $array multidimensional array
7936
 * @param int $key key to find to compare
7937
 * @return array
7938
 *
7939
 */
7940
function api_unique_multidim_array($array, $key)
7941
{
7942
    $temp_array = [];
7943
    $i = 0;
7944
    $key_array = [];
7945
7946
    foreach ($array as $val) {
7947
        if (!in_array($val[$key], $key_array)) {
7948
            $key_array[$i] = $val[$key];
7949
            $temp_array[$i] = $val;
7950
        }
7951
        $i++;
7952
    }
7953
    return $temp_array;
7954
}
7955
7956
/**
7957
 * Limit the access to Session Admins wheen the limit_session_admin_role
7958
 * configuration variable is set to true
7959
 */
7960
function api_protect_limit_for_session_admin()
7961
{
7962
    $limitAdmin = api_get_setting('limit_session_admin_role');
7963
    if (api_is_session_admin() && $limitAdmin === 'true') {
7964
        api_not_allowed(true);
7965
    }
7966
}
7967
7968
function api_is_student_view_active()
7969
{
7970
    $studentView = Session::read('studentview');
7971
    return $studentView == 'studentview';
7972
}
7973
7974
/**
7975
 * Adds a file inside the upload/$type/id
7976
 *
7977
 * @param string $type
7978
 * @param array $file
7979
 * @param int $itemId
7980
 * @param string $cropParameters
7981
 * @return array|bool
7982
 */
7983
function api_upload_file($type, $file, $itemId, $cropParameters = '')
7984
{
7985
    $upload = process_uploaded_file($file);
7986
    if ($upload) {
7987
        $name = api_replace_dangerous_char($file['name']);
7988
7989
        // No "dangerous" files
7990
        $name = disable_dangerous_file($name);
7991
7992
        $pathId = '/'.substr((string) $itemId, 0, 1).'/'.$itemId.'/';
7993
        $path = api_get_path(SYS_UPLOAD_PATH).$type.$pathId;
7994
7995
        if (!is_dir($path)) {
7996
            mkdir($path, api_get_permissions_for_new_directories(), true);
7997
        }
7998
7999
        $pathToSave = $path.$name;
8000
8001
        $result = move_uploaded_file($file['tmp_name'], $pathToSave);
8002
        if ($result) {
8003
            if (!empty($cropParameters)) {
8004
                $image = new Image($pathToSave);
8005
                $image->crop($cropParameters);
8006
            }
8007
8008
            return ['path_to_save' => $pathId.$name];
8009
        }
8010
        return false;
8011
    }
8012
}
8013
8014
/**
8015
 * @param string $type
8016
 * @param string $file
8017
 */
8018
function api_remove_uploaded_file($type, $file)
8019
{
8020
    $path = api_get_path(SYS_UPLOAD_PATH).$type.'/'.$file;
8021
    if (file_exists($path)) {
8022
        unlink($path);
8023
    }
8024
}
8025
8026
/**
8027
 * Converts string value to float value
8028
 *
8029
 * 3.141516 => 3.141516
8030
 * 3,141516 => 3.141516
8031
 * @todo WIP
8032
 *
8033
 * @param string $number
8034
 * @return float
8035
 */
8036
function api_float_val($number)
8037
{
8038
    $number = (float) str_replace(',', '.', trim($number));
8039
    return $number;
8040
}
8041
8042
/**
8043
 * Converts float values
8044
 * Example if $decimals = 2
8045
 *
8046
 * 3.141516 => 3.14
8047
 * 3,141516 => 3,14
8048
 *
8049
 * @todo WIP
8050
 *
8051
 * @param string $number number in iso code
8052
 * @param int $decimals
8053
 * @return bool|string
8054
 */
8055
function api_number_format($number, $decimals = 0)
8056
{
8057
    $number = api_float_val($number);
8058
8059
    return number_format($number, $decimals);
8060
}
8061
8062
/**
8063
 * Set location url with a exit break by default
8064
 *
8065
 * @param $url
8066
 * @param bool $exit
8067
 * @return void
8068
 */
8069
function location($url, $exit = true)
8070
{
8071
    header('Location: '.$url);
8072
8073
    if ($exit) {
8074
        exit;
8075
    }
8076
}
8077