Completed
Push — master ( cf2682...200fdf )
by Julito
30:36
created

api.lib.php ➔ api_is_anonymous()   C

Complexity

Conditions 12
Paths 11

Size

Total Lines 35
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 17
nc 11
nop 2
dl 0
loc 35
rs 5.1612
c 0
b 0
f 0

How to fix   Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use ChamiloSession as Session;
5
use Chamilo\CourseBundle\Entity\CItemProperty;
6
use Symfony\Component\Validator\Constraints as Assert;
7
use Chamilo\UserBundle\Entity\User;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, User.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

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

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

Let’s take a look at these examples:

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

// More likely intended return: true/false
return 0 === ($foo & 4);
Loading history...
1096
            isset($course_info['registration_code']) &&
1097
            !empty($course_info['registration_code'])
1098
        ) {
1099
            $is_visible = false;
1100
        }
1101
    }
1102
1103
    // Check session visibility
1104
    $session_id = api_get_session_id();
1105
1106
    if (!empty($session_id)) {
1107
        //$is_allowed_in_course was set in local.inc.php
1108
        if (!$is_allowed_in_course) {
1109
            $is_visible = false;
1110
        }
1111
    }
1112
1113
    if (!$is_visible) {
1114
        api_not_allowed($print_headers);
1115
        return false;
1116
    }
1117
    return true;
1118
}
1119
1120
/**
1121
 * Function used to protect an admin script.
1122
 *
1123
 * The function blocks access when the user has no platform admin rights
1124
 * with an error message printed on default output
1125
 * @param bool Whether to allow session admins as well
1126
 * @param bool Whether to allow HR directors as well
1127
 * @param string An optional message (already passed through get_lang)
1128
 * @return bool True if user is allowed, false otherwise.
1129
 * The function also outputs an error message in case not allowed
1130
 * @author Roan Embrechts (original author)
1131
 */
1132
function api_protect_admin_script($allow_sessions_admins = false, $allow_drh = false, $message = null)
1133
{
1134
    if (!api_is_platform_admin($allow_sessions_admins, $allow_drh)) {
1135
        api_not_allowed(true, $message);
1136
        return false;
1137
    }
1138
    return true;
1139
}
1140
1141
/**
1142
 * Function used to protect a teacher script.
1143
 * The function blocks access when the user has no teacher rights.
1144
 *
1145
 * @author Yoselyn Castillo
1146
 */
1147
function api_protect_teacher_script($allow_sessions_admins = false)
1148
{
1149
    if (!api_is_allowed_to_edit()) {
1150
        api_not_allowed(true);
1151
        return false;
1152
    }
1153
    return true;
1154
}
1155
1156
/**
1157
 * Function used to prevent anonymous users from accessing a script.
1158
 * @param bool|true $printHeaders
1159
 * @author Roan Embrechts
1160
 *
1161
 * @return bool
1162
 */
1163
function api_block_anonymous_users($printHeaders = true)
1164
{
1165
    $user = api_get_user_info();
1166 View Code Duplication
    if (!(isset($user['user_id']) && $user['user_id']) || api_is_anonymous($user['user_id'], true)) {
1167
        api_not_allowed($printHeaders);
1168
        return false;
1169
    }
1170
1171
    return true;
1172
}
1173
1174
/**
1175
 * @return array with the navigator name and version
1176
 */
1177
function api_get_navigator() {
1178
    $navigator = 'Unknown';
1179
    $version = 0;
1180
1181
    if (!isset($_SERVER['HTTP_USER_AGENT'])) {
1182
        return array('name' => 'Unknown', 'version' => '0.0.0');
1183
    }
1184
1185
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') !== false) {
1186
        $navigator = 'Opera';
1187
        list (, $version) = explode('Opera', $_SERVER['HTTP_USER_AGENT']);
1188 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {
1189
        $navigator = 'Internet Explorer';
1190
        list (, $version) = explode('MSIE', $_SERVER['HTTP_USER_AGENT']);
1191
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome') !== false) {
1192
        $navigator = 'Chrome';
1193
        list (, $version) = explode('Chrome', $_SERVER['HTTP_USER_AGENT']);
1194 View Code Duplication
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'safari') !== false) {
1195
        $navigator = 'Safari';
1196
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1197
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Gecko') !== false) {
1198
        $navigator = 'Mozilla';
1199
        list (, $version) = explode('; rv:', $_SERVER['HTTP_USER_AGENT']);
1200 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Netscape') !== false) {
1201
        $navigator = 'Netscape';
1202
        list (, $version) = explode('Netscape', $_SERVER['HTTP_USER_AGENT']);
1203
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Konqueror') !== false) {
1204
        $navigator = 'Konqueror';
1205
        list (, $version) = explode('Konqueror', $_SERVER['HTTP_USER_AGENT']);
1206 View Code Duplication
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'applewebkit') !== false) {
1207
        $navigator = 'AppleWebKit';
1208
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1209
    }
1210
    $version = str_replace('/', '', $version);
1211
    if (strpos($version, '.') === false) {
1212
        $version = number_format(doubleval($version), 1);
1213
    }
1214
    $return = array('name' => $navigator, 'version' => $version);
1215
    return $return;
1216
}
1217
1218
/**
1219
 * @return True if user self registration is allowed, false otherwise.
1220
 */
1221
function api_is_self_registration_allowed()
1222
{
1223
    return isset($GLOBALS['allowSelfReg']) ? $GLOBALS['allowSelfReg'] : false;
1224
}
1225
1226
/**
1227
 * This function returns the id of the user which is stored in the $_user array.
1228
 *
1229
 * example: The function can be used to check if a user is logged in
1230
 *          if (api_get_user_id())
1231
 * @return integer the id of the current user, 0 if is empty
1232
 */
1233
function api_get_user_id()
1234
{
1235
    $userInfo = Session::read('_user');
1236
    if ($userInfo && isset($userInfo['user_id'])) {
1237
        return $userInfo['user_id'];
1238
    }
1239
    return 0;
1240
}
1241
1242
/**
1243
 * Gets the list of courses a specific user is subscribed to
1244
 * @param int       User ID
1245
 * @param boolean   $fetch_session Whether to get session courses or not - NOT YET IMPLEMENTED
1246
 * @return array    Array of courses in the form [0]=>('code'=>xxx,'db'=>xxx,'dir'=>xxx,'status'=>d)
1247
 */
1248
function api_get_user_courses($userid, $fetch_session = true)
1249
{
1250
    // Get out if not integer
1251
    if ($userid != strval(intval($userid))) {
1252
        return array();
1253
    }
1254
1255
    $t_course = Database::get_main_table(TABLE_MAIN_COURSE);
1256
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1257
1258
    $sql = "SELECT cc.id as real_id, cc.code code, cc.directory dir, cu.status status
1259
            FROM    $t_course       cc,
1260
                    $t_course_user   cu
1261
            WHERE
1262
                cc.id = cu.c_id AND
1263
                cu.user_id = '".$userid."' AND
1264
                cu.relation_type<>".COURSE_RELATION_TYPE_RRHH." ";
1265
    $result = Database::query($sql);
1266
    if ($result === false) {
1267
        return array();
1268
    }
1269
1270
    $courses = array();
1271
    while ($row = Database::fetch_array($result)) {
1272
        // we only need the database name of the course
1273
        $courses[] = $row;
1274
    }
1275
1276
    return $courses;
1277
}
1278
1279
/**
1280
 * Formats user information into a standard array
1281
 * This function should be only used inside api_get_user_info()
1282
 *
1283
 * @param array Non-standard user array
1284
 * @param bool $add_password
0 ignored issues
show
Bug introduced by
There is no parameter named $add_password. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

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

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

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

Loading history...
1285
 *
1286
 * @return array Standard user array
1287
 */
1288
function _api_format_user(
1289
    User $user,
1290
    $checkIfUserOnline = false,
1291
    $showPassword = false,
1292
    $loadExtraData = false,
1293
    $loadOnlyVisibleExtraData = false
1294
) {
1295
    $result = array();
1296
1297
    $result['username'] = $user->getUsername();
1298
    $result['firstname'] = $user->getFirstname();
1299
    $result['lastname'] = $user->getLastname();
1300
    $result['firstName'] = $user->getFirstname();
1301
    $result['lastName'] = $user->getLastname();
1302
    $result['complete_name'] = api_get_person_name($result['firstname'], $result['lastname']);
1303
    $result['complete_name_with_username'] = $result['complete_name'];
1304
    if (!empty($result['username'])) {
1305
        $result['complete_name_with_username'] = $result['complete_name'].' ('.$user->getUsername().')';
1306
    }
1307
1308
1309
    $result['phone'] = $user->getPhone();
1310
    $result['address'] = $user->getAddress();
1311
    $result['official_code'] = $user->getOfficialCode();
1312
    $result['status'] = $user->getStatus();
1313
    $result['active'] = $user->getActive();
1314
    $result['auth_source'] = $user->getAuthSource();
1315
    $result['theme'] = $user->getTheme();
1316
    $result['language'] = $user->getLanguage();
1317
    $result['creator_id'] = $user->getCreatorId();
1318
    $result['registration_date'] = $user->getRegistrationDate() ? $user->getRegistrationDate()->format('Y-m-d h:i:s') : '';
1319
    $result['hr_dept_id'] = $user->getHrDeptId();
1320
    $result['expiration_date'] = $user->getExpirationDate() ? $user->getExpirationDate()->format('Y-m-d h:i:s') : '';
1321
    $result['picture_uri'] = $user->getPictureUri();
1322
1323
    if (api_get_setting('extended_profile') === 'true') {
1324
        $result['competences'] = $user->getCompetences();
1325
        $result['diplomas']  = $user->getDiplomas();
1326
        $result['teach'] = $user->getTeach();
1327
        $result['openarea'] = $user->getOpenarea();
1328
    }
1329
1330
    $result['mail'] = $user->getEmail();
1331
    $result['email'] = $user->getEmail();
1332
1333
    $user_id = $user->getId();
1334
    // Maintain the user_id index for backwards compatibility
1335
    $result['user_id'] = $result['id'] = $user_id;
1336
    $result['last_login'] = $user->getLastLogin() ? $user->getLastLogin()->format('Y-m-d h:i:s') : '';
1337
1338
    // Getting user avatar.
1339
    $originalFile = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_ORIGINAL, null, $result);
