Test Setup Failed
Push — master ( ec638a...cb9435 )
by Julito
51:10
created

api.lib.php ➔ api_get_settings()   C

Complexity

Conditions 7
Paths 32

Size

Total Lines 31
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

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