1340
    $smallFile = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_SMALL, null, $result);
1341
    $mediumFile = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_MEDIUM, null, $result);
1342
1343
    $result['avatar'] = $originalFile;
1344
    $avatarString = explode('?', $originalFile);
1345
    $result['avatar_no_query'] = reset($avatarString);
1346
    $result['avatar_small'] = $smallFile;
1347
    $result['avatar_medium'] = $mediumFile;
1348
1349
    if ($showPassword) {
1350
        $result['password'] = $user->getPassword();
1351
    }
1352
1353
    $result['profile_completed'] = $user->isProfileCompleted();
1354
    $result['profile_url'] = api_get_path(WEB_CODE_PATH).'social/profile.php?u='.$user_id;
1355
1356
    if ($checkIfUserOnline) {
1357
        $use_status_in_platform = UserManager::user_is_online($user_id);
1358
1359
        $result['user_is_online'] = $use_status_in_platform;
1360
        $user_online_in_chat = 0;
1361
1362
        if ($use_status_in_platform) {
1363
            $user_status = UserManager::get_extra_user_data_by_field(
1364
                $user_id,
1365
                'user_chat_status',
1366
                false,
1367
                true
1368
            );
1369
            if (intval($user_status['user_chat_status']) == 1) {
1370
                $user_online_in_chat = 1;
1371
            }
1372
        }
1373
        $result['user_is_online_in_chat'] = $user_online_in_chat;
1374
    }
1375
1376
    if ($loadExtraData) {
1377
        $fieldValue = new ExtraFieldValue('user');
1378
1379
        $result['extra'] = $fieldValue->getAllValuesForAnItem(
1380
            $user_id,
1381
            $loadOnlyVisibleExtraData
1382
        );
1383
    }
1384
1385
    return $result;
1386
}
1387
1388
/**
1389
 * Finds all the information about a user.
1390
 * If no parameter is passed you find all the information about the current user.
1391
 * @param int  $user_id
1392
 * @param bool $checkIfUserOnline
1393
 * @param bool $showPassword
1394
 * @param bool $loadExtraData
1395
 * @param bool $loadOnlyVisibleExtraData Get the user extra fields that are visible
1396
 * @return array $user_info user_id, lastname, firstname, username, email, etc
1397
 * @author Patrick Cool <[email protected]>
1398
 * @author Julio Montoya
1399
 * @version 21 September 2004
1400
 */
1401
function api_get_user_info(
1402
    $user_id = 0,
1403
    $checkIfUserOnline = false,
1404
    $showPassword = false,
1405
    $loadExtraData = false,
1406
    $loadOnlyVisibleExtraData = false
1407
) {
1408
    if (empty($user_id)) {
1409
        $storage = Container::getTokenStorage();
1410
        $token = $storage->getToken();
1411
        $user = $token->getUser();
1412
        if ($user instanceof User) {
1413
            return _api_format_user(
1414
                $token->getUser(),
1415
                $checkIfUserOnline,
1416
                $showPassword,
1417
                $loadExtraData,
1418
                $loadOnlyVisibleExtraData
1419
            );
1420
        }
1421
1422
        return false;
1423
    }
1424
1425
    $user = UserManager::getManager()->find($user_id);
1426
1427
    if ($user) {
1428
        return _api_format_user(
1429
            $user,
1430
            $checkIfUserOnline,
1431
            $showPassword,
1432
            $loadExtraData,
1433
            $loadOnlyVisibleExtraData
1434
        );
1435
    }
1436
    return false;
1437
}
1438
1439
/**
1440
 * @param int $userId
1441
 * @return User
1442
 */
1443
function api_get_user_entity($userId)
1444
{
1445
    /** @var \Chamilo\UserBundle\Repository\UserRepository $repo */
1446
    $repo = Database::getManager()->getRepository('ChamiloUserBundle:User');
1447
1448
    return $repo->find($userId);
1449
}
1450
1451
/**
1452
 * @param int $courseId
1453
 *
1454
 * @return Course
1455
 */
1456
function api_get_user_course_entity($courseId = 0)
1457
{
1458
    if (empty($courseId)) {
1459
        $courseId = api_get_course_int_id();
1460
    }
1461
    return CourseManager::getManager()->find($courseId);
1462
}
1463
1464
/**
1465
 * Finds all the information about a user from username instead of user id
1466
 * @param string $username
1467
 * @return array $user_info array user_id, lastname, firstname, username, email
1468
 * @author Yannick Warnier <[email protected]>
1469
 */
1470 View Code Duplication
function api_get_user_info_from_username($username = '')
1471
{
1472
    if (empty($username)) {
1473
        return false;
1474
    }
1475
    $username = trim($username);
1476
1477
1478
    $user = UserManager::getManager()->findUserByUsername($username);
1479
    if ($user) {
1480
        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...
1481
    }
1482
    return false;
1483
}
1484
1485
/**
1486
 * Get first user with an email
1487
 * @param string $email
1488
 * @return array|bool
1489
 */
1490 View Code Duplication
function api_get_user_info_from_email($email)
1491
{
1492
    if (empty($email)) {
1493
        return false;
1494
    }
1495
1496
    $user = UserManager::getManager()->findUserByEmail($email);
1497
    if ($user) {
1498
        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...
1499
    }
1500
1501
    return false;
1502
}
1503
1504
/**
1505
 * @return string
1506
 */
1507
function api_get_course_id()
1508
{
1509
    return Session::read('_cid', null);
1510
}
1511
1512
/**
1513
 * Returns the current course id (integer)
1514
 * @param   string  $code   Optional course code
1515
 * @return int
1516
 */
1517
function api_get_course_int_id($code = null)
1518
{
1519 View Code Duplication
    if (!empty($code)) {
1520
        $code = Database::escape_string($code);
1521
        $row = Database::select(
1522
            'id',
1523
            Database::get_main_table(TABLE_MAIN_COURSE),
1524
            array('where'=> array('code = ?' => array($code))),
1525
            'first'
1526
        );
1527
1528
        if (is_array($row) && isset($row['id'])) {
1529
            return $row['id'];
1530
        } else {
1531
            return false;
1532
        }
1533
    }
1534
    return Session::read('_real_cid', 0);
1535
}
1536
1537
/**
1538
 * Returns the current course directory
1539
 *
1540
 * This function relies on api_get_course_info()
1541
 * @param string    The course code - optional (takes it from session if not given)
1542
 * @return string   The directory where the course is located inside the Chamilo "courses" directory
1543
 * @author Yannick Warnier <[email protected]>
1544
 */
1545
function api_get_course_path($course_code = null)
1546
{
1547
    $info = !empty($course_code) ? api_get_course_info($course_code) : api_get_course_info();
1548
    return $info['path'];
1549
}
1550
1551
/**
1552
 * Gets a course setting from the current course_setting table. Try always using integer values.
1553
 * @param string    The name of the setting we want from the table
1554
 * @param string    Optional: course code
1555
 * @param string $setting_name
1556
 * @return mixed    The value of that setting in that table. Return -1 if not found.
1557
 */
1558
function api_get_course_setting($setting_name, $course_code = null)
1559
{
1560
    $course_info = api_get_course_info($course_code);
1561
    $table = Database::get_course_table(TABLE_COURSE_SETTING);
1562
    $setting_name = Database::escape_string($setting_name);
1563
    if (!empty($course_info['real_id']) && !empty($setting_name)) {
1564
        $sql = "SELECT value FROM $table
1565
                WHERE c_id = {$course_info['real_id']} AND variable = '$setting_name'";
1566
        $res = Database::query($sql);
1567
        if (Database::num_rows($res) > 0) {
1568
            $row = Database::fetch_array($res);
1569
            return $row['value'];
1570
        }
1571
    }
1572
    return -1;
1573
}
1574
1575
/**
1576
 * Gets an anonymous user ID
1577
 *
1578
 * For some tools that need tracking, like the learnpath tool, it is necessary
1579
 * to have a usable user-id to enable some kind of tracking, even if not
1580
 * perfect. An anonymous ID is taken from the users table by looking for a
1581
 * status of "6" (anonymous).
1582
 * @return int  User ID of the anonymous user, or O if no anonymous user found
1583
 */
1584 View Code Duplication
function api_get_anonymous_id()
1585
{
1586
    $table = Database::get_main_table(TABLE_MAIN_USER);
1587
    $sql = "SELECT user_id FROM $table WHERE status = ".ANONYMOUS;
1588
    $res = Database::query($sql);
1589
    if (Database::num_rows($res) > 0) {
1590
        $row = Database::fetch_array($res);
1591
        return $row['user_id'];
1592
    }
1593
1594
    // No anonymous user was found.
1595
    return 0;
1596
}
1597
1598
/**
1599
 * @param string $courseCode
1600
 * @param int $sessionId
1601
 * @param int $groupId
1602
 * @return string
1603
 */
1604
function api_get_cidreq_params($courseCode, $sessionId = 0, $groupId = 0)
1605
{
1606
    $courseCode = !empty($courseCode) ? htmlspecialchars($courseCode) : '';
1607
    $sessionId = !empty($sessionId) ? (int) $sessionId : 0;
1608
    $groupId = !empty($groupId) ? (int) $groupId : 0;
1609
1610
    $url = 'cidReq='.$courseCode;
1611
    $url .= '&id_session='.$sessionId;
1612
    $url .= '&gidReq='.$groupId;
1613
1614
    return $url;
1615
}
1616
1617
/**
1618
 * Returns the current course url part including session, group, and gradebook params
1619
 *
1620
 * @param bool $addSessionId
1621
 * @param bool $addGroupId
1622
 * @param string $origin
1623
 *
1624
 * @return  string  Course & session references to add to a URL
1625
 *
1626
 */
1627
function api_get_cidreq($addSessionId = true, $addGroupId = true, $origin = '')
1628
{
1629
    $courseCode = api_get_course_id();
1630
    $url = empty($courseCode) ? '' : 'cidReq='.htmlspecialchars($courseCode);
1631
    $origin = empty($origin) ? api_get_origin() : Security::remove_XSS($origin);
1632
1633
    if ($addSessionId) {
1634
        if (!empty($url)) {
1635
            $url .= api_get_session_id() == 0 ? '&id_session=0' : '&id_session='.api_get_session_id();
1636
        }
1637
    }
1638
1639
    if ($addGroupId) {
1640
        if (!empty($url)) {
1641
            $url .= api_get_group_id() == 0 ? '&gidReq=0' : '&gidReq='.api_get_group_id();
1642
        }
1643
    }
1644
1645
    if (!empty($url)) {
1646
        $url .= '&gradebook='.intval(api_is_in_gradebook());
1647
        $url .= '&origin='.$origin;
1648
    }
1649
1650
    return $url;
1651
}
1652
1653
/**
1654
 * get gradebook in session
1655
 */
1656
function api_is_in_gradebook()
1657
{
1658
    return Session::read('in_gradebook', false);
1659
}
1660
1661
/**
1662
 * set gradebook session
1663
 */
1664
function api_set_in_gradebook()
1665
{
1666
    Session::write('in_gradebook', true);
1667
}
1668
1669
/**
1670
 * remove gradebook session
1671
 */
1672
function api_remove_in_gradebook()
1673
{
1674
    Session::erase('in_gradebook');
1675
}
1676
1677
/**
1678
 * Returns the current course info array see api_format_course_array()
1679
 * If the course_code is given, the returned array gives info about that
1680
 * particular course, if none given it gets the course info from the session.
1681
 *
1682
 * @param string $course_code
1683
 * @param bool $strict
1684
 *
1685
 * @return array
1686
 */
1687
function api_get_course_info($course_code = null, $strict = false)
1688
{
1689
    if (!empty($course_code)) {
1690
        $course_code = Database::escape_string($course_code);
1691
        $courseId = api_get_course_int_id($course_code);
1692
1693
        if (empty($courseId)) {
1694
            return array();
1695
        }
1696
1697
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1698
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1699
        $sql = "SELECT
1700
                    course.*,
1701
                    course_category.code faCode,
1702
                    course_category.name faName
1703
                FROM $course_table
1704
                LEFT JOIN $course_cat_table
1705
                ON course.category_code = course_category.code
1706
                WHERE course.id = $courseId";
1707
        $result = Database::query($sql);
1708
        $courseInfo = array();
1709
        if (Database::num_rows($result) > 0) {
1710
            $data = Database::fetch_array($result);
1711
            $courseInfo = api_format_course_array($data);
1712
        }
1713
1714
        return $courseInfo;
1715
    }
1716
1717
    $_course = Session::read('_course');
1718
    if ($_course == '-1') {
1719
        $_course = array();
1720
    }
1721
1722
    return $_course;
1723
}
1724
1725
/**
1726
 * Returns the current course info array.
1727
1728
 * Now if the course_code is given, the returned array gives info about that
1729
 * particular course, not specially the current one.
1730
 * @param int $id Numeric ID of the course
1731
 * @return array The course info as an array formatted by api_format_course_array, including category.name
1732
 */
1733
function api_get_course_info_by_id($id = null)
1734
{
1735
    if (!empty($id)) {
1736
        $id = intval($id);
1737
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1738
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1739
        $sql = "SELECT
1740
                    course.*,
1741
                    course_category.code faCode,
1742
                    course_category.name faName
1743
                FROM $course_table
1744
                LEFT JOIN $course_cat_table
1745
                ON course.category_code =  course_category.code
1746
                WHERE course.id = $id";
1747
        $result = Database::query($sql);
1748
        $_course = array();
1749
        if (Database::num_rows($result) > 0) {
1750
            $course_data = Database::fetch_array($result);
1751
            $_course = api_format_course_array($course_data);
1752
        }
1753
        return $_course;
1754
    }
1755
1756
    global $_course;
1757
    if ($_course == '-1') $_course = array();
1758
    return $_course;
1759
}
1760
1761
/**
1762
 * Reformat the course array (output by api_get_course_info()) in order, mostly,
1763
 * to switch from 'code' to 'id' in the array. This is a legacy feature and is
1764
 * now possibly causing massive confusion as a new "id" field has been added to
1765
 * the course table in 1.9.0.
1766
 * @param $course_data
1767
 * @return array
1768
 * @todo eradicate the false "id"=code field of the $_course array and use the int id
1769
 */
1770
function api_format_course_array($course_data)
1771
{
1772
    if (empty($course_data)) {
1773
        return array();
1774
    }
1775
1776
    $_course = array();
1777
    $_course['id'] = $course_data['code'];
1778
    $_course['real_id'] = $course_data['id'];
1779
1780
    // Added
1781
    $_course['code'] = $course_data['code'];
1782
    $_course['name'] = $course_data['title'];
1783
    $_course['title'] = $course_data['title'];
1784
    $_course['official_code'] = $course_data['visual_code'];
1785
    $_course['visual_code'] = $course_data['visual_code'];
1786
    $_course['sysCode'] = $course_data['code'];
1787
    $_course['path'] = $course_data['directory']; // Use as key in path.
1788
    $_course['directory'] = $course_data['directory'];
1789
    $_course['creation_date'] = $course_data['creation_date'];
1790
    $_course['titular'] = $course_data['tutor_name'];
1791
    $_course['language'] = $course_data['course_language'];
1792
    $_course['extLink']['url'] = $course_data['department_url'];
1793
    $_course['extLink']['name'] = $course_data['department_name'];
1794
    $_course['categoryCode'] = $course_data['faCode'];
1795
    $_course['categoryName'] = $course_data['faName'];
1796
    $_course['visibility'] = $course_data['visibility'];
1797
    $_course['subscribe_allowed'] = $course_data['subscribe'];
1798
    $_course['subscribe'] = $course_data['subscribe'];
1799
    $_course['unsubscribe'] = $course_data['unsubscribe'];
1800
    $_course['course_language'] = $course_data['course_language'];
1801
    $_course['activate_legal'] = isset($course_data['activate_legal']) ? $course_data['activate_legal'] : false;
1802
    $_course['legal'] = $course_data['legal'];
1803
    $_course['show_score'] = $course_data['show_score']; //used in the work tool
1804
    $_course['department_name'] = $course_data['department_name'];
1805
    $_course['department_url'] = $course_data['department_url'];
1806
1807
    // Course password
1808
    $_course['registration_code'] = !empty($course_data['registration_code']) ? sha1($course_data['registration_code']) : null;
1809
    $_course['disk_quota'] = $course_data['disk_quota'];
1810
    $_course['course_public_url'] = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/index.php';
1811
1812
    if (array_key_exists('add_teachers_to_sessions_courses', $course_data)) {
1813
        $_course['add_teachers_to_sessions_courses'] = $course_data['add_teachers_to_sessions_courses'];
1814
    }
1815
1816
    if (file_exists(api_get_path(SYS_COURSE_PATH).$course_data['directory'].'/course-pic85x85.png')) {
1817
        $url_image = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/course-pic85x85.png';
1818
    } else {
1819
        $url_image = Display::return_icon('course.png', null, null, ICON_SIZE_BIG, null, true, false);
1820
    }
1821
    $_course['course_image'] = $url_image;
1822
1823
    if (file_exists(api_get_path(SYS_COURSE_PATH).$course_data['directory'].'/course-pic.png')) {
1824
        $url_image = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/course-pic.png';
1825
    } else {
1826
        $url_image = Display::returnIconPath('session_default.png');
1827
    }
1828
    $_course['course_image_large'] = $url_image;
1829
1830
    $_course['extra_fields'] = isset($course_data['extra_fields']) ? $course_data['extra_fields'] : array();
1831
    $_course['settings'] = isset($course_data['settings']) ? $course_data['settings'] : array();
1832
    $_course['teacher_list'] = isset($course_data['teacher_list']) ? $course_data['teacher_list'] : array();
1833
    $_course['teacher_list_formatted'] = isset($course_data['teacher_list_formatted']) ? $course_data['teacher_list_formatted'] : array();
1834
1835
    return $_course;
1836
}
1837
1838
/**
1839
 * Add a parameter to the existing URL. If this parameter already exists,
1840
 * just replace it with the new value
1841
 * @param   string  The URL
1842
 * @param   string  param=value string
1843
 * @param   boolean Whether to filter XSS or not
1844
 * @return  string  The URL with the added parameter
1845
 */
1846
function api_add_url_param($url, $param, $filter_xss = true) {
1847
    if (empty($param)) {
1848
        return $url;
1849
    }
1850
    if (strpos($url, '?') !== false) {
1851
        if ($param[0] != '&') {
1852
            $param = '&'.$param;
1853
        }
1854
        list (, $query_string) = explode('?', $url);
1855
        $param_list1 = explode('&', $param);
1856
        $param_list2 = explode('&', $query_string);
1857
        $param_list1_keys = $param_list1_vals = array();
1858
        foreach ($param_list1 as $key => $enreg) {
1859
            list ($param_list1_keys[$key], $param_list1_vals[$key]) = explode('=', $enreg);
1860
        }
1861
        $param_list1 = array ('keys' => $param_list1_keys, 'vals' => $param_list1_vals);
1862
        foreach ($param_list2 as $enreg) {
1863
            $enreg = explode('=', $enreg);
1864
            $key = array_search($enreg[0], $param_list1['keys']);
1865
            if (!is_null($key) && !is_bool($key)) {
1866
                $url = str_replace($enreg[0].'='.$enreg[1], $enreg[0].'='.$param_list1['vals'][$key], $url);
1867
                $param = str_replace('&'.$enreg[0].'='.$param_list1['vals'][$key], '', $param);
1868
            }
1869
        }
1870
        $url .= $param;
1871
    } else {
1872
        $url = $url.'?'.$param;
1873
    }
1874
    if ($filter_xss === true) {
1875
        $url = Security::remove_XSS(urldecode($url));
1876
    }
1877
    return $url;
1878
}
1879
1880
/**
1881
 * Returns a difficult to guess password.
1882
 * @param int $length the length of the password
1883
 * @return string the generated password
1884
 */
1885
function api_generate_password($length = 8)
1886
{
1887
    $characters = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
1888
    $numbers = '23456789';
1889
1890
    if ($length < 2) {
1891
        $length = 2;
1892
    }
1893
    $password = '';
1894
    for ($i = 0; $i < $length; $i ++) {
1895
        $password .= $characters[rand() % strlen($characters)];
1896
    }
1897
1898
    // At least 2 digits
1899
    for ($i = 0; $i < 2; $i ++) {
1900
        $password .= $numbers[rand() % strlen($numbers)];
1901
    }
1902
1903
    return $password;
1904
}
1905
1906
/**
1907
 * Checks a password to see wether it is OK to use.
1908
 * @param string $password
1909
 * @return boolean if the password is acceptable, false otherwise
1910
 * Notes about what a password "OK to use" is:
1911
 * 1. The password should be at least 5 characters long.
1912
 * 2. Only English letters (uppercase or lowercase, it doesn't matter) and digits are allowed.
1913
 * 3. The password should contain at least 3 letters.
1914
 * 4. It should contain at least 2 digits.
1915
 * 5. It should not contain 3 or more consequent (according to ASCII table) characters.
1916
 */
1917
function api_check_password($password) {
1918
    $password_length = api_strlen($password);
1919
    if ($password_length < 5) {
1920
        return false;
1921
    }
1922
    $password = api_strtolower($password);
1923
    $letters = 0;
1924
    $digits = 0;
1925
    $consequent_characters = 0;
1926
    $previous_character_code = 0;
1927
    for ($i = 0; $i < $password_length; $i ++) {
1928
        $current_character_code = api_ord(api_substr($password, $i, 1));
0 ignored issues
show
Security Bug introduced by
It seems like api_substr($password, $i, 1) targeting api_substr() can also be of type false; however, api_ord() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
1929
        if ($i && abs($current_character_code - $previous_character_code) <= 1) {
1930
            $consequent_characters ++;
1931
            if ($consequent_characters == 3) {
1932
                return false;
1933
            }
1934
        } else {
1935
            $consequent_characters = 1;
1936
        }
1937
        if ($current_character_code >= 97 && $current_character_code <= 122) {
1938
            $letters ++;
1939
        } elseif ($current_character_code >= 48 && $current_character_code <= 57) {
1940
            $digits ++;
1941
        } else {
1942
            return false;
1943
        }
1944
        $previous_character_code = $current_character_code;
1945
    }
1946
    return ($letters >= 3 && $digits >= 2);
1947
}
1948
1949
/**
1950
 * Clears the user ID from the session if it was the anonymous user. Generally
1951
 * used on out-of-tools pages to remove a user ID that could otherwise be used
1952
 * in the wrong context.
1953
 * This function is to be used in conjunction with the api_set_anonymous()
1954
 * function to simulate the user existence in case of an anonymous visit.
1955
 * @param bool      database check switch - passed to api_is_anonymous()
1956
 * @return bool     true if succesfully unregistered, false if not anonymous.
1957
 */
1958
function api_clear_anonymous($db_check = false)
1959
{
1960
    global $_user;
1961
    if (api_is_anonymous($_user['user_id'], $db_check)) {
1962
        unset($_user['user_id']);
1963
        Session::erase('_uid');
1964
        return true;
1965
    }
1966
    return false;
1967
}
1968
1969
/**
1970
 * Returns the status string corresponding to the status code
1971
 * @author Noel Dieschburg
1972
 * @param the int status code
1973
 */
1974
function get_status_from_code($status_code)
1975
{
1976
    switch ($status_code) {
1977
        case STUDENT:
1978
            return get_lang('Student', '');
1979
        case TEACHER:
1980
            return get_lang('Teacher', '');
1981
        case COURSEMANAGER:
1982
            return get_lang('Manager', '');
1983
        case SESSIONADMIN:
1984
            return get_lang('SessionsAdmin', '');
1985
        case DRH:
1986
            return get_lang('Drh', '');
1987
    }
1988
}
1989
1990
/**
1991
 * Sets the current user as anonymous if it hasn't been identified yet. This
1992
 * function should be used inside a tool only. The function api_clear_anonymous()
1993
 * acts in the opposite direction by clearing the anonymous user's data every
1994
 * time we get on a course homepage or on a neutral page (index, admin, my space)
1995
 * @return bool     true if set user as anonymous, false if user was already logged in or anonymous id could not be found
1996
 */
1997
function api_set_anonymous() {
1998
    $_user = Session::read('_user');
1999
2000
    if (!empty($_user['user_id'])) {
2001
        return false;
2002
    }
2003
    $user_id = api_get_anonymous_id();
2004
    if ($user_id == 0) {
2005
        return false;
2006
    }
2007
    Session::erase('_user');
2008
    $_user['user_id'] = $user_id;
2009
    $_user['is_anonymous'] = true;
2010
    $GLOBALS['_user'] = $_user;
2011
    Session::write('_user', $_user);
2012
    return true;
2013
}
2014
2015
/**
2016
 * Gets the current Chamilo (not PHP/cookie) session ID
2017
 * @return  int     O if no active session, the session ID otherwise
2018
 */
2019
function api_get_session_id()
2020
{
2021
    return Session::read('id_session', 0);
2022
}
2023
2024
/**
2025
 * Gets the current Chamilo (not social network) group ID
2026
 * @return  int     O if no active session, the session ID otherwise
2027
 */
2028
function api_get_group_id()
2029
{
2030
    return Session::read('_gid', 0);
2031
}
2032
2033
/**
2034
 * Gets the current or given session name
2035
 * @param   int     Session ID (optional)
2036
 * @return  string  The session name, or null if unfound
2037
 */
2038
function api_get_session_name($session_id = 0)
2039
{
2040
    if (empty($session_id)) {
2041
        $session_id = api_get_session_id();
2042
        if (empty($session_id)) {
2043
            return null;
2044
        }
2045
    }
2046
    $t = Database::get_main_table(TABLE_MAIN_SESSION);
2047
    $s = "SELECT name FROM $t WHERE id = ".(int)$session_id;
2048
    $r = Database::query($s);
2049
    $c = Database::num_rows($r);
2050
    if ($c > 0) {
2051
        //technically, there can be only one, but anyway we take the first
2052
        $rec = Database::fetch_array($r);
2053
        return $rec['name'];
2054
    }
2055
    return null;
2056
}
2057
2058
/**
2059
 * Gets the session info by id
2060
 * @param int       Session ID
2061
 * @return array    information of the session
2062
 */
2063
function api_get_session_info($session_id)
2064
{
2065
    return SessionManager::fetch($session_id);
2066
}
2067
2068
/**
2069
 * Gets the session visibility by session id
2070
 * @param int $session_id
2071
 * @param int $courseId
2072
 * @param bool $ignore_visibility_for_admins
2073
 * @return int
2074
 *  0 = session still available,
2075
 *  SESSION_VISIBLE_READ_ONLY = 1,
2076
 *  SESSION_VISIBLE = 2,
2077
 *  SESSION_INVISIBLE = 3
2078
 */
2079
function api_get_session_visibility(
2080
    $session_id,
2081
    $courseId = null,
2082
    $ignore_visibility_for_admins = true
2083
) {
2084
    // Means that the session is still available.
2085
    $visibility = 0;
2086
2087
    if (api_is_platform_admin()) {
2088
        if ($ignore_visibility_for_admins) {
2089
            return SESSION_AVAILABLE;
2090
        }
2091
    }
2092
2093
    $now = time();
2094
    if (!empty($session_id)) {
2095
        $session_id = intval($session_id);
2096
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2097
2098
        $sql = "SELECT * FROM $tbl_session
2099
                WHERE id = $session_id ";
2100
2101
        $result = Database::query($sql);
2102
2103
        if (Database::num_rows($result) > 0) {
2104
            $row = Database::fetch_array($result, 'ASSOC');
2105
            $visibility = $original_visibility = $row['visibility'];
2106
2107
            // I don't care the session visibility.
2108
            if (empty($row['access_start_date']) && empty($row['access_end_date'])) {
2109
                // Session duration per student.
2110
                if (isset($row['duration']) && !empty($row['duration'])) {
2111
                    $duration = $row['duration'] * 24 * 60 * 60;
2112
2113
                    $courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser(
2114
                        $session_id,
2115
                        api_get_user_id()
2116
                    );
2117
2118
                    // If there is a session duration but there is no previous
2119
                    // access by the user, then the session is still available
2120
                    if (count($courseAccess) == 0) {
2121
                        return SESSION_AVAILABLE;
2122
                    }
2123
2124
                    $currentTime = time();
2125
                    $firstAccess = 0;
2126
                    if (isset($courseAccess['login_course_date'])) {
2127
                        $firstAccess = api_strtotime(
2128
                            $courseAccess['login_course_date'],
2129
                            'UTC'
2130
                        );
2131
                    }
2132
                    $userDurationData = SessionManager::getUserSession(
2133
                        api_get_user_id(),
2134
                        $session_id
2135
                    );
2136
                    $userDuration = 0;
2137
                    if (isset($userDurationData['duration'])) {
2138
                        $userDuration = intval($userDurationData['duration']) * 24 * 60 * 60;
2139
                    }
2140
2141
                    $totalDuration = $firstAccess + $duration + $userDuration;
2142
                    if ($totalDuration > $currentTime) {
2143
                        return SESSION_AVAILABLE;
2144
                    } else {
2145
                        return SESSION_INVISIBLE;
2146
                    }
2147
                }
2148
2149
                return SESSION_AVAILABLE;
2150
            } else {
2151
                // If start date was set.
2152
                if (!empty($row['access_start_date'])) {
2153
                    if ($now > api_strtotime($row['access_start_date'], 'UTC')) {
2154
                        $visibility = SESSION_AVAILABLE;
2155
                    } else {
2156
                        $visibility = SESSION_INVISIBLE;
2157
                    }
2158
                }
2159
2160
                // If the end date was set.
2161
                if (!empty($row['access_end_date'])) {
2162
                    // Only if date_start said that it was ok
2163
                    if ($visibility === SESSION_AVAILABLE) {
2164
                        if ($now < api_strtotime($row['access_end_date'], 'UTC')) {
2165
                            // Date still available
2166
                            $visibility = SESSION_AVAILABLE;
2167
                        } else {
2168
                            // Session ends
2169
                            $visibility = $row['visibility'];
2170
                        }
2171
                    }
2172
                }
2173
            }
2174
2175
            /* If I'm a coach the visibility can change in my favor depending in
2176
             the coach dates */
2177
            $isCoach = api_is_coach($session_id, $courseId);
2178
2179
            if ($isCoach) {
2180
                // Test end date.
2181
                if (!empty($row['coach_access_end_date'])) {
2182
                    $endDateCoach = api_strtotime($row['coach_access_end_date'], 'UTC');
2183
2184
                    if ($endDateCoach >= $now) {
2185
                        $visibility = SESSION_AVAILABLE;
2186
                    } else {
2187
                        $visibility = SESSION_INVISIBLE;
2188
                    }
2189
                }
2190
2191
                // Test start date.
2192
                if (!empty($row['coach_access_start_date'])) {
2193
                    $start = api_strtotime($row['coach_access_start_date'], 'UTC');
2194
                    if ($start < $now) {
2195
                        $visibility = SESSION_AVAILABLE;
2196
                    } else {
2197
                        $visibility = SESSION_INVISIBLE;
2198
                    }
2199
                }
2200
            }
2201
        } else {
2202
            $visibility = SESSION_INVISIBLE;
2203
        }
2204
    }
2205
    return $visibility;
2206
}
2207
2208
/**
2209
 * This function returns a (star) session icon if the session is not null and
2210
 * the user is not a student
2211
 * @param int   $session_id
2212
 * @param int   $status_id User status id - if 5 (student), will return empty
2213
 * @return string   Session icon
2214
 */
2215
function api_get_session_image($session_id, $status_id)
2216
{
2217
    $session_id = (int)$session_id;
2218
    $session_img = '';
2219
    if ((int)$status_id != 5) { //check whether is not a student
2220
        if ($session_id > 0) {
2221
            $session_img = "&nbsp;&nbsp;".Display::return_icon(
2222
                'star.png',
2223
                get_lang('SessionSpecificResource'),
2224
                array('align' => 'absmiddle'),
2225
                ICON_SIZE_SMALL
2226
            );
2227
        }
2228
    }
2229
    return $session_img;
2230
}
2231
2232
/**
2233
 * This function add an additional condition according to the session of the course
2234
 * @param int       $session_id session id
2235
 * @param bool      $and optional, true if more than one condition false if the only condition in the query
2236
 * @param bool      $with_base_content optional, true to accept content with session=0 as well, false for strict session condition
2237
 * @return string   condition of the session
2238
 */
2239
function api_get_session_condition(
2240
    $session_id,
2241
    $and = true,
2242
    $with_base_content = false,
2243
    $session_field = "session_id"
2244
) {
2245
    $session_id = intval($session_id);
2246
2247
    if (empty($session_field)) {
2248
        $session_field = "session_id";
2249
    }
2250
    // Condition to show resources by session
2251
    $condition_add = $and ? " AND " : " WHERE ";
2252
2253
    if ($with_base_content) {
2254
        $condition_session = $condition_add." ( $session_field = $session_id OR $session_field = 0 OR $session_field IS NULL) ";
2255
    } else {
2256
        if (empty($session_id)) {
2257
            $condition_session = $condition_add." ($session_field = $session_id OR $session_field IS NULL)";
2258
        } else {
2259
            $condition_session = $condition_add." $session_field = $session_id ";
2260
        }
2261
    }
2262
    return $condition_session;
2263
}
2264
2265
/**
2266
 * @param string $variable
2267
 * @param string $option
2268
 * @return bool
2269
 */
2270
function api_get_setting_in_list($variable, $option)
2271
{
2272
    $value = api_get_setting($variable);
2273
2274
    return in_array($option, $value);
2275
}
2276
2277
2278
/**
2279
 * Returns the value of a setting from the web-adjustable admin config settings.
2280
 *
2281
 * WARNING true/false are stored as string, so when comparing you need to check e.g.
2282
 * if (api_get_setting('course.show_navigation_menu') == 'true') //CORRECT
2283
 * instead of
2284
 * if (api_get_setting('course.show_navigation_menu') == true) //INCORRECT
2285
 * @param string    $variable The variable name
2286
 * @return string
2287
 *
2288
 * @author Julio Montoya
2289
 */
2290
function api_get_setting($variable, $subVariable = '')
2291
{
2292
    $variable = trim($variable);
2293
2294
    switch ($variable) {
2295 View Code Duplication
        case 'header_extra_content':
2296
            $filename = api_get_path(SYS_PATH).api_get_home_path().'header_extra_content.txt';
2297
            if (file_exists($filename)) {
2298
                $value = file_get_contents($filename);
2299
                    return $value ;
2300
            } else {
2301
                return '';
2302
            }
2303
            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...
2304 View Code Duplication
        case 'footer_extra_content':
2305
            $filename = api_get_path(SYS_PATH).api_get_home_path().'footer_extra_content.txt';
2306
            if (file_exists($filename)) {
2307
                $value = file_get_contents($filename);
2308
                return $value ;
2309
            } else {
2310
                return '';
2311
            }
2312
            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...
2313
        case 'server_type':
2314
            $test = ['dev', 'test'];
2315
            $environment = Container::getEnvironment();
2316
            if (in_array($environment, $test)) {
2317
                return 'test';
2318
            }
2319
            return 'prod';
2320
        case 'stylesheets':
2321
            $variable = 'platform.theme';
2322
            break;
2323
        // deprecated settings
2324
        case 'openid_authentication':
2325
        case 'sso_authentication':
2326
        case 'service_ppt2lp':
2327
        case 'add_cas_login_button_cas_button_label':
2328
        case 'add_cas_login_button_cas_button_comment':
2329
        case 'add_cas_login_button_cas_image_url':
2330
        case 'add_cas_logout_button_cas_logout_label':
2331
        case 'add_cas_logout_button_cas_logout_comment':
2332
        case 'add_cas_logout_button_cas_logout_image_url':
2333
        case 'add_facebook_login_button_facebook_button_url':
2334
        case 'add_shibboleth_login_button_shibboleth_button_label':
2335
        case 'add_shibboleth_login_button_shibboleth_button_comment':
2336
        case 'add_shibboleth_login_button_shibboleth_image_url':
2337
        case 'formLogin_hide_unhide_label':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
2338
2339
            break;
2340
        default:
2341
            return Container::getSettingsManager()->getSetting($variable);
2342
    }
2343
}
2344
2345
/**
2346
 * @param string $plugin
2347
 * @param string $variable
2348
 * @return string
2349
 */
2350
function api_get_plugin_setting($plugin, $variable)
2351
{
2352
    return null;
2353
    $variableName = $plugin.'_'.$variable;
0 ignored issues
show
Unused Code introduced by
$variableName = $plugin . '_' . $variable; 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...
2354
    $result = api_get_setting($variableName);
2355
    if (isset($result[$plugin])) {
2356
        return $result[$plugin];
2357
    }
2358
2359
    return null;
2360
}
2361
2362
/**
2363
 * Returns the value of a setting from the web-adjustable admin config settings.
2364
 **/
2365
function api_get_settings_params($params) {
2366
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2367
    $result = Database::select('*', $table, array('where' => $params));
2368
    return $result;
2369
}
2370
2371
function api_get_settings_params_simple($params) {
2372
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2373
    $result = Database::select('*', $table, array('where' => $params), 'one');
2374
    return $result;
2375
}
2376
2377
/**
2378
 * Returns the value of a setting from the web-adjustable admin config settings.
2379
 **/
2380
function api_delete_settings_params($params) {
2381
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2382
    $result = Database::delete($table, $params);
2383
    return $result;
2384
}
2385
2386
/**
2387
 * Returns an escaped version of $_SERVER['PHP_SELF'] to avoid XSS injection
2388
 * @return string   Escaped version of $_SERVER['PHP_SELF']
2389
 */
2390
function api_get_self() {
2391
    return htmlentities($_SERVER['PHP_SELF']);
2392
}
2393
2394
/**
2395
 * Checks whether current user is a platform administrator
2396
 * @param boolean $allowSessionAdmins Whether session admins should be considered admins or not
2397
 * @param boolean $allowDrh Whether HR directors should be considered admins or not
2398
 * @return boolean True if the user has platform admin rights,
2399
 * false otherwise.
2400
 * @see usermanager::is_admin(user_id) for a user-id specific function
2401
 */
2402
function api_is_platform_admin($allowSessionAdmins = false, $allowDrh = false)
2403
{
2404
    $checker = Container::getAuthorizationChecker();
2405
    if ($checker) {
2406
        if ($checker->isGranted('ROLE_ADMIN')) {
2407
            return true;
2408
        }
2409
        if ($allowSessionAdmins) {
2410
            if ($checker->isGranted('ROLE_SESSION_MANAGER')) {
2411
                return true;
2412
            }
2413
        }
2414
    }
2415
2416
    return false;
2417
2418
    $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...
2419
    if ($isPlatformAdmin) {
2420
        return true;
2421
    }
2422
    $_user = api_get_user_info();
2423
2424
    return
2425
        isset($_user['status']) &&
2426
        (
2427
            ($allowSessionAdmins && $_user['status'] == SESSIONADMIN) ||
2428
            ($allowDrh && $_user['status'] == DRH)
2429
        );
2430
}
2431
2432
/**
2433
 * Checks whether the user given as user id is in the admin table.
2434
 * @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...
2435
 * @param int $url URL ID. If provided, also check if the user is active on given URL
2436
 * @result bool True if the user is admin, false otherwise
2437
 */
2438
function api_is_platform_admin_by_id($user_id = null, $url = null)
2439
{
2440
    $user_id = intval($user_id);
2441
    if (empty($user_id)) {
2442
        $user_id = api_get_user_id();
2443
    }
2444
2445
    $em = Container::getEntityManager();
2446
    $user = $em->getRepository('ChamiloUserBundle:User')->find($user_id);
2447
    $is_admin = $user->hasRole('ROLE_ADMIN');
2448
2449
    if (!$is_admin or !isset($url)) {
2450
        return $is_admin;
2451
    }
2452
2453
    // We get here only if $url is set
2454
    $url = intval($url);
2455
    $url_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
2456
    $sql = "SELECT * FROM $url_user_table
2457
            WHERE access_url_id = $url AND user_id = $user_id";
2458
    $res = Database::query($sql);
2459
    $is_on_url = Database::num_rows($res) === 1;
2460
2461
    return $is_on_url;
2462
}
2463
2464
/**
2465
 * Returns the user's numeric status ID from the users table
2466
 * @param int $user_id If none provided, will use current user
2467
 * @return int User's status (1 for teacher, 5 for student, etc)
2468
 */
2469 View Code Duplication
function api_get_user_status($user_id = null)
2470
{
2471
    $user_id = intval($user_id);
2472
    if (empty($user_id)) {
2473
        $user_id = api_get_user_id();
2474
    }
2475
    $table = Database::get_main_table(TABLE_MAIN_USER);
2476
    $sql = "SELECT status FROM $table WHERE user_id = $user_id ";
2477
    $result = Database::query($sql);
2478
    $status = null;
2479
    if (Database::num_rows($result)) {
2480
        $row = Database::fetch_array($result);
2481
        $status = $row['status'];
2482
    }
2483
    return $status;
2484
}
2485
2486
/**
2487
 * Checks whether current user is allowed to create courses
2488
 * @return boolean True if the user has course creation rights,
2489
 * false otherwise.
2490
 */
2491
function api_is_allowed_to_create_course()
2492
{
2493
    if (api_is_platform_admin()) {
2494
        return true;
2495
    }
2496
2497
    // Teachers can only create courses
2498
    if (api_is_teacher()) {
2499
        if (api_get_setting('allow_users_to_create_courses') === 'true') {
2500
            return true;
2501
        } else {
2502
            return false;
2503
        }
2504
    }
2505
2506
    return Session::read('is_allowedCreateCourse');
2507
}
2508
2509
/**
2510
 * Checks whether the current user is a course administrator
2511
 * @return boolean True if current user is a course administrator
2512
 */
2513
function api_is_course_admin() {
2514
    if (api_is_platform_admin()) {
2515
        return true;
2516
    }
2517
    return Session::read('is_courseAdmin');
2518
}
2519
2520
/**
2521
 * Checks whether the current user is a course coach
2522
 * @return bool     True if current user is a course coach
2523
 */
2524
function api_is_course_coach() {
2525
    return Session::read('is_courseCoach');
2526
}
2527
2528
/**
2529
 * Checks whether the current user is a course tutor
2530
 * @return bool     True if current user is a course tutor
2531
 */
2532
function api_is_course_tutor() {
2533
    return Session::read('is_courseTutor');
2534
}
2535
2536
/**
2537
 * @param int $user_id
2538
 * @param int $courseId
2539
 * @param int $session_id
2540
 * @return bool
2541
 */
2542
function api_is_course_session_coach($user_id, $courseId, $session_id)
2543
{
2544
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2545
    $session_rel_course_rel_user_table  = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2546
2547
    $user_id = intval($user_id);
2548
    $session_id = intval($session_id);
2549
    $courseId = intval($courseId);
2550
2551
    $sql = "SELECT DISTINCT session.id
2552
            FROM $session_table
2553
            INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2554
            ON session.id = session_rc_ru.session_id
2555
            WHERE
2556
                session_rc_ru.user_id = '".$user_id."'  AND
2557
                session_rc_ru.c_id = '$courseId' AND
2558
                session_rc_ru.status = 2 AND
2559
                session_rc_ru.session_id = '$session_id'";
2560
    $result = Database::query($sql);
2561
2562
    return Database::num_rows($result) > 0;
2563
}
2564
2565
/**
2566
 * Checks whether the current user is a course or session coach
2567
 * @param int $session_id
2568
 * @param int $courseId
2569
 * @param bool  Check whether we are in student view and, if we are, return false
2570
 * @return boolean True if current user is a course or session coach
2571
 */
2572
function api_is_coach($session_id = 0, $courseId = null, $check_student_view = true)
2573
{
2574
    $userId = api_get_user_id();
2575
2576
    if (!empty($session_id)) {
2577
        $session_id = intval($session_id);
2578
    } else {
2579
        $session_id = api_get_session_id();
2580
    }
2581
2582
    // The student preview was on
2583
    if ($check_student_view &&
2584
        isset($_SESSION['studentview']) && $_SESSION['studentview'] == "studentview"
2585
    ) {
2586
        return false;
2587
    }
2588
2589
    if (!empty($courseId)) {
2590
        $courseId = intval($courseId);
2591
    } else {
2592
        $courseId = api_get_course_int_id();
2593
    }
2594
2595
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2596
    $session_rel_course_rel_user_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2597
    $sessionIsCoach = null;
2598
2599
    if (!empty($courseId)) {
2600
        $sql = "SELECT DISTINCT s.id, name, access_start_date, access_end_date
2601
                FROM $session_table s
2602
                INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2603
                ON session_rc_ru.session_id = s.id AND session_rc_ru.user_id = '".$userId."'
2604
                WHERE
2605
                    session_rc_ru.c_id = '$courseId' AND
2606
                    session_rc_ru.status = 2 AND
2607
                    session_rc_ru.session_id = '$session_id'";
2608
        $result = Database::query($sql);
2609
        $sessionIsCoach = Database::store_result($result);
2610
    }
2611
2612
    if (!empty($session_id)) {
2613
        $sql = "SELECT DISTINCT id, name, access_start_date, access_end_date
2614
                FROM $session_table
2615
                WHERE session.id_coach = $userId AND id = $session_id
2616
                ORDER BY access_start_date, access_end_date, name";
2617
        $result = Database::query($sql);
2618
        if (!empty($sessionIsCoach)) {
2619
            $sessionIsCoach = array_merge($sessionIsCoach , Database::store_result($result));
2620
        } else {
2621
            $sessionIsCoach = Database::store_result($result);
2622
        }
2623
    }
2624
2625
    return (count($sessionIsCoach) > 0);
2626
}
2627
2628
/**
2629
 * Checks whether the current user is a session administrator
2630
 * @return boolean True if current user is a course administrator
2631
 */
2632
function api_is_session_admin()
2633
{
2634
    $user = api_get_user_info();
2635
    return isset($user['status']) && $user['status'] == SESSIONADMIN;
2636
}
2637
2638
/**
2639
 * Checks whether the current user is a human resources manager
2640
 * @return boolean True if current user is a human resources manager
2641
 */
2642
function api_is_drh()
2643
{
2644
    $user = api_get_user_info();
2645
    return isset($user['status']) && $user['status'] == DRH;
2646
}
2647
2648
/**
2649
 * Checks whether the current user is a student
2650
 * @return boolean True if current user is a human resources manager
2651
 */
2652
function api_is_student()
2653
{
2654
    $user = api_get_user_info();
2655
    return isset($user['status']) && $user['status'] == STUDENT;
2656
}
2657
2658
/**
2659
 * Checks whether the current user has the status 'teacher'
2660
 * @return boolean True if current user is a human resources manager
2661
 */
2662
function api_is_teacher()
2663
{
2664
    $user = api_get_user_info();
2665
    return isset($user['status']) && $user['status'] == COURSEMANAGER;
2666
}
2667
2668
/**
2669
 * Checks whether the current user is a invited user
2670
 * @return boolean
2671
 */
2672
function api_is_invitee()
2673
{
2674
    $user = api_get_user_info();
2675
2676
    return isset($user['status']) && $user['status'] == INVITEE;
2677
}
2678
2679
/**
2680
 * This function checks whether a session is assigned into a category
2681
 * @param int       - session id
2682
 * @param string    - category name
2683
 * @return bool     - true if is found, otherwise false
2684
 */
2685
function api_is_session_in_category($session_id, $category_name)
2686
{
2687
    $session_id = intval($session_id);
2688
    $category_name = Database::escape_string($category_name);
2689
2690
    $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2691
    $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
2692
2693
    $sql = "SELECT 1
2694
            FROM $tbl_session
2695
            WHERE $session_id IN (
2696
                SELECT s.id FROM $tbl_session s, $tbl_session_category sc
2697
                WHERE
2698
                  s.session_category_id = sc.id AND
2699
                  sc.name LIKE '%$category_name'
2700
            )";
2701
    $rs = Database::query($sql);
2702
2703
    if (Database::num_rows($rs) > 0) {
2704
        return true;
2705
    } else {
2706
        return false;
2707
    }
2708
}
2709
2710
/**
2711
 * Displays the title of a tool.
2712
 * Normal use: parameter is a string:
2713
 * api_display_tool_title("My Tool")
2714
 *
2715
 * Optionally, there can be a subtitle below
2716
 * the normal title, and / or a supra title above the normal title.
2717
 *
2718
 * e.g. supra title:
2719
 * group
2720
 * GROUP PROPERTIES
2721
 *
2722
 * e.g. subtitle:
2723
 * AGENDA
2724
 * calender & events tool
2725
 *
2726
 * @author Hugues Peeters <[email protected]>
2727
 * @param  mixed $title_element - it could either be a string or an array
2728
 *                               containing 'supraTitle', 'mainTitle',
2729
 *                               'subTitle'
2730
 * @return void
2731
 */
2732
function api_display_tool_title($title_element) {
2733
    if (is_string($title_element)) {
2734
        $tit = $title_element;
2735
        unset ($title_element);
2736
        $title_element['mainTitle'] = $tit;
2737
    }
2738
    echo '<h3>';
2739
    if (!empty($title_element['supraTitle'])) {
2740
        echo '<small>'.$title_element['supraTitle'].'</small><br />';
2741
    }
2742
    if (!empty($title_element['mainTitle'])) {
2743
        echo $title_element['mainTitle'];
2744
    }
2745
    if (!empty($title_element['subTitle'])) {
2746
        echo '<br /><small>'.$title_element['subTitle'].'</small>';
2747
    }
2748
    echo '</h3>';
2749
}
2750
2751
/**
2752
 * Displays options for switching between student view and course manager view
2753
 *
2754
 * Changes in version 1.2 (Patrick Cool)
2755
 * Student view switch now behaves as a real switch. It maintains its current state until the state
2756
 * is changed explicitly
2757
 *
2758
 * Changes in version 1.1 (Patrick Cool)
2759
 * student view now works correctly in subfolders of the document tool
2760
 * student view works correctly in the new links tool
2761
 *
2762
 * Example code for using this in your tools:
2763
 * //if ($is_courseAdmin && api_get_setting('student_view_enabled') == 'true') {
2764
 * //   display_tool_view_option($isStudentView);
2765
 * //}
2766
 * //and in later sections, use api_is_allowed_to_edit()
2767
 *
2768
 * @author Roan Embrechts
2769
 * @author Patrick Cool
2770
 * @author Julio Montoya, changes added in Chamilo
2771
 * @version 1.2
2772
 * @todo rewrite code so it is easier to understand
2773
 */
2774
function api_display_tool_view_option() {
2775
    if (api_get_setting('student_view_enabled') != 'true') {
2776
        return '';
2777
    }
2778
2779
    $sourceurl = '';
2780
    $is_framed = false;
2781
    // Exceptions apply for all multi-frames pages
2782
    if (strpos($_SERVER['REQUEST_URI'], 'chat/chat_banner.php') !== false) {
2783
        // The chat is a multiframe bit that doesn't work too well with the student_view, so do not show the link
2784
        return '';
2785
    }
2786
2787
    // Uncomment to remove student view link from document view page
2788
    if (strpos($_SERVER['REQUEST_URI'], 'lp/lp_header.php') !== false) {
2789
        if (empty($_GET['lp_id'])) {
2790
            return '';
2791
        }
2792
        $sourceurl = substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], '?'));
2793
        $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);
2794
        //showinframes doesn't handle student view anyway...
2795
        //return '';
2796
        $is_framed = true;
2797
    }
2798
2799
    // Check whether the $_SERVER['REQUEST_URI'] contains already url parameters (thus a questionmark)
2800
    if (!$is_framed) {
2801
        if (strpos($_SERVER['REQUEST_URI'], '?') === false) {
2802
            $sourceurl = api_get_self().'?'.api_get_cidreq();
2803
        } else {
2804
            $sourceurl = $_SERVER['REQUEST_URI'];
2805
        }
2806
    }
2807
2808
    $output_string = '';
2809
    if (!empty($_SESSION['studentview'])) {
2810
        if ($_SESSION['studentview'] == 'studentview') {
2811
            // We have to remove the isStudentView=true from the $sourceurl
2812
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
2813
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
2814
            $output_string .= '<a class="btn btn-primary btn-sm" href="'.$sourceurl.'&isStudentView=false" target="_self">'.Display::returnFontAwesomeIcon('eye').' '.get_lang('SwitchToTeacherView').'</a>';
2815
        } elseif ($_SESSION['studentview'] == 'teacherview') {
2816
            // Switching to teacherview
2817
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
2818
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
2819
            $output_string .= '<a class="btn btn-default btn-sm" href="'.$sourceurl.'&isStudentView=true" target="_self">'.Display::returnFontAwesomeIcon('eye').' '.get_lang('SwitchToStudentView').'</a>';
2820
        }
2821
    } else {
2822
        $output_string .= '<a class="btn btn-default btn-sm" href="'.$sourceurl.'&isStudentView=true" target="_self">'.Display::returnFontAwesomeIcon('eye').' '.get_lang('SwitchToStudentView').'</a>';
2823
    }
2824
    $html = Display::tag('div', $output_string, array('class'=>'view-options'));
2825
    return $html;
2826
}
2827
2828
// TODO: This is for the permission section.
2829
/**
2830
 * Function that removes the need to directly use is_courseAdmin global in
2831
 * tool scripts. It returns true or false depending on the user's rights in
2832
 * this particular course.
2833
 * Optionally checking for tutor and coach roles here allows us to use the
2834
 * student_view feature altogether with these roles as well.
2835
 * @param bool  Whether to check if the user has the tutor role
2836
 * @param bool  Whether to check if the user has the coach role
2837
 * @param bool  Whether to check if the user has the session coach role
2838
 * @param bool  check the student view or not
2839
 *
2840
 * @author Roan Embrechts
2841
 * @author Patrick Cool
2842
 * @author Julio Montoya
2843
 * @version 1.1, February 2004
2844
 * @return boolean true: the user has the rights to edit, false: he does not
2845
 */
2846
2847
function api_is_allowed_to_edit(
2848
    $tutor = false,
2849
    $coach = false,
2850
    $session_coach = false,
2851
    $check_student_view = true
2852
) {
2853
    $my_session_id = api_get_session_id();
2854
    $is_allowed_coach_to_edit = api_is_coach(null, null, $check_student_view);
2855
    $session_visibility = api_get_session_visibility($my_session_id);
2856
2857
    // Admins can edit anything.
2858
    if (api_is_platform_admin(false)) {
2859
        // The student preview was on
2860
        if ($check_student_view && api_is_student_view_active()) {
2861
            return false;
2862
        } else {
2863
            return true;
2864
        }
2865
    }
2866
2867
    $is_courseAdmin = api_is_course_admin();
2868
2869
    if (!$is_courseAdmin && $tutor) {
2870
        // If we also want to check if the user is a tutor...
2871
        $is_courseAdmin = $is_courseAdmin || api_is_course_tutor();
2872
    }
2873
2874
    if (!$is_courseAdmin && $coach) {
2875
        // If we also want to check if the user is a coach...';
2876
        // Check if session visibility is read only for coaches.
2877
        if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
2878
            $is_allowed_coach_to_edit = false;
2879
        }
2880
2881
        if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
2882
            // Check if coach is allowed to edit a course.
2883
            $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
2884
        }
2885
    }
2886
2887
    if (!$is_courseAdmin && $session_coach) {
2888
        $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
2889
    }
2890
2891
    // Check if the student_view is enabled, and if so, if it is activated.
2892
    if (api_get_setting('student_view_enabled') == 'true') {
2893
        if (!empty($my_session_id)) {
2894
            // Check if session visibility is read only for coaches.
2895
            if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
2896
                $is_allowed_coach_to_edit = false;
2897
            }
2898
2899
            if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
2900
                // Check if coach is allowed to edit a course.
2901
                $is_allowed = $is_allowed_coach_to_edit;
2902
            } else {
2903
                $is_allowed = false;
2904
            }
2905
            if ($check_student_view) {
2906
                $is_allowed = $is_allowed && $_SESSION['studentview'] != 'studentview';
2907
            }
2908
        } else {
2909
            if ($check_student_view) {
2910
                $is_allowed = $is_courseAdmin && $_SESSION['studentview'] != 'studentview';
2911
            } else {
2912
                $is_allowed = $is_courseAdmin;
2913
            }
2914
        }
2915
2916
        return $is_allowed;
2917
    } else {
2918
2919
        return $is_courseAdmin;
2920
    }
2921
}
2922
2923
/**
2924
 * Returns true if user is a course coach of at least one course in session
2925
 * @param int $sessionId
2926
 * @return bool
2927
 */
2928
function api_is_coach_of_course_in_session($sessionId)
2929
{
2930
    if (api_is_platform_admin()) {
2931
        return true;
2932
    }
2933
2934
    $userId = api_get_user_id();
2935
    $courseList = UserManager::get_courses_list_by_session(
2936
        $userId,
2937
        $sessionId
2938
    );
2939
2940
    // Session visibility.
2941
    $visibility = api_get_session_visibility(
2942
        $sessionId,
2943
        null,
2944
        false
2945
    );
2946
2947 View Code Duplication
    if ($visibility != SESSION_VISIBLE && !empty($courseList)) {
2948
        // Course Coach session visibility.
2949
        $blockedCourseCount = 0;
2950
        $closedVisibilityList = array(
2951
            COURSE_VISIBILITY_CLOSED,
2952
            COURSE_VISIBILITY_HIDDEN
2953
        );
2954
2955
        foreach ($courseList as $course) {
2956
            // Checking session visibility
2957
            $sessionCourseVisibility = api_get_session_visibility(
2958
                $sessionId,
2959
                $course['real_id'],
2960
                $ignore_visibility_for_admins
0 ignored issues
show
Bug introduced by
The variable $ignore_visibility_for_admins does not exist. Did you mean $visibility?

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

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

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

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
3767
        $objCourse = $em->find('ChamiloCoreBundle:Course', intval($course_id));
3768
        $objTime = new DateTime('now', new DateTimeZone('UTC'));
3769
        $objUser = $em->find('ChamiloUserBundle:User', intval($user_id));
3770
        $objGroup = $em->find('ChamiloCourseBundle:CGroupInfo', intval($to_group_id));
3771
        $objToUser = $em->find('ChamiloUserBundle:User', intval($to_user_id));
3772
        $objSession = $em->find('ChamiloCoreBundle:Session', intval($session_id));
3773
3774
        $startVisibleDate = !empty($start_visible) ? new DateTime($start_visible, new DateTimeZone('UTC')) : null;
3775
        $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...
3776
3777
        $cItemProperty = new CItemProperty($objCourse);
3778
        $cItemProperty
3779
            ->setTool($tool)
3780
            ->setRef($item_id)
3781
            ->setInsertDate($objTime)
3782
            ->setInsertUser($objUser)
3783
            ->setLasteditDate($objTime)
3784
            ->setLasteditType($last_edit_type)
3785
            ->setGroup($objGroup)
3786
            ->setToUser($objToUser)
3787
            ->setVisibility($visibility)
3788
            ->setStartVisible($startVisibleDate)
3789
            ->setEndVisible($endVisibleDate)
3790
            ->setSession($objSession);
3791
3792
        $em->persist($cItemProperty);
3793
        $em->flush();
3794
3795
        $id = $cItemProperty->getIid();
3796
3797
        if ($id) {
3798
            $cItemProperty->setId($id);
3799
            $em->merge($cItemProperty);
3800
            $em->flush();
3801
3802
            return false;
3803
        }
3804
    }
3805
3806
    return true;
3807
}
3808
3809
/**
3810
 * Gets item property by tool
3811
 * @param string    course code
3812
 * @param string    tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
3813
 * @param int       id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
3814
 * @param int $session_id
3815
 * @param string $tool
3816
 * @param string $course_code
3817
 * @return array All fields from c_item_property (all rows found) or empty array
3818
 */
3819 View Code Duplication
function api_get_item_property_by_tool($tool, $course_code, $session_id = null)
3820
{
3821
    $course_info = api_get_course_info($course_code);
3822
    $tool = Database::escape_string($tool);
3823
3824
    // Definition of tables.
3825
    $item_property_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3826
    $session_id = intval($session_id);
3827
    $session_condition = ' AND session_id = '.$session_id;
3828
    if (empty($session_id)) {
3829
        $session_condition = " AND (session_id = 0 OR session_id IS NULL) ";
3830
    }
3831
    $course_id = $course_info['real_id'];
3832
3833
    $sql = "SELECT * FROM $item_property_table
3834
            WHERE
3835
                c_id = $course_id AND
3836
                tool = '$tool'
3837
                $session_condition ";
3838
    $rs  = Database::query($sql);
3839
    $list = array();
3840
    if (Database::num_rows($rs) > 0) {
3841
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
3842
            $list[] = $row;
3843
        }
3844
    }
3845
    return $list;
3846
}
3847
3848
/**
3849
 * Gets item property by tool and user
3850
 * @param int $userId
3851
 * @param int $tool
3852
 * @param int $courseId
3853
 * @param int $session_id
3854
 * @return array
3855
 */
3856 View Code Duplication
function api_get_item_property_list_by_tool_by_user(
3857
    $userId,
3858
    $tool,
3859
    $courseId,
3860
    $session_id = 0
3861
) {
3862
    $userId = intval($userId);
3863
    $tool = Database::escape_string($tool);
3864
    $session_id = intval($session_id);
3865
    $courseId = intval($courseId);
3866
3867
    // Definition of tables.
3868
    $item_property_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3869
    $session_condition = ' AND session_id = '.$session_id;
3870
    if (empty($session_id)) {
3871
        $session_condition = " AND (session_id = 0 OR session_id IS NULL) ";
3872
    }
3873
    $sql = "SELECT * FROM $item_property_table
3874
            WHERE
3875
                insert_user_id = $userId AND
3876
                c_id = $courseId AND
3877
                tool = '$tool'
3878
                $session_condition ";
3879
3880
    $rs = Database::query($sql);
3881
    $list = array();
3882
    if (Database::num_rows($rs) > 0) {
3883
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
3884
            $list[] = $row;
3885
        }
3886
    }
3887
3888
    return $list;
3889
}
3890
3891
/**
3892
 * Gets item property id from tool of a course
3893
 * @param string $course_code course code
3894
 * @param string $tool tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
3895
 * @param int $ref id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
3896
 * @param int $sessionId Session ID (optional)
3897
 * @return int
3898
 */
3899
function api_get_item_property_id($course_code, $tool, $ref, $sessionId = 0)
3900
{
3901
    $course_info = api_get_course_info($course_code);
3902
    $tool = Database::escape_string($tool);
3903
    $ref = intval($ref);
3904
3905
    // Definition of tables.
3906
    $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
3907
    $course_id = $course_info['real_id'];
3908
    $sessionId = (int) $sessionId;
3909
    $sessionCondition = " AND session_id = $sessionId ";
3910
    if (empty($sessionId)) {
3911
        $sessionCondition = " AND (session_id = 0 OR session_id IS NULL) ";
3912
    }
3913
    $sql = "SELECT id FROM $tableItemProperty
3914
            WHERE
3915
                c_id = $course_id AND
3916
                tool = '$tool' AND
3917
                ref = $ref
3918
                $sessionCondition";
3919
    $rs  = Database::query($sql);
3920
    $item_property_id = '';
3921
    if (Database::num_rows($rs) > 0) {
3922
        $row = Database::fetch_array($rs);
3923
        $item_property_id = $row['id'];
3924
    }
3925
    return $item_property_id;
3926
}
3927
3928
/**
3929
 * Inserts a record in the track_e_item_property table (No update)
3930
 * @param string $tool
3931
 * @param int $ref
3932
 * @param string $title
3933
 * @param string $content
3934
 * @param int $progress
3935
 * @return bool|int
3936
 */
3937
function api_track_item_property_update($tool, $ref, $title, $content, $progress)
3938
{
3939
    $tbl_stats_item_property = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY);
3940
    $course_id = api_get_course_int_id(); //numeric
3941
    $course_code = api_get_course_id(); //alphanumeric
3942
    $item_property_id = api_get_item_property_id($course_code, $tool, $ref);
3943
    if (!empty($item_property_id)) {
3944
        $sql = "INSERT IGNORE INTO $tbl_stats_item_property SET
3945
                course_id           = '$course_id',
3946
                item_property_id    = '$item_property_id',
3947
                title               = '".Database::escape_string($title)."',
3948
                content             = '".Database::escape_string($content)."',
3949
                progress            = '".intval($progress)."',
3950
                lastedit_date       = '".api_get_utc_datetime()."',
3951
                lastedit_user_id    = '".api_get_user_id()."',
3952
                session_id          = '".api_get_session_id()."'";
3953
        $result = Database::query($sql);
3954
        $affected_rows = Database::affected_rows($result);
3955
3956
        return $affected_rows;
3957
    }
3958
3959
    return false;
3960
}
3961
3962
/**
3963
 * @param string $tool
3964
 * @param int $ref
3965
 * @return array|resource
3966
 */
3967 View Code Duplication
function api_get_track_item_property_history($tool, $ref)
3968
{
3969
    $tbl_stats_item_property = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY);
3970
    $course_id = api_get_course_int_id(); //numeric
3971
    $course_code = api_get_course_id(); //alphanumeric
3972
    $item_property_id = api_get_item_property_id($course_code, $tool, $ref);
3973
    $sql = "SELECT * FROM $tbl_stats_item_property
3974
            WHERE item_property_id = $item_property_id AND course_id = $course_id
3975
            ORDER BY lastedit_date DESC";
3976
    $result = Database::query($sql);
3977
    if ($result == false) {
3978
        $result = array();
3979
    } else {
3980
        $result = Database::store_result($result,'ASSOC');
0 ignored issues
show
Bug introduced by
It seems like $result can be null; however, store_result() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

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

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

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