Completed
Push — master ( 2ab56b...9d3aa0 )
by Julito
38:18
created

api.lib.php ➔ api_get_access_url()   C

Complexity

Conditions 7
Paths 8

Size

Total Lines 38
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 20
nc 8
nop 2
dl 0
loc 38
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
12
/**
13
 * This is a code library for Chamilo.
14
 * It is included by default in every Chamilo file (through including the global.inc.php)
15
 * This library is in process of being transferred to src/Chamilo/CoreBundle/Component/Utils/ChamiloApi.
16
 * Whenever a function is transferred to the ChamiloApi class, the places where it is used should include
17
 * the "use Chamilo\CoreBundle\Component\Utils\ChamiloApi;" statement.
18
 * @package chamilo.library
19
 */
20
21
/**
22
 * Constants declaration
23
 */
24
25
// PHP version requirement.
26
define('REQUIRED_PHP_VERSION', '7.0');
27
define('REQUIRED_MIN_MEMORY_LIMIT', '128');
28
define('REQUIRED_MIN_UPLOAD_MAX_FILESIZE', '10');
29
define('REQUIRED_MIN_POST_MAX_SIZE', '10');
30
31
// USER STATUS CONSTANTS
32
/** global status of a user: student */
33
define('STUDENT', 5);
34
/** global status of a user: course manager */
35
define('COURSEMANAGER', 1);
36
/** global status of a user: session admin */
37
define('SESSIONADMIN', 3);
38
/** global status of a user: human ressource manager */
39
define('DRH', 4);
40
/** global status of a user: human ressource manager */
41
define('ANONYMOUS', 6);
42
/** global status of a user: low security, necessary for inserting data from
43
 * the teacher through HTMLPurifier */
44
define('COURSEMANAGERLOWSECURITY', 10);
45
// Soft user status
46
define('PLATFORM_ADMIN', 11);
47
define('SESSION_COURSE_COACH', 12);
48
define('SESSION_GENERAL_COACH', 13);
49
define('COURSE_STUDENT', 14);   //student subscribed in a course
50
define('SESSION_STUDENT', 15);  //student subscribed in a session course
51
define('COURSE_TUTOR', 16); // student is tutor of a course (NOT in session)
52
define('STUDENT_BOSS', 17); // student is boss
53
define('INVITEE', 20);
54
55
// Table of status
56
$_status_list[COURSEMANAGER] = 'teacher';        // 1
57
$_status_list[SESSIONADMIN] = 'session_admin';  // 3
58
$_status_list[DRH] = 'drh';            // 4
59
$_status_list[STUDENT] = 'user';           // 5
60
$_status_list[ANONYMOUS] = 'anonymous';      // 6
61
$_status_list[INVITEE] = 'invited';        // 20
62
63
// COURSE VISIBILITY CONSTANTS
64
/** only visible for course admin */
65
define('COURSE_VISIBILITY_CLOSED', 0);
66
/** only visible for users registered in the course */
67
define('COURSE_VISIBILITY_REGISTERED', 1);
68
/** Open for all registered users on the platform */
69
define('COURSE_VISIBILITY_OPEN_PLATFORM', 2);
70
/** Open for the whole world */
71
define('COURSE_VISIBILITY_OPEN_WORLD', 3);
72
/** Invisible to all except admin */
73
define('COURSE_VISIBILITY_HIDDEN', 4);
74
75
define('COURSE_REQUEST_PENDING', 0);
76
define('COURSE_REQUEST_ACCEPTED', 1);
77
define('COURSE_REQUEST_REJECTED', 2);
78
define('DELETE_ACTION_ENABLED', false);
79
80
// EMAIL SENDING RECIPIENT CONSTANTS
81
define('SEND_EMAIL_EVERYONE', 1);
82
define('SEND_EMAIL_STUDENTS', 2);
83
define('SEND_EMAIL_TEACHERS', 3);
84
85
// SESSION VISIBILITY CONSTANTS
86
define('SESSION_VISIBLE_READ_ONLY', 1);
87
define('SESSION_VISIBLE', 2);
88
define('SESSION_INVISIBLE', 3); // not available
89
define('SESSION_AVAILABLE', 4);
90
91
define('SESSION_LINK_TARGET', '_self');
92
93
define('SUBSCRIBE_ALLOWED', 1);
94
define('SUBSCRIBE_NOT_ALLOWED', 0);
95
define('UNSUBSCRIBE_ALLOWED', 1);
96
define('UNSUBSCRIBE_NOT_ALLOWED', 0);
97
98
// SURVEY VISIBILITY CONSTANTS
99
define('SURVEY_VISIBLE_TUTOR', 0);
100
define('SURVEY_VISIBLE_TUTOR_STUDENT', 1);
101
define('SURVEY_VISIBLE_PUBLIC', 2);
102
103
// CONSTANTS defining all tools, using the english version
104
/* When you add a new tool you must add it into function api_get_tools_lists() too */
105
define('TOOL_DOCUMENT', 'document');
106
define('TOOL_LP_FINAL_ITEM', 'final_item');
107
define('TOOL_THUMBNAIL', 'thumbnail');
108
define('TOOL_HOTPOTATOES', 'hotpotatoes');
109
define('TOOL_CALENDAR_EVENT', 'calendar_event');
110
define('TOOL_LINK', 'link');
111
define('TOOL_LINK_CATEGORY', 'link_category');
112
define('TOOL_COURSE_DESCRIPTION', 'course_description');
113
define('TOOL_SEARCH', 'search');
114
define('TOOL_LEARNPATH', 'learnpath');
115
define('TOOL_AGENDA', 'agenda');
116
define('TOOL_ANNOUNCEMENT', 'announcement');
117
define('TOOL_FORUM', 'forum');
118
define('TOOL_FORUM_CATEGORY', 'forum_category');
119
define('TOOL_FORUM_THREAD', 'forum_thread');
120
define('TOOL_FORUM_POST', 'forum_post');
121
define('TOOL_FORUM_ATTACH', 'forum_attachment');
122
define('TOOL_FORUM_THREAD_QUALIFY', 'forum_thread_qualify');
123
define('TOOL_THREAD', 'thread');
124
define('TOOL_POST', 'post');
125
define('TOOL_DROPBOX', 'dropbox');
126
define('TOOL_QUIZ', 'quiz');
127
define('TOOL_TEST_CATEGORY', 'test_category');
128
define('TOOL_USER', 'user');
129
define('TOOL_GROUP', 'group');
130
define('TOOL_BLOGS', 'blog_management');
131
define('TOOL_CHAT', 'chat');
132
define('TOOL_STUDENTPUBLICATION', 'student_publication');
133
define('TOOL_TRACKING', 'tracking');
134
define('TOOL_HOMEPAGE_LINK', 'homepage_link');
135
define('TOOL_COURSE_SETTING', 'course_setting');
136
define('TOOL_BACKUP', 'backup');
137
define('TOOL_COPY_COURSE_CONTENT', 'copy_course_content');
138
define('TOOL_RECYCLE_COURSE', 'recycle_course');
139
define('TOOL_COURSE_HOMEPAGE', 'course_homepage');
140
define('TOOL_COURSE_RIGHTS_OVERVIEW', 'course_rights');
141
define('TOOL_UPLOAD', 'file_upload');
142
define('TOOL_COURSE_MAINTENANCE', 'course_maintenance');
143
define('TOOL_SURVEY', 'survey');
144
define('TOOL_WIKI', 'wiki');
145
define('TOOL_GLOSSARY', 'glossary');
146
define('TOOL_GRADEBOOK', 'gradebook');
147
define('TOOL_NOTEBOOK', 'notebook');
148
define('TOOL_ATTENDANCE', 'attendance');
149
define('TOOL_COURSE_PROGRESS', 'course_progress');
150
151
// CONSTANTS defining Chamilo interface sections
152
define('SECTION_CAMPUS', 'mycampus');
153
define('SECTION_COURSES', 'mycourses');
154
define('SECTION_CATALOG', 'catalog');
155
define('SECTION_MYPROFILE', 'myprofile');
156
define('SECTION_MYAGENDA', 'myagenda');
157
define('SECTION_COURSE_ADMIN', 'course_admin');
158
define('SECTION_PLATFORM_ADMIN', 'platform_admin');
159
define('SECTION_MYGRADEBOOK', 'mygradebook');
160
define('SECTION_TRACKING', 'session_my_space');
161
define('SECTION_SOCIAL', 'social-network');
162
define('SECTION_DASHBOARD', 'dashboard');
163
define('SECTION_REPORTS', 'reports');
164
define('SECTION_GLOBAL', 'global');
165
166
// CONSTANT name for local authentication source
167
define('PLATFORM_AUTH_SOURCE', 'platform');
168
define('CAS_AUTH_SOURCE', 'cas');
169
define('LDAP_AUTH_SOURCE', 'extldap');
170
171
// CONSTANT defining the default HotPotatoes files directory
172
define('DIR_HOTPOTATOES', '/HotPotatoes_files');
173
174
// event logs types
175
define('LOG_COURSE_DELETE', 'course_deleted');
176
define('LOG_COURSE_CREATE', 'course_created');
177
178
// @todo replace 'soc_gr' with social_group
179
define('LOG_GROUP_PORTAL_CREATED', 'soc_gr_created');
180
define('LOG_GROUP_PORTAL_UPDATED', 'soc_gr_updated');
181
define('LOG_GROUP_PORTAL_DELETED', 'soc_gr_deleted');
182
define('LOG_GROUP_PORTAL_USER_DELETE_ALL', 'soc_gr_delete_users');
183
184
define('LOG_GROUP_PORTAL_ID', 'soc_gr_portal_id');
185
define('LOG_GROUP_PORTAL_REL_USER_ARRAY', 'soc_gr_user_array');
186
187
define('LOG_GROUP_PORTAL_USER_SUBSCRIBED', 'soc_gr_u_subs');
188
define('LOG_GROUP_PORTAL_USER_UNSUBSCRIBED', 'soc_gr_u_unsubs');
189
define('LOG_GROUP_PORTAL_USER_UPDATE_ROLE', 'soc_gr_update_role');
190
191
define('LOG_USER_DELETE', 'user_deleted');
192
define('LOG_USER_CREATE', 'user_created');
193
define('LOG_USER_ENABLE', 'user_enable');
194
define('LOG_USER_DISABLE', 'user_disable');
195
define('LOG_USER_FIELD_CREATE', 'user_field_created');
196
define('LOG_USER_FIELD_DELETE', 'user_field_deleted');
197
define('LOG_SESSION_CREATE', 'session_created');
198
define('LOG_SESSION_DELETE', 'session_deleted');
199
define('LOG_SESSION_ADD_USER_COURSE', 'session_add_user_course');
200
define('LOG_SESSION_DELETE_USER_COURSE', 'session_delete_user_course');
201
define('LOG_SESSION_DELETE_USER', 'session_delete_user');
202
define('LOG_SESSION_ADD_COURSE', 'session_add_course');
203
define('LOG_SESSION_DELETE_COURSE', 'session_delete_course');
204
205
define('LOG_SESSION_CATEGORY_CREATE', 'session_cat_created'); //changed in 1.9.8
206
define('LOG_SESSION_CATEGORY_DELETE', 'session_cat_deleted'); //changed in 1.9.8
207
define('LOG_CONFIGURATION_SETTINGS_CHANGE', 'settings_changed');
208
define('LOG_PLATFORM_LANGUAGE_CHANGE', 'platform_lng_changed'); //changed in 1.9.8
209
define('LOG_SUBSCRIBE_USER_TO_COURSE', 'user_subscribed');
210
define('LOG_UNSUBSCRIBE_USER_FROM_COURSE', 'user_unsubscribed');
211
define('LOG_ATTEMPTED_FORCED_LOGIN', 'attempted_forced_login');
212
213
define('LOG_HOMEPAGE_CHANGED', 'homepage_changed');
214
215
define('LOG_PROMOTION_CREATE', 'promotion_created');
216
define('LOG_PROMOTION_DELETE', 'promotion_deleted');
217
define('LOG_CAREER_CREATE', 'career_created');
218
define('LOG_CAREER_DELETE', 'career_deleted');
219
220
define('LOG_USER_PERSONAL_DOC_DELETED', 'user_doc_deleted');
221
define('LOG_WIKI_ACCESS', 'wiki_page_view');
222
223
define('LOG_EXERCISE_RESULT_DELETE', 'exe_result_deleted');
224
define('LOG_LP_ATTEMPT_DELETE', 'lp_attempt_deleted');
225
define('LOG_QUESTION_RESULT_DELETE', 'qst_attempt_deleted');
226
227
define('LOG_MY_FOLDER_CREATE', 'my_folder_created');
228
define('LOG_MY_FOLDER_CHANGE', 'my_folder_changed');
229
define('LOG_MY_FOLDER_DELETE', 'my_folder_deleted');
230
define('LOG_MY_FOLDER_COPY', 'my_folder_copied');
231
define('LOG_MY_FOLDER_CUT', 'my_folder_cut');
232
define('LOG_MY_FOLDER_PASTE', 'my_folder_pasted');
233
define('LOG_MY_FOLDER_UPLOAD', 'my_folder_uploaded');
234
235
// Event logs data types (max 20 chars)
236
define('LOG_COURSE_CODE', 'course_code');
237
define('LOG_COURSE_ID', 'course_id');
238
define('LOG_USER_ID', 'user_id');
239
define('LOG_USER_OBJECT', 'user_object');
240
define('LOG_USER_FIELD_VARIABLE', 'user_field_variable');
241
define('LOG_SESSION_ID', 'session_id');
242
define('LOG_SESSION_CATEGORY_ID', 'session_category_id');
243
define('LOG_CONFIGURATION_SETTINGS_CATEGORY', 'settings_category');
244
define('LOG_CONFIGURATION_SETTINGS_VARIABLE', 'settings_variable');
245
define('LOG_PLATFORM_LANGUAGE', 'default_platform_language');
246
define('LOG_CAREER_ID', 'career_id');
247
define('LOG_PROMOTION_ID', 'promotion_id');
248
define('LOG_GRADEBOOK_LOCKED', 'gradebook_locked');
249
define('LOG_GRADEBOOK_UNLOCKED', 'gradebook_unlocked');
250
define('LOG_GRADEBOOK_ID', 'gradebook_id');
251
define('LOG_WIKI_PAGE_ID', 'wiki_page_id');
252
define('LOG_EXERCISE_ID', 'exercise_id');
253
define('LOG_EXERCISE_AND_USER_ID', 'exercise_and_user_id');
254
define('LOG_LP_ID', 'lp_id');
255
define('LOG_EXERCISE_ATTEMPT_QUESTION_ID', 'exercise_a_q_id');
256
257
define('LOG_WORK_DIR_DELETE', 'work_dir_delete');
258
define('LOG_WORK_FILE_DELETE', 'work_file_delete');
259
define('LOG_WORK_DATA', 'work_data_array');
260
261
define('LOG_MY_FOLDER_PATH', 'path');
262
define('LOG_MY_FOLDER_NEW_PATH', 'new_path');
263
264
define('USERNAME_PURIFIER', '/[^0-9A-Za-z_\.]/');
265
266
//used when login_is_email setting is true
267
define('USERNAME_PURIFIER_MAIL', '/[^0-9A-Za-z_\.@]/');
268
define('USERNAME_PURIFIER_SHALLOW', '/\s/');
269
270
// This constant is a result of Windows OS detection, it has a boolean value:
271
// true whether the server runs on Windows OS, false otherwise.
272
define('IS_WINDOWS_OS', api_is_windows_os());
273
274
// Checks for installed optional php-extensions.
275
define('INTL_INSTALLED', function_exists('intl_get_error_code'));   // intl extension (from PECL), it is installed by default as of PHP 5.3.0
276
define('ICONV_INSTALLED', function_exists('iconv'));                // iconv extension, for PHP5 on Windows it is installed by default.
277
define('MBSTRING_INSTALLED', function_exists('mb_strlen'));         // mbstring extension.
278
279
// Patterns for processing paths.                                   // Examples:
280
define('REPEATED_SLASHES_PURIFIER', '/\/{2,}/');                    // $path = preg_replace(REPEATED_SLASHES_PURIFIER, '/', $path);
281
define('VALID_WEB_PATH', '/https?:\/\/[^\/]*(\/.*)?/i');            // $is_valid_path = preg_match(VALID_WEB_PATH, $path);
282
define('VALID_WEB_SERVER_BASE', '/https?:\/\/[^\/]*/i');            // $new_path = preg_replace(VALID_WEB_SERVER_BASE, $new_base, $path);
283
284
// Constants for api_get_path() and api_get_path_type(), etc. - registered path types.
285
// basic (leaf elements)
286
define('REL_CODE_PATH', 'REL_CODE_PATH');
287
define('REL_COURSE_PATH', 'REL_COURSE_PATH');
288
define('REL_HOME_PATH', 'REL_HOME_PATH');
289
290
// Constants for api_get_path() and api_get_path_type(), etc. - registered path types.
291
define('WEB_PATH', 'WEB_PATH');
292
define('WEB_APP_PATH', 'WEB_APP_PATH');
293
define('SYS_PATH', 'SYS_PATH');
294
define('SYS_APP_PATH', 'SYS_APP_PATH');
295
define('SYS_UPLOAD_PATH', 'SYS_UPLOAD_PATH');
296
define('WEB_UPLOAD_PATH', 'WEB_UPLOAD_PATH');
297
298
define('REL_PATH', 'REL_PATH');
299
define('WEB_COURSE_PATH', 'WEB_COURSE_PATH');
300
define('SYS_COURSE_PATH', 'SYS_COURSE_PATH');
301
define('WEB_CODE_PATH', 'WEB_CODE_PATH');
302
define('SYS_CODE_PATH', 'SYS_CODE_PATH');
303
define('SYS_LANG_PATH', 'SYS_LANG_PATH');
304
define('WEB_IMG_PATH', 'WEB_IMG_PATH');
305
define('WEB_CSS_PATH', 'WEB_CSS_PATH');
306
define('WEB_PUBLIC_PATH', 'WEB_PUBLIC_PATH');
307
define('SYS_CSS_PATH', 'SYS_CSS_PATH');
308
define('SYS_PLUGIN_PATH', 'SYS_PLUGIN_PATH');
309
define('WEB_PLUGIN_PATH', 'WEB_PLUGIN_PATH');
310
define('WEB_PLUGIN_ASSET_PATH', 'WEB_PLUGIN_ASSET_PATH');
311
define('SYS_ARCHIVE_PATH', 'SYS_ARCHIVE_PATH');
312
define('WEB_ARCHIVE_PATH', 'WEB_ARCHIVE_PATH');
313
define('SYS_INC_PATH', 'SYS_INC_PATH');
314
define('LIBRARY_PATH', 'LIBRARY_PATH');
315
define('CONFIGURATION_PATH', 'CONFIGURATION_PATH');
316
define('WEB_LIBRARY_PATH', 'WEB_LIBRARY_PATH');
317
define('WEB_LIBRARY_JS_PATH', 'WEB_LIBRARY_JS_PATH');
318
define('WEB_AJAX_PATH', 'WEB_AJAX_PATH');
319
define('SYS_TEST_PATH', 'SYS_TEST_PATH');
320
define('WEB_TEMPLATE_PATH', 'WEB_TEMPLATE_PATH');
321
define('SYS_TEMPLATE_PATH', 'SYS_TEMPLATE_PATH');
322
define('SYS_PUBLIC_PATH', 'SYS_PUBLIC_PATH');
323
define('SYS_HOME_PATH', 'SYS_HOME_PATH');
324
define('WEB_HOME_PATH', 'WEB_HOME_PATH');
325
define('WEB_FONTS_PATH', 'WEB_FONTS_PATH');
326
define('SYS_FONTS_PATH', 'SYS_FONTS_PATH');
327
328
define('SYS_DEFAULT_COURSE_DOCUMENT_PATH', 'SYS_DEFAULT_COURSE_DOCUMENT_PATH');
329
define('REL_DEFAULT_COURSE_DOCUMENT_PATH', 'REL_DEFAULT_COURSE_DOCUMENT_PATH');
330
define('WEB_DEFAULT_COURSE_DOCUMENT_PATH', 'WEB_DEFAULT_COURSE_DOCUMENT_PATH');
331
332
// Relations type with Course manager
333
define('COURSE_RELATION_TYPE_COURSE_MANAGER', 1);
334
define('SESSION_RELATION_TYPE_COURSE_MANAGER', 1);
335
336
// Relations type with Human resources manager
337
define('COURSE_RELATION_TYPE_RRHH', 1);
338
define('SESSION_RELATION_TYPE_RRHH', 1);
339
340
//User image sizes
341
define('USER_IMAGE_SIZE_ORIGINAL', 1);
342
define('USER_IMAGE_SIZE_BIG', 2);
343
define('USER_IMAGE_SIZE_MEDIUM', 3);
344
define('USER_IMAGE_SIZE_SMALL', 4);
345
346
// Relation type between users
347
define('USER_UNKNOW', 0);
348
define('USER_RELATION_TYPE_UNKNOW', 1);
349
define('USER_RELATION_TYPE_PARENT', 2); // should be deprecated is useless
350
define('USER_RELATION_TYPE_FRIEND', 3);
351
define('USER_RELATION_TYPE_GOODFRIEND', 4); // should be deprecated is useless
352
define('USER_RELATION_TYPE_ENEMY', 5); // should be deprecated is useless
353
define('USER_RELATION_TYPE_DELETED', 6);
354
define('USER_RELATION_TYPE_RRHH', 7);
355
define('USER_RELATION_TYPE_BOSS', 8);
356
357
// Gradebook link constants
358
// Please do not change existing values, they are used in the database !
359
define('GRADEBOOK_ITEM_LIMIT', 1000);
360
361
define('LINK_EXERCISE', 1);
362
define('LINK_DROPBOX', 2);
363
define('LINK_STUDENTPUBLICATION', 3);
364
define('LINK_LEARNPATH', 4);
365
define('LINK_FORUM_THREAD', 5);
366
//define('LINK_WORK',6);
367
define('LINK_ATTENDANCE', 7);
368
define('LINK_SURVEY', 8);
369
define('LINK_HOTPOTATOES', 9);
370
371
// Score display types constants
372
define('SCORE_DIV', 1);    // X / Y
373
define('SCORE_PERCENT', 2);    // XX %
374
define('SCORE_DIV_PERCENT', 3);    // X / Y (XX %)
375
define('SCORE_AVERAGE', 4);    // XX %
376
define('SCORE_DECIMAL', 5);    // 0.50  (X/Y)
377
define('SCORE_BAR', 6);    // Uses the Display::bar_progress function
378
define('SCORE_SIMPLE', 7);    // X
379
define('SCORE_IGNORE_SPLIT', 8);    //  ??
380
define('SCORE_DIV_PERCENT_WITH_CUSTOM', 9);    // X / Y (XX %) - Good!
381
define('SCORE_CUSTOM', 10);    // Good!
382
define('SCORE_DIV_SIMPLE_WITH_CUSTOM', 11);    // X - Good!
383
define('SCORE_DIV_SIMPLE_WITH_CUSTOM_LETTERS', 12);    // X - Good!
384
define('SCORE_ONLY_SCORE', 13);    // X - Good!
385
386
define('SCORE_BOTH', 1);
387
define('SCORE_ONLY_DEFAULT', 2);
388
define('SCORE_ONLY_CUSTOM', 3);
389
390
// From display.lib.php
391
392
define('MAX_LENGTH_BREADCRUMB', 100);
393
define('ICON_SIZE_ATOM', 8);
394
define('ICON_SIZE_TINY', 16);
395
define('ICON_SIZE_SMALL', 22);
396
define('ICON_SIZE_MEDIUM', 32);
397
define('ICON_SIZE_LARGE', 48);
398
define('ICON_SIZE_BIG', 64);
399
define('ICON_SIZE_HUGE', 128);
400
define('SHOW_TEXT_NEAR_ICONS', false);
401
402
// Session catalog
403
define('CATALOG_COURSES', 0);
404
define('CATALOG_SESSIONS', 1);
405
define('CATALOG_COURSES_SESSIONS', 2);
406
407
// Hook type events, pre-process and post-process.
408
// All means to be executed for both hook event types
409
define('HOOK_EVENT_TYPE_PRE', 0);
410
define('HOOK_EVENT_TYPE_POST', 1);
411
define('HOOK_EVENT_TYPE_ALL', 10);
412
413
define('CAREER_STATUS_ACTIVE', 1);
414
define('CAREER_STATUS_INACTIVE', 0);
415
416
define('PROMOTION_STATUS_ACTIVE', 1);
417
define('PROMOTION_STATUS_INACTIVE', 0);
418
419
// Group permissions
420
define('GROUP_PERMISSION_OPEN', '1');
421
define('GROUP_PERMISSION_CLOSED', '2');
422
423
// Group user permissions
424
define('GROUP_USER_PERMISSION_ADMIN', '1'); // the admin of a group
425
define('GROUP_USER_PERMISSION_READER', '2'); // a normal user
426
define('GROUP_USER_PERMISSION_PENDING_INVITATION', '3'); // When an admin/moderator invites a user
427
define('GROUP_USER_PERMISSION_PENDING_INVITATION_SENT_BY_USER', '4'); // an user joins a group
428
define('GROUP_USER_PERMISSION_MODERATOR', '5'); // a moderator
429
define('GROUP_USER_PERMISSION_ANONYMOUS', '6'); // an anonymous user
430
define('GROUP_USER_PERMISSION_HRM', '7'); // a human resources manager
431
432
define('GROUP_IMAGE_SIZE_ORIGINAL', 1);
433
define('GROUP_IMAGE_SIZE_BIG', 2);
434
define('GROUP_IMAGE_SIZE_MEDIUM', 3);
435
define('GROUP_IMAGE_SIZE_SMALL', 4);
436
define('GROUP_TITLE_LENGTH', 50);
437
438
// Exercise
439
// @todo move into a class
440
define('ALL_ON_ONE_PAGE', 1);
441
define('ONE_PER_PAGE', 2);
442
443
define('EXERCISE_FEEDBACK_TYPE_END', 0); //Feedback 		 - show score and expected answers
444
define('EXERCISE_FEEDBACK_TYPE_DIRECT', 1); //DirectFeedback - Do not show score nor answers
445
define('EXERCISE_FEEDBACK_TYPE_EXAM', 2); //NoFeedback 	 - Show score only
446
447
define('RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS', 0); //show score and expected answers
448
define('RESULT_DISABLE_NO_SCORE_AND_EXPECTED_ANSWERS', 1); //Do not show score nor answers
449
define('RESULT_DISABLE_SHOW_SCORE_ONLY', 2); //Show score only
450
define('RESULT_DISABLE_SHOW_FINAL_SCORE_ONLY_WITH_CATEGORIES', 3); //Show final score only with categories
451
define('RESULT_DISABLE_SHOW_SCORE_ATTEMPT_SHOW_ANSWERS_LAST_ATTEMPT', 4); //Show final score only with categories
452
453
define('EXERCISE_MAX_NAME_SIZE', 80);
454
455
// Question types (edit next array as well when adding values)
456
// @todo move into a class
457
define('UNIQUE_ANSWER', 1);
458
define('MULTIPLE_ANSWER', 2);
459
define('FILL_IN_BLANKS', 3);
460
define('MATCHING', 4);
461
define('FREE_ANSWER', 5);
462
define('HOT_SPOT', 6);
463
define('HOT_SPOT_ORDER', 7);
464
define('HOT_SPOT_DELINEATION', 8);
465
define('MULTIPLE_ANSWER_COMBINATION', 9);
466
define('UNIQUE_ANSWER_NO_OPTION', 10);
467
define('MULTIPLE_ANSWER_TRUE_FALSE', 11);
468
define('MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE', 12);
469
define('ORAL_EXPRESSION', 13);
470
define('GLOBAL_MULTIPLE_ANSWER', 14);
471
define('MEDIA_QUESTION', 15);
472
define('CALCULATED_ANSWER', 16);
473
define('UNIQUE_ANSWER_IMAGE', 17);
474
define('DRAGGABLE', 18);
475
define('MATCHING_DRAGGABLE', 19);
476
477
define('EXERCISE_CATEGORY_RANDOM_SHUFFLED', 1);
478
define('EXERCISE_CATEGORY_RANDOM_ORDERED', 2);
479
define('EXERCISE_CATEGORY_RANDOM_DISABLED', 0);
480
481
// Question selection type
482
define('EX_Q_SELECTION_ORDERED', 1);
483
define('EX_Q_SELECTION_RANDOM', 2);
484
define('EX_Q_SELECTION_CATEGORIES_ORDERED_QUESTIONS_ORDERED', 3);
485
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_ORDERED', 4);
486
define('EX_Q_SELECTION_CATEGORIES_ORDERED_QUESTIONS_RANDOM', 5);
487
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_RANDOM', 6);
488
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_ORDERED_NO_GROUPED', 7);
489
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_RANDOM_NO_GROUPED', 8);
490
define('EX_Q_SELECTION_CATEGORIES_ORDERED_BY_PARENT_QUESTIONS_ORDERED', 9);
491
define('EX_Q_SELECTION_CATEGORIES_ORDERED_BY_PARENT_QUESTIONS_RANDOM', 10);
492
493
// one big string with all question types, for the validator in pear/HTML/QuickForm/Rule/QuestionType
494
define('QUESTION_TYPES',
495
    UNIQUE_ANSWER.':'.
496
    MULTIPLE_ANSWER.':'.
497
    FILL_IN_BLANKS.':'.
498
    MATCHING.':'.
499
    FREE_ANSWER.':'.
500
    HOT_SPOT.':'.
501
    HOT_SPOT_ORDER.':'.
502
    HOT_SPOT_DELINEATION.':'.
503
    MULTIPLE_ANSWER_COMBINATION.':'.
504
    UNIQUE_ANSWER_NO_OPTION.':'.
505
    MULTIPLE_ANSWER_TRUE_FALSE.':'.
506
    MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE.':'.
507
    ORAL_EXPRESSION.':'.
508
    GLOBAL_MULTIPLE_ANSWER.':'.
509
    MEDIA_QUESTION.':'.
510
    CALCULATED_ANSWER.':'.
511
    UNIQUE_ANSWER_IMAGE.':'.
512
    DRAGGABLE.':'.
513
    MATCHING_DRAGGABLE
514
);
515
516
//Some alias used in the QTI exports
517
define('MCUA', 1);
518
define('TF', 1);
519
define('MCMA', 2);
520
define('FIB', 3);
521
522
// Skills
523
define('SKILL_TYPE_REQUIREMENT', 'required');
524
define('SKILL_TYPE_ACQUIRED', 'acquired');
525
define('SKILL_TYPE_BOTH', 'both');
526
527
// Message
528
define('MESSAGE_STATUS_NEW', '0');
529
define('MESSAGE_STATUS_UNREAD', '1');
530
//2 ??
531
define('MESSAGE_STATUS_DELETED', '3');
532
define('MESSAGE_STATUS_OUTBOX', '4');
533
define('MESSAGE_STATUS_INVITATION_PENDING', '5');
534
define('MESSAGE_STATUS_INVITATION_ACCEPTED', '6');
535
define('MESSAGE_STATUS_INVITATION_DENIED', '7');
536
define('MESSAGE_STATUS_WALL', '8');
537
define('MESSAGE_STATUS_WALL_DELETE', '9');
538
define('MESSAGE_STATUS_WALL_POST', '10');
539
// Images
540
define('IMAGE_WALL_SMALL_SIZE', 200);
541
define('IMAGE_WALL_MEDIUM_SIZE', 500);
542
define('IMAGE_WALL_BIG_SIZE', 2000);
543
define('IMAGE_WALL_SMALL', 'small');
544
define('IMAGE_WALL_MEDIUM', 'medium');
545
define('IMAGE_WALL_BIG', 'big');
546
547
// Social PLUGIN PLACES
548
define('SOCIAL_LEFT_PLUGIN', 1);
549
define('SOCIAL_CENTER_PLUGIN', 2);
550
define('SOCIAL_RIGHT_PLUGIN', 3);
551
define('CUT_GROUP_NAME', 50);
552
553
/**
554
 * FormValidator Filter
555
 */
556
define('NO_HTML', 1);
557
define('STUDENT_HTML', 2);
558
define('TEACHER_HTML', 3);
559
define('STUDENT_HTML_FULLPAGE', 4);
560
define('TEACHER_HTML_FULLPAGE', 5);
561
562
// Timeline
563
define('TIMELINE_STATUS_ACTIVE', '1');
564
define('TIMELINE_STATUS_INACTIVE', '2');
565
566
// Event email template class
567
define('EVENT_EMAIL_TEMPLATE_ACTIVE',  1);
568
define('EVENT_EMAIL_TEMPLATE_INACTIVE', 0);
569
570
// Course home
571
define('SHORTCUTS_HORIZONTAL', 0);
572
define('SHORTCUTS_VERTICAL', 1);
573
574
// Image class
575
define('IMAGE_PROCESSOR', 'gd'); // 'imagick' or 'gd' strings
576
577
// Course copy
578
define('FILE_SKIP', 1);
579
define('FILE_RENAME', 2);
580
define('FILE_OVERWRITE', 3);
581
define('UTF8_CONVERT', false); //false by default
582
583
define('DOCUMENT','file');
584
define('FOLDER','folder');
585
586
define('RESOURCE_DOCUMENT', 'document');
587
define('RESOURCE_GLOSSARY', 'glossary');
588
define('RESOURCE_EVENT', 'calendar_event');
589
define('RESOURCE_LINK', 'link');
590
define('RESOURCE_COURSEDESCRIPTION', 'course_description');
591
define('RESOURCE_LEARNPATH', 'learnpath');
592
define('RESOURCE_ANNOUNCEMENT', 'announcement');
593
define('RESOURCE_FORUM', 'forum');
594
define('RESOURCE_FORUMTOPIC', 'thread');
595
define('RESOURCE_FORUMPOST', 'post');
596
define('RESOURCE_QUIZ', 'quiz');
597
define('RESOURCE_TEST_CATEGORY', 'test_category');
598
define('RESOURCE_QUIZQUESTION', 'Exercise_Question');
599
define('RESOURCE_TOOL_INTRO', 'Tool introduction');
600
define('RESOURCE_LINKCATEGORY', 'Link_Category');
601
define('RESOURCE_FORUMCATEGORY', 'Forum_Category');
602
define('RESOURCE_SCORM', 'Scorm');
603
define('RESOURCE_SURVEY', 'survey');
604
define('RESOURCE_SURVEYQUESTION', 'survey_question');
605
define('RESOURCE_SURVEYINVITATION', 'survey_invitation');
606
define('RESOURCE_WIKI', 'wiki');
607
define('RESOURCE_THEMATIC', 'thematic');
608
define('RESOURCE_ATTENDANCE', 'attendance');
609
define('RESOURCE_WORK', 'work');
610
define('RESOURCE_SESSION_COURSE', 'session_course');
611
define('RESOURCE_GRADEBOOK', 'gradebook');
612
define('ADD_THEMATIC_PLAN', 6);
613
614
// Max online users to show per page (whoisonline)
615
define('MAX_ONLINE_USERS', 12);
616
617
// Make sure the CHAMILO_LOAD_WYSIWYG constant is defined
618
// To remove CKeditor libs from HTML, set this constant to true before loading
619
if (!defined('CHAMILO_LOAD_WYSIWYG')) {
620
    define('CHAMILO_LOAD_WYSIWYG', true);
621
}
622
623
define('TOOL_PUBLIC', 'Public');
624
define('TOOL_PUBLIC_BUT_HIDDEN', 'PublicButHide');
625
define('TOOL_COURSE_ADMIN', 'courseAdmin');
626
define('TOOL_PLATFORM_ADMIN', 'platformAdmin');
627
define('TOOL_AUTHORING', 'toolauthoring');
628
define('TOOL_INTERACTION', 'toolinteraction');
629
define('TOOL_COURSE_PLUGIN', 'toolcourseplugin'); //all plugins that can be enabled in courses
630
define('TOOL_ADMIN', 'tooladmin');
631
define('TOOL_ADMIN_PLATFORM', 'tooladminplatform');
632
define('TOOL_DRH', 'tool_drh');
633
define('TOOL_STUDENT_VIEW', 'toolstudentview');
634
define('TOOL_ADMIN_VISIBLE', 'tooladminvisible');
635
636
define('FORUM_NEW_POST', 0);
637
define('CONFVAL_ASK_FOR_OFFICIAL_CODE', true);
638
define('CHECK_PASS_EASY_TO_FIND', false);
639
640
641
/**
642
 * Inclusion of internationalization libraries
643
 */
644
require_once __DIR__.'/internationalization.lib.php';
645
646
/**
647
 * Returns a path to a certain resource within the Chamilo area, specifyed through a parameter.
648
 * Also, this function provides conversion between path types, in this case the input path points inside the Chamilo area too.
649
 *
650
 * See $_configuration['course_folder'] in the configuration.php to alter the WEB_COURSE_PATH and SYS_COURSE_PATH parameters.
651
652
 * @param string $path (optional)   A path which type is to be converted. Also, it may be a defined constant for a path.
653
 * This parameter has meaning when $type parameter has one of the following values: TO_WEB, TO_SYS, TO_REL. Otherwise it is ignored.
654
 * @return string                   The requested path or the converted path.
655
 *
656
 *
657
 * Notes about the current behaviour model:
658
 * 1. Windows back-slashes are converted to slashes in the result.
659
 * 2. A semi-absolute web-path is detected by its leading slash. On Linux systems, absolute system paths start with
660
 * a slash too, so an additional check about presence of leading system server base is implemented. For example, the function is
661
 * able to distinguish type difference between /var/www/chamilo/courses/ (SYS) and /chamilo/courses/ (REL).
662
 * 3. The function api_get_path() returns only these three types of paths, which in some sense are absolute. The function has
663
 * no a mechanism for processing relative web/system paths, such as: lesson01.html, ./lesson01.html, ../css/my_styles.css.
664
 * It has not been identified as needed yet.
665
 * 4. Also, resolving the meta-symbols "." and ".." within paths has not been implemented, it is to be identified as needed.
666
 *
667
 * For examples go to: *
668
 * See main/admin/system_status.php?section=paths
669
 *
670
 * Vchamilo changes : allow using an alternate configuration
671
 * to get vchamilo  instance paths
672
*/
673
function api_get_path($path = '', $configuration = [])
674
{
675
    global $paths;
676
677
    // get proper configuration data if exists
678
    global $_configuration;
679
680
    if (empty($configuration)) {
681
        $configuration = (array) $_configuration;
682
    }
683
684
    $course_folder = 'courses/';
685
    $root_sys = Container::getRootDir();
686
    $root_rel = isset($configuration['url_append']) ? $configuration['url_append'] : '';
687
688
    // Resolve master hostname.
689
    if (!empty($configuration) && array_key_exists('root_web', $configuration)) {
690
        $root_web = $configuration['root_web'];
691
    } else {
692
        $root_web = Container::getUrlGenerator()->generate(
693
            'home',
694
            []
695
        );
696
    }
697
698
    if (isset($configuration['multiple_access_urls']) && $configuration['multiple_access_urls']) {
699
        // To avoid that the api_get_access_url() function fails since global.inc.php also calls the main_api.lib.php
700
        if (isset($configuration['access_url']) && !empty($configuration['access_url'])) {
701
            // We look into the DB the function api_get_access_url
702
            $url_info = api_get_access_url($configuration['access_url']);
703
            // Avoid default value
704
            $defaulValues = ['http://localhost/', 'https://localhost/'];
705
            if (!empty($url_info['url']) && !in_array($url_info['url'], $defaulValues)) {
706
                $root_web = $url_info['active'] == 1 ? $url_info['url'] : $configuration['root_web'];
707
            }
708
        }
709
    }
710
711
    if (empty($paths)) {
712
        $paths = [];
713
    }
714
715
    $paths = [];
716
    // Initialise cache with default values.
717
    if (!array_key_exists($root_web, $paths)) {
718
        $paths[$root_web] = array(
719
            WEB_PATH => '',
720
            SYS_PATH => '',
721
            REL_PATH => '',
722
            WEB_COURSE_PATH => '',
723
            SYS_COURSE_PATH => '',
724
            REL_COURSE_PATH => '',
725
            WEB_CODE_PATH => 'main/',
726
            SYS_CODE_PATH => 'main/',
727
            REL_CODE_PATH => '/main/',
728
            SYS_LANG_PATH => 'lang/',
729
            WEB_IMG_PATH => 'web/img/',
730
            WEB_CSS_PATH => 'web/css/',
731
            SYS_CSS_PATH => 'app/Resources/public/css/',
732
            SYS_PLUGIN_PATH => 'plugin/',
733
            WEB_PLUGIN_PATH => 'plugin/',
734
            WEB_PLUGIN_ASSET_PATH => 'web/plugins/',
735
            SYS_ARCHIVE_PATH => 'app/cache/',
736
            WEB_ARCHIVE_PATH => 'app/cache/',
737
            SYS_HOME_PATH => 'app/home/',
738
            WEB_HOME_PATH => 'app/home/',
739
            REL_HOME_PATH => 'app/home/',
740
            SYS_APP_PATH => 'app/',
741
            WEB_APP_PATH => 'app/',
742
            SYS_UPLOAD_PATH => 'app/upload/',
743
            SYS_INC_PATH => 'inc/',
744
            CONFIGURATION_PATH => 'app/config/',
745
            LIBRARY_PATH => 'inc/lib/',
746
            WEB_LIBRARY_PATH => 'inc/lib/',
747
            WEB_LIBRARY_JS_PATH => 'web/js/',
748
            WEB_AJAX_PATH => 'inc/ajax/',
749
            SYS_TEST_PATH => 'tests/',
750
            WEB_TEMPLATE_PATH => 'template/',
751
            SYS_TEMPLATE_PATH => 'template/',
752
            WEB_UPLOAD_PATH => 'app/upload/',
753
            WEB_PUBLIC_PATH => 'web/',
754
            SYS_PUBLIC_PATH => 'web/',
755
            WEB_FONTS_PATH => 'fonts/',
756
            SYS_FONTS_PATH => 'fonts/',
757
        );
758
    }
759
760
    $isInitialized = [];
761
    $course_folder = isset($configuration['course_folder']) ? $configuration['course_folder'] : $course_folder;
762
763
    // Web server base and system server base.
764
    if (!array_key_exists($root_web, $isInitialized)) {
765
        // process absolute global roots
766
        $code_folder = 'main';
767
        // Support for the installation process.
768
        // Developers might use the function api_get_path() directly or indirectly (this is difficult to be traced), at the moment when
769
        // configuration has not been created yet. This is why this function should be upgraded to return correct results in this case.
770
771
        // Dealing with trailing slashes.
772
        $slashed_root_web = api_add_trailing_slash($root_web);
773
774
        $root_sys = api_add_trailing_slash($root_sys);
775
        $root_rel = api_add_trailing_slash($root_rel);
776
        $code_folder = api_add_trailing_slash($code_folder);
777
        $course_folder = api_add_trailing_slash($course_folder);
778
779
        // Initialization of a table that contains common-purpose paths.
780
        $paths[$root_web][REL_PATH] = $root_rel;
781
        $paths[$root_web][REL_COURSE_PATH] = $root_rel.$course_folder;
782
        $paths[$root_web][REL_DEFAULT_COURSE_DOCUMENT_PATH] = $paths[$root_web][REL_PATH].'main/default_course_document/';
783
784
        $paths[$root_web][WEB_PATH] = $slashed_root_web;
785
        $paths[$root_web][WEB_CODE_PATH] = $paths[$root_web][WEB_PATH].$code_folder;
786
        $paths[$root_web][WEB_COURSE_PATH] = $paths[$root_web][WEB_PATH].$course_folder;
787
        $paths[$root_web][WEB_DEFAULT_COURSE_DOCUMENT_PATH] = $paths[$root_web][WEB_CODE_PATH].'default_course_document/';
788
        $paths[$root_web][WEB_APP_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_APP_PATH];
789
        $paths[$root_web][WEB_PLUGIN_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_PLUGIN_PATH];
790
        $paths[$root_web][WEB_PLUGIN_ASSET_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_PLUGIN_ASSET_PATH];
791
        $paths[$root_web][WEB_ARCHIVE_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_ARCHIVE_PATH];
792
        $paths[$root_web][WEB_CSS_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_CSS_PATH];
793
        $paths[$root_web][WEB_IMG_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_IMG_PATH];
794
        $paths[$root_web][WEB_LIBRARY_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_LIBRARY_PATH];
795
        $paths[$root_web][WEB_LIBRARY_JS_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_LIBRARY_JS_PATH];
796
        $paths[$root_web][WEB_AJAX_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_AJAX_PATH];
797
        $paths[$root_web][WEB_FONTS_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_FONTS_PATH];
798
        $paths[$root_web][WEB_TEMPLATE_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_TEMPLATE_PATH];
799
        $paths[$root_web][WEB_UPLOAD_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_UPLOAD_PATH];
800
        $paths[$root_web][WEB_PUBLIC_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_PUBLIC_PATH];
801
        $paths[$root_web][WEB_HOME_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][REL_HOME_PATH];
802
803
        $paths[$root_web][SYS_PATH] = $root_sys;
804
        $paths[$root_web][SYS_CODE_PATH] = $root_sys.$code_folder;
805
        $paths[$root_web][SYS_TEST_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_TEST_PATH];
806
        $paths[$root_web][SYS_TEMPLATE_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_TEMPLATE_PATH];
807
        $paths[$root_web][SYS_PUBLIC_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_PUBLIC_PATH];
808
        $paths[$root_web][SYS_CSS_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_CSS_PATH];
809
        $paths[$root_web][SYS_FONTS_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_FONTS_PATH];
810
        $paths[$root_web][SYS_ARCHIVE_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_ARCHIVE_PATH];
811
        $paths[$root_web][SYS_APP_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_APP_PATH];
812
        $paths[$root_web][SYS_COURSE_PATH] = $paths[$root_web][SYS_APP_PATH].$course_folder;
813
        $paths[$root_web][SYS_UPLOAD_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_UPLOAD_PATH];
814
        $paths[$root_web][SYS_LANG_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_LANG_PATH];
815
        $paths[$root_web][SYS_HOME_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_HOME_PATH];
816
        $paths[$root_web][SYS_PLUGIN_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_PLUGIN_PATH];
817
        $paths[$root_web][SYS_INC_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_INC_PATH];
818
819
        $paths[$root_web][LIBRARY_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][LIBRARY_PATH];
820
        $paths[$root_web][CONFIGURATION_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][CONFIGURATION_PATH];
821
822
        global $virtualChamilo;
823
        if (!empty($virtualChamilo)) {
824
            $paths[$root_web][SYS_ARCHIVE_PATH] = api_add_trailing_slash($virtualChamilo[SYS_ARCHIVE_PATH]);
825
            $paths[$root_web][SYS_HOME_PATH] = api_add_trailing_slash($virtualChamilo[SYS_HOME_PATH]);
826
            $paths[$root_web][SYS_COURSE_PATH] = api_add_trailing_slash($virtualChamilo[SYS_COURSE_PATH]);
827
            $paths[$root_web][SYS_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[SYS_UPLOAD_PATH]);
828
            //$paths[$root_web][WEB_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[WEB_UPLOAD_PATH]);
829
            //$paths[$root_web][REL_PATH] = $virtualChamilo[REL_PATH];
830
            //$paths[$root_web][REL_COURSE_PATH] = $virtualChamilo[REL_COURSE_PATH];
831
        }
832
833
        $isInitialized[$root_web] = true;
834
    }
835
836
    $path = trim($path);
837
838
    // Retrieving a common-purpose path.
839
    if (isset($paths[$root_web][$path])) {
840
        return $paths[$root_web][$path];
841
    }
842
843
    // Second purification.
844
845
    // Replacing Windows back slashes.
846
    $path = str_replace('\\', '/', $path);
847
    // Query strings sometimes mighth wrongly appear in non-URLs.
848
    // Let us check remove them from all types of paths.
849
    if (($pos = strpos($path, '?')) !== false) {
850
        $path = substr($path, 0, $pos);
851
    }
852
853
    // Detection of the input path type. Conversion to semi-absolute type ( /chamilo/main/inc/.... ).
854
855
    if (preg_match(VALID_WEB_PATH, $path)) {
856
        // A special case: When a URL points to the document download script directly, without
857
        // mod-rewrite translation, we have to translate it into an "ordinary" web path.
858
        // For example:
859
        // http://localhost/chamilo/main/document/download.php?doc_url=/image.png&cDir=/
860
        // becomes
861
        // http://localhost/chamilo/courses/TEST/document/image.png
862
        // TEST is a course directory name, so called "system course code".
863
        if (strpos($path, 'download.php') !== false) { // Fast detection first.
864
            $path = urldecode($path);
865
            if (preg_match('/(.*)main\/document\/download.php\?doc_url=\/(.*)&cDir=\/(.*)?/', $path, $matches)) {
866
                $sys_course_code =
867
                    isset($_SESSION['_course']['sysCode'])  // User is inside a course?
868
                        ? $_SESSION['_course']['sysCode']   // Yes, then use course's directory name.
869
                        : '{SYS_COURSE_CODE}';              // No, then use a fake code, it may be processed later.
870
                $path = $matches[1].'courses/'.$sys_course_code.'/document/'.str_replace('//', '/', $matches[3].'/'.$matches[2]);
871
            }
872
        }
873
        // Replacement of the present web server base with a slash '/'.
874
        $path = preg_replace(VALID_WEB_SERVER_BASE, '/', $path);
875
    }
876
877
    // Path now is semi-absolute. It is convenient at this moment repeated slashes to be removed.
878
    $path = preg_replace(REPEATED_SLASHES_PURIFIER, '/', $path);
879
880
    return $path;
881
}
882
883
/**
884
 * Gets a modified version of the path for the CDN, if defined in
885
 * configuration.php
886
 * @param string $web_path The path of the resource without CDN
887
 * @return string The path of the resource converted to CDN
888
 * @author Yannick Warnier <[email protected]>
889
 */
890
function api_get_cdn_path($web_path)
891
{
892
    global $_configuration;
893
    $web_root = api_get_path(WEB_PATH);
894
    $ext = substr($web_path,strrpos($web_path,'.'));
895
    if (isset($ext[2])) { // faster version of strlen to check if len>2
896
        // Check for CDN definitions
897
        if (!empty($_configuration['cdn_enable']) && !empty($ext)) {
898
            foreach ($_configuration['cdn'] as $host => $exts) {
899
                if (in_array($ext,$exts)) {
900
                    //Use host as defined in $_configuration['cdn'], without
901
                    // trailing slash
902
                    return str_replace($web_root,$host.'/',$web_path);
903
                }
904
            }
905
        }
906
    }
907
    return $web_path;
908
}
909
910
/**
911
 * @return bool Return true if CAS authentification is activated
912
 *
913
 */
914
function api_is_cas_activated() {
915
    return api_get_setting('cas_activate') == "true";
916
}
917
918
/**
919
 * Check if cas is configured
920
 * @return bool
921
 */
922
function api_cas_configured()
923
{
924
    $cas_auth_server = api_get_setting('cas_server');
925
    $cas_auth_port = api_get_setting('cas_port');
926
    $res = false;
927
    if (!empty($cas_auth_server) && !empty($cas_auth_port)) {
928
        $res = true;
929
    }
930
931
    return $res;
932
}
933
934
935
936
/**
937
 * @return bool     Return true if LDAP authentification is activated
938
 *
939
 */
940
function api_is_ldap_activated() {
941
    global $extAuthSource;
942
    return is_array($extAuthSource[LDAP_AUTH_SOURCE]);
943
}
944
945
/**
946
 * @return bool     Return true if Facebook authentification is activated
947
 *
948
 */
949
function api_is_facebook_auth_activated() {
950
    global $_configuration;
951
    return (isset($_configuration['facebook_auth']) && $_configuration['facebook_auth'] == 1);
952
}
953
954
/**
955
 * This function checks whether a given path points inside the system.
956
 * @param string $path      The path to be tested.
957
 * It should be full path, web-absolute (WEB), semi-absolute (REL) or system-absolyte (SYS).
958
 * @return bool             Returns true when the given path is inside the system, false otherwise.
959
 */
960
function api_is_internal_path($path) {
961
    $path = str_replace('\\', '/', trim($path));
962
    if (empty($path)) {
963
        return false;
964
    }
965
    if (strpos($path, api_remove_trailing_slash(api_get_path(WEB_PATH))) === 0) {
966
        return true;
967
    }
968
    if (strpos($path, api_remove_trailing_slash(api_get_path(SYS_PATH))) === 0) {
969
        return true;
970
    }
971
    $server_base_web = api_remove_trailing_slash(api_get_path(REL_PATH));
972
    $server_base_web = empty($server_base_web) ? '/' : $server_base_web;
973
    if (strpos($path, $server_base_web) === 0) {
974
        return true;
975
    }
976
    return false;
977
}
978
979
/**
980
 * Adds to a given path a trailing slash if it is necessary (adds "/" character at the end of the string).
981
 * @param string $path          The input path.
982
 * @return string               Returns the modified path.
983
 */
984
function api_add_trailing_slash($path) {
985
    return substr($path, -1) == '/' ? $path : $path.'/';
986
}
987
988
/**
989
 * Removes from a given path the trailing slash if it is necessary (removes "/" character from the end of the string).
990
 * @param string $path          The input path.
991
 * @return string               Returns the modified path.
992
 */
993
function api_remove_trailing_slash($path) {
994
    return substr($path, -1) == '/' ? substr($path, 0, -1) : $path;
995
}
996
997
/**
998
 * Checks the RFC 3986 syntax of a given URL.
999
 * @param string $url       The URL to be checked.
1000
 * @param bool $absolute    Whether the URL is absolute (beginning with a scheme such as "http:").
1001
 * @return string|false             Returns the URL if it is valid, FALSE otherwise.
1002
 * This function is an adaptation from the function valid_url(), Drupal CMS.
1003
 * @link http://drupal.org
1004
 * Note: The built-in function filter_var($urs, FILTER_VALIDATE_URL) has a bug for some versions of PHP.
1005
 * @link http://bugs.php.net/51192
1006
 */
1007
function api_valid_url($url, $absolute = false) {
1008
    if ($absolute) {
1009
        if (preg_match("
1010
            /^                                                      # Start at the beginning of the text
1011
            (?:ftp|https?|feed):\/\/                                # Look for ftp, http, https or feed schemes
1012
            (?:                                                     # Userinfo (optional) which is typically
1013
                (?:(?:[\w\.\-\+!$&'\(\)*\+,;=]|%[0-9a-f]{2})+:)*    # a username or a username and password
1014
                (?:[\w\.\-\+%!$&'\(\)*\+,;=]|%[0-9a-f]{2})+@        # combination
1015
            )?
1016
            (?:
1017
                (?:[a-z0-9\-\.]|%[0-9a-f]{2})+                      # A domain name or a IPv4 address
1018
                |(?:\[(?:[0-9a-f]{0,4}:)*(?:[0-9a-f]{0,4})\])       # or a well formed IPv6 address
1019
            )
1020
            (?::[0-9]+)?                                            # Server port number (optional)
1021
            (?:[\/|\?]
1022
                (?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2}) # The path and query (optional)
1023
            *)?
1024
            $/xi", $url)) {
1025
            return $url;
1026
        }
1027
        return false;
1028
    } else {
1029
        return preg_match("/^(?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2})+$/i", $url) ? $url : false;
1030
    }
1031
}
1032
1033
/**
1034
 * Checks whether a given string looks roughly like an email address.
1035
 *
1036
 * @param string $address   The e-mail address to be checked.
1037
 * @return mixed            Returns the e-mail if it is valid, FALSE otherwise.
1038
 */
1039
function api_valid_email($address)
1040
{
1041
    return filter_var($address, FILTER_VALIDATE_EMAIL);
1042
}
1043
1044
/* PROTECTION FUNCTIONS
1045
   Use these functions to protect your scripts. */
1046
1047
/**
1048
 * Function used to protect a course script.
1049
 * The function blocks access when
1050
 * - there is no $_SESSION["_course"] defined; or
1051
 * - $is_allowed_in_course is set to false (this depends on the course
1052
 * visibility and user status).
1053
 *
1054
 * This is only the first proposal, test and improve!
1055
 * @param boolean       Option to print headers when displaying error message. Default: false
1056
 * @param boolean       Whether session admins should be allowed or not.
1057
 * @return boolean      True if the user has access to the current course or is out of a course context, false otherwise
1058
 * @todo replace global variable
1059
 * @author Roan Embrechts
1060
 */
1061
function api_protect_course_script($print_headers = false, $allow_session_admins = false, $allow_drh = false)
1062
{
1063
    $is_allowed_in_course = api_is_allowed_in_course();
1064
1065
    $is_visible = false;
1066
    $course_info = api_get_course_info();
1067
1068
    if (empty($course_info)) {
1069
        api_not_allowed($print_headers);
1070
        return false;
1071
    }
1072
1073
    if (api_is_drh()) {
1074
        return true;
1075
    }
1076
1077
    if (api_is_platform_admin($allow_session_admins)) {
1078
        return true;
1079
    }
1080
1081
    if (isset($course_info) && isset($course_info['visibility'])) {
1082
        switch ($course_info['visibility']) {
1083
            default:
1084 View Code Duplication
            case COURSE_VISIBILITY_CLOSED:
1085
                // Completely closed: the course is only accessible to the teachers. - 0
1086
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1087
                    $is_visible = true;
1088
                }
1089
                break;
1090 View Code Duplication
            case COURSE_VISIBILITY_REGISTERED:
1091
                // Private - access authorized to course members only - 1
1092
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1093
                    $is_visible = true;
1094
                }
1095
                break;
1096 View Code Duplication
            case COURSE_VISIBILITY_OPEN_PLATFORM:
1097
                // Open - access allowed for users registered on the platform - 2
1098
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1099
                    $is_visible = true;
1100
                }
1101
                break;
1102
            case COURSE_VISIBILITY_OPEN_WORLD:
1103
                //Open - access allowed for the whole world - 3
1104
                $is_visible = true;
1105
                break;
1106
            case COURSE_VISIBILITY_HIDDEN:
1107
                //Completely closed: the course is only accessible to the teachers. - 0
1108
                if (api_is_platform_admin()) {
1109
                    $is_visible = true;
1110
                }
1111
                break;
1112
        }
1113
1114
        //If password is set and user is not registered to the course then the course is not visible
1115
        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...
1116
            isset($course_info['registration_code']) &&
1117
            !empty($course_info['registration_code'])
1118
        ) {
1119
            $is_visible = false;
1120
        }
1121
    }
1122
1123
    // Check session visibility
1124
    $session_id = api_get_session_id();
1125
1126
    if (!empty($session_id)) {
1127
        //$is_allowed_in_course was set in local.inc.php
1128
        if (!$is_allowed_in_course) {
1129
            $is_visible = false;
1130
        }
1131
    }
1132
1133
    if (!$is_visible) {
1134
        api_not_allowed($print_headers);
1135
        return false;
1136
    }
1137
    return true;
1138
}
1139
1140
/**
1141
 * Function used to protect an admin script.
1142
 *
1143
 * The function blocks access when the user has no platform admin rights
1144
 * with an error message printed on default output
1145
 * @param bool Whether to allow session admins as well
1146
 * @param bool Whether to allow HR directors as well
1147
 * @param string An optional message (already passed through get_lang)
1148
 * @return bool True if user is allowed, false otherwise.
1149
 * The function also outputs an error message in case not allowed
1150
 * @author Roan Embrechts (original author)
1151
 */
1152
function api_protect_admin_script($allow_sessions_admins = false, $allow_drh = false, $message = null)
1153
{
1154
    if (!api_is_platform_admin($allow_sessions_admins, $allow_drh)) {
1155
        api_not_allowed(true, $message);
1156
        return false;
1157
    }
1158
    return true;
1159
}
1160
1161
/**
1162
 * Function used to protect a teacher script.
1163
 * The function blocks access when the user has no teacher rights.
1164
 *
1165
 * @author Yoselyn Castillo
1166
 */
1167
function api_protect_teacher_script($allow_sessions_admins = false)
1168
{
1169
    if (!api_is_allowed_to_edit()) {
1170
        api_not_allowed(true);
1171
        return false;
1172
    }
1173
    return true;
1174
}
1175
1176
/**
1177
 * Function used to prevent anonymous users from accessing a script.
1178
 * @param bool|true $printHeaders
1179
 * @author Roan Embrechts
1180
 *
1181
 * @return bool
1182
 */
1183
function api_block_anonymous_users($printHeaders = true)
1184
{
1185
    $user = api_get_user_info();
1186 View Code Duplication
    if (!(isset($user['user_id']) && $user['user_id']) || api_is_anonymous($user['user_id'], true)) {
1187
        api_not_allowed($printHeaders);
1188
        return false;
1189
    }
1190
1191
    return true;
1192
}
1193
1194
/**
1195
 * @return array with the navigator name and version
1196
 */
1197
function api_get_navigator() {
1198
    $navigator = 'Unknown';
1199
    $version = 0;
1200
1201
    if (!isset($_SERVER['HTTP_USER_AGENT'])) {
1202
        return array('name' => 'Unknown', 'version' => '0.0.0');
1203
    }
1204
1205
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') !== false) {
1206
        $navigator = 'Opera';
1207
        list (, $version) = explode('Opera', $_SERVER['HTTP_USER_AGENT']);
1208 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {
1209
        $navigator = 'Internet Explorer';
1210
        list (, $version) = explode('MSIE', $_SERVER['HTTP_USER_AGENT']);
1211
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome') !== false) {
1212
        $navigator = 'Chrome';
1213
        list (, $version) = explode('Chrome', $_SERVER['HTTP_USER_AGENT']);
1214 View Code Duplication
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'safari') !== false) {
1215
        $navigator = 'Safari';
1216
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1217
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Gecko') !== false) {
1218
        $navigator = 'Mozilla';
1219
        list (, $version) = explode('; rv:', $_SERVER['HTTP_USER_AGENT']);
1220 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Netscape') !== false) {
1221
        $navigator = 'Netscape';
1222
        list (, $version) = explode('Netscape', $_SERVER['HTTP_USER_AGENT']);
1223
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Konqueror') !== false) {
1224
        $navigator = 'Konqueror';
1225
        list (, $version) = explode('Konqueror', $_SERVER['HTTP_USER_AGENT']);
1226 View Code Duplication
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'applewebkit') !== false) {
1227
        $navigator = 'AppleWebKit';
1228
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1229
    }
1230
    $version = str_replace('/', '', $version);
1231
    if (strpos($version, '.') === false) {
1232
        $version = number_format(doubleval($version), 1);
1233
    }
1234
    $return = array('name' => $navigator, 'version' => $version);
1235
    return $return;
1236
}
1237
1238
/**
1239
 * @return True if user self registration is allowed, false otherwise.
1240
 */
1241
function api_is_self_registration_allowed()
1242
{
1243
    return isset($GLOBALS['allowSelfReg']) ? $GLOBALS['allowSelfReg'] : false;
1244
}
1245
1246
/**
1247
 * This function returns the id of the user which is stored in the $_user array.
1248
 *
1249
 * example: The function can be used to check if a user is logged in
1250
 *          if (api_get_user_id())
1251
 * @return integer the id of the current user, 0 if is empty
1252
 */
1253
function api_get_user_id()
1254
{
1255
    $userInfo = Session::read('_user');
1256
    if ($userInfo && isset($userInfo['user_id'])) {
1257
        return $userInfo['user_id'];
1258
    }
1259
    return 0;
1260
}
1261
1262
/**
1263
 * Gets the list of courses a specific user is subscribed to
1264
 * @param int       User ID
1265
 * @param boolean   $fetch_session Whether to get session courses or not - NOT YET IMPLEMENTED
1266
 * @return array    Array of courses in the form [0]=>('code'=>xxx,'db'=>xxx,'dir'=>xxx,'status'=>d)
1267
 */
1268
function api_get_user_courses($userid, $fetch_session = true)
1269
{
1270
    // Get out if not integer
1271
    if ($userid != strval(intval($userid))) {
1272
        return array();
1273
    }
1274
1275
    $t_course = Database::get_main_table(TABLE_MAIN_COURSE);
1276
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1277
1278
    $sql = "SELECT cc.id as real_id, cc.code code, cc.directory dir, cu.status status
1279
            FROM    $t_course       cc,
1280
                    $t_course_user   cu
1281
            WHERE
1282
                cc.id = cu.c_id AND
1283
                cu.user_id = '".$userid."' AND
1284
                cu.relation_type<>".COURSE_RELATION_TYPE_RRHH." ";
1285
    $result = Database::query($sql);
1286
    if ($result === false) {
1287
        return array();
1288
    }
1289
1290
    $courses = array();
1291
    while ($row = Database::fetch_array($result)) {
1292
        // we only need the database name of the course
1293
        $courses[] = $row;
1294
    }
1295
1296
    return $courses;
1297
}
1298
1299
/**
1300
 * Formats user doctrine object information into array
1301
 * This function should be only used inside api_get_user_info()
1302
 *
1303
 * @param User $user
1304
 * @param bool $checkIfUserOnline
1305
 * @param bool $showPassword
1306
 * @param bool $loadExtraData
1307
 * @param bool $loadOnlyVisibleExtraData
1308
 * @return array
1309
 */
1310
function _api_format_user(
1311
    User $user,
1312
    $checkIfUserOnline = false,
1313
    $showPassword = false,
1314
    $loadExtraData = false,
1315
    $loadOnlyVisibleExtraData = false
1316
) {
1317
    $result = array();
1318
1319
    $result['username'] = $user->getUsername();
1320
    $result['firstName'] = $result['firstname'] = $user->getFirstname();
1321
    $result['lastName'] = $result['lastname'] = $user->getLastname();
1322
    $result['complete_name'] = api_get_person_name($result['firstname'], $result['lastname']);
1323
    $result['complete_name_with_username'] = $result['complete_name'];
1324
    if (!empty($result['username'])) {
1325
        $result['complete_name_with_username'] = $result['complete_name'].' ('.$result['username'].')';
1326
    }
1327
    $result['phone'] = $user->getPhone();
1328
    $result['address'] = $user->getAddress();
1329
    $result['official_code'] = $user->getOfficialCode();
1330
    $result['status'] = $user->getStatus();
1331
    $result['active'] = $user->getActive();
1332
    $result['auth_source'] = $user->getAuthSource();
1333
    $result['theme'] = $user->getTheme();
1334
    $result['language'] = $user->getLanguage();
1335
    $result['creator_id'] = $user->getCreatorId();
1336
    $result['registration_date'] = $user->getRegistrationDate() ? $user->getRegistrationDate()->format('Y-m-d h:i:s') : '';
1337
    $result['hr_dept_id'] = $user->getHrDeptId();
1338
    $result['expiration_date'] = $user->getExpirationDate() ? $user->getExpirationDate()->format('Y-m-d h:i:s') : '';
1339
    $result['picture_uri'] = $user->getPictureUri();
1340
1341
    if (api_get_setting('extended_profile') === 'true') {
1342
        $result['competences'] = $user->getCompetences();
1343
        $result['diplomas']  = $user->getDiplomas();
1344
        $result['teach'] = $user->getTeach();
1345
        $result['openarea'] = $user->getOpenarea();
1346
    }
1347
1348
    $result['email'] = $result['mail'] = $user->getEmail();
1349
    $userId = $user->getId();
1350
    // Maintain the user_id index for backwards compatibility
1351
    $result['user_id'] = $result['id'] = $userId;
1352
    $result['last_login'] = $user->getLastLogin() ? $user->getLastLogin()->format('Y-m-d h:i:s') : '';
1353
1354
    // Getting user avatar.
1355
    $originalFile = UserManager::getUserPicture($userId, USER_IMAGE_SIZE_ORIGINAL, null, $result);
1356
    $smallFile = UserManager::getUserPicture($userId, USER_IMAGE_SIZE_SMALL, null, $result);
1357
    $mediumFile = UserManager::getUserPicture($userId, USER_IMAGE_SIZE_MEDIUM, null, $result);
1358
1359
    $result['avatar'] = $originalFile;
1360
    $avatarString = explode('?', $originalFile);
1361
    $result['avatar_no_query'] = reset($avatarString);
1362
    $result['avatar_small'] = $smallFile;
1363
    $result['avatar_medium'] = $mediumFile;
1364
1365
    if ($showPassword) {
1366
        $result['password'] = $user->getPassword();
1367
    }
1368
1369
    $result['profile_completed'] = $user->isProfileCompleted();
1370
    $result['profile_url'] = api_get_path(WEB_CODE_PATH).'social/profile.php?u='.$userId;
1371
1372
    if ($checkIfUserOnline) {
1373
        $use_status_in_platform = UserManager::user_is_online($userId);
1374
1375
        $result['user_is_online'] = $use_status_in_platform;
1376
        $user_online_in_chat = 0;
1377
1378
        if ($use_status_in_platform) {
1379
            $user_status = UserManager::get_extra_user_data_by_field(
1380
                $userId,
1381
                'user_chat_status',
1382
                false,
1383
                true
1384
            );
1385
            if (intval($user_status['user_chat_status']) == 1) {
1386
                $user_online_in_chat = 1;
1387
            }
1388
        }
1389
        $result['user_is_online_in_chat'] = $user_online_in_chat;
1390
    }
1391
1392
    if ($loadExtraData) {
1393
        $fieldValue = new ExtraFieldValue('user');
1394
1395
        $result['extra'] = $fieldValue->getAllValuesForAnItem(
1396
            $userId,
1397
            $loadOnlyVisibleExtraData
1398
        );
1399
    }
1400
1401
    return $result;
1402
}
1403
1404
/**
1405
 * Finds all the information about a user.
1406
 * If no parameter is passed you find all the information about the current user.
1407
 * @param int  $user_id
1408
 * @param bool $checkIfUserOnline
1409
 * @param bool $showPassword
1410
 * @param bool $loadExtraData
1411
 * @param bool $loadOnlyVisibleExtraData Get the user extra fields that are visible
1412
 * @return array $user_info user_id, lastname, firstname, username, email, etc
1413
 * @author Patrick Cool <[email protected]>
1414
 * @author Julio Montoya
1415
 * @version 21 September 2004
1416
 */
1417
function api_get_user_info(
1418
    $user_id = 0,
1419
    $checkIfUserOnline = false,
1420
    $showPassword = false,
1421
    $loadExtraData = false,
1422
    $loadOnlyVisibleExtraData = false
1423
) {
1424
    if (empty($user_id)) {
1425
        $storage = Container::getTokenStorage();
1426
        $token = $storage->getToken();
1427
        $user = $token->getUser();
1428
        if ($user instanceof User) {
1429
            return _api_format_user(
1430
                $token->getUser(),
1431
                $checkIfUserOnline,
1432
                $showPassword,
1433
                $loadExtraData,
1434
                $loadOnlyVisibleExtraData
1435
            );
1436
        }
1437
1438
        return false;
1439
    }
1440
1441
    $user = UserManager::getManager()->find($user_id);
1442
1443
    if ($user) {
1444
        return _api_format_user(
1445
            $user,
1446
            $checkIfUserOnline,
1447
            $showPassword,
1448
            $loadExtraData,
1449
            $loadOnlyVisibleExtraData
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 gradebook in session
1671
 */
1672
function api_is_in_gradebook()
1673
{
1674
    return Session::read('in_gradebook', false);
1675
}
1676
1677
/**
1678
 * set gradebook session
1679
 */
1680
function api_set_in_gradebook()
1681
{
1682
    Session::write('in_gradebook', true);
1683
}
1684
1685
/**
1686
 * remove gradebook session
1687
 */
1688
function api_remove_in_gradebook()
1689
{
1690
    Session::erase('in_gradebook');
1691
}
1692
1693
/**
1694
 * Returns the current course info array see api_format_course_array()
1695
 * If the course_code is given, the returned array gives info about that
1696
 * particular course, if none given it gets the course info from the session.
1697
 *
1698
 * @param string $course_code
1699
 * @param bool $strict
1700
 *
1701
 * @return array
1702
 */
1703
function api_get_course_info($course_code = null, $strict = false)
1704
{
1705
    if (!empty($course_code)) {
1706
        $course_code = Database::escape_string($course_code);
1707
        $courseId = api_get_course_int_id($course_code);
1708
1709
        if (empty($courseId)) {
1710
            return array();
1711
        }
1712
1713
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1714
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1715
        $sql = "SELECT
1716
                    course.*,
1717
                    course_category.code faCode,
1718
                    course_category.name faName
1719
                FROM $course_table
1720
                LEFT JOIN $course_cat_table
1721
                ON course.category_code = course_category.code
1722
                WHERE course.id = $courseId";
1723
        $result = Database::query($sql);
1724
        $courseInfo = array();
1725
        if (Database::num_rows($result) > 0) {
1726
            $data = Database::fetch_array($result);
1727
            $courseInfo = api_format_course_array($data);
1728
        }
1729
1730
        return $courseInfo;
1731
    }
1732
1733
    $_course = Session::read('_course');
1734
    if ($_course == '-1') {
1735
        $_course = array();
1736
    }
1737
1738
    return $_course;
1739
}
1740
1741
/**
1742
 * Returns the current course info array.
1743
1744
 * Now if the course_code is given, the returned array gives info about that
1745
 * particular course, not specially the current one.
1746
 * @param int $id Numeric ID of the course
1747
 * @return array The course info as an array formatted by api_format_course_array, including category.name
1748
 */
1749
function api_get_course_info_by_id($id = null)
1750
{
1751
    if (!empty($id)) {
1752
        $id = intval($id);
1753
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1754
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1755
        $sql = "SELECT
1756
                    course.*,
1757
                    course_category.code faCode,
1758
                    course_category.name faName
1759
                FROM $course_table
1760
                LEFT JOIN $course_cat_table
1761
                ON course.category_code =  course_category.code
1762
                WHERE course.id = $id";
1763
        $result = Database::query($sql);
1764
        $_course = array();
1765
        if (Database::num_rows($result) > 0) {
1766
            $course_data = Database::fetch_array($result);
1767
            $_course = api_format_course_array($course_data);
1768
        }
1769
        return $_course;
1770
    }
1771
1772
    global $_course;
1773
    if ($_course == '-1') $_course = array();
1774
    return $_course;
1775
}
1776
1777
/**
1778
 * Reformat the course array (output by api_get_course_info()) in order, mostly,
1779
 * to switch from 'code' to 'id' in the array. This is a legacy feature and is
1780
 * now possibly causing massive confusion as a new "id" field has been added to
1781
 * the course table in 1.9.0.
1782
 * @param $course_data
1783
 * @return array
1784
 * @todo eradicate the false "id"=code field of the $_course array and use the int id
1785
 */
1786
function api_format_course_array($course_data)
1787
{
1788
    if (empty($course_data)) {
1789
        return array();
1790
    }
1791
1792
    $_course = array();
1793
    $_course['id'] = $course_data['code'];
1794
    $_course['real_id'] = $course_data['id'];
1795
1796
    // Added
1797
    $_course['code'] = $course_data['code'];
1798
    $_course['name'] = $course_data['title'];
1799
    $_course['title'] = $course_data['title'];
1800
    $_course['official_code'] = $course_data['visual_code'];
1801
    $_course['visual_code'] = $course_data['visual_code'];
1802
    $_course['sysCode'] = $course_data['code'];
1803
    $_course['path'] = $course_data['directory']; // Use as key in path.
1804
    $_course['directory'] = $course_data['directory'];
1805
    $_course['creation_date'] = $course_data['creation_date'];
1806
    $_course['titular'] = $course_data['tutor_name'];
1807
    $_course['language'] = $course_data['course_language'];
1808
    $_course['extLink']['url'] = $course_data['department_url'];
1809
    $_course['extLink']['name'] = $course_data['department_name'];
1810
    $_course['categoryCode'] = $course_data['faCode'];
1811
    $_course['categoryName'] = $course_data['faName'];
1812
    $_course['visibility'] = $course_data['visibility'];
1813
    $_course['subscribe_allowed'] = $course_data['subscribe'];
1814
    $_course['subscribe'] = $course_data['subscribe'];
1815
    $_course['unsubscribe'] = $course_data['unsubscribe'];
1816
    $_course['course_language'] = $course_data['course_language'];
1817
    $_course['activate_legal'] = isset($course_data['activate_legal']) ? $course_data['activate_legal'] : false;
1818
    $_course['legal'] = $course_data['legal'];
1819
    $_course['show_score'] = $course_data['show_score']; //used in the work tool
1820
    $_course['department_name'] = $course_data['department_name'];
1821
    $_course['department_url'] = $course_data['department_url'];
1822
1823
    // Course password
1824
    $_course['registration_code'] = !empty($course_data['registration_code']) ? sha1($course_data['registration_code']) : null;
1825
    $_course['disk_quota'] = $course_data['disk_quota'];
1826
    $_course['course_public_url'] = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/index.php';
1827
1828
    if (array_key_exists('add_teachers_to_sessions_courses', $course_data)) {
1829
        $_course['add_teachers_to_sessions_courses'] = $course_data['add_teachers_to_sessions_courses'];
1830
    }
1831
1832
    if (file_exists(api_get_path(SYS_COURSE_PATH).$course_data['directory'].'/course-pic85x85.png')) {
1833
        $url_image = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/course-pic85x85.png';
1834
    } else {
1835
        $url_image = Display::return_icon('course.png', null, null, ICON_SIZE_BIG, null, true, false);
1836
    }
1837
    $_course['course_image'] = $url_image;
1838
1839
    if (file_exists(api_get_path(SYS_COURSE_PATH).$course_data['directory'].'/course-pic.png')) {
1840
        $url_image = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/course-pic.png';
1841
    } else {
1842
        $url_image = Display::returnIconPath('session_default.png');
1843
    }
1844
    $_course['course_image_large'] = $url_image;
1845
1846
    $_course['extra_fields'] = isset($course_data['extra_fields']) ? $course_data['extra_fields'] : array();
1847
    $_course['settings'] = isset($course_data['settings']) ? $course_data['settings'] : array();
1848
    $_course['teacher_list'] = isset($course_data['teacher_list']) ? $course_data['teacher_list'] : array();
1849
    $_course['teacher_list_formatted'] = isset($course_data['teacher_list_formatted']) ? $course_data['teacher_list_formatted'] : array();
1850
1851
    return $_course;
1852
}
1853
1854
/**
1855
 * Add a parameter to the existing URL. If this parameter already exists,
1856
 * just replace it with the new value
1857
 * @param   string  The URL
1858
 * @param   string  param=value string
1859
 * @param   boolean Whether to filter XSS or not
1860
 * @return  string  The URL with the added parameter
1861
 */
1862
function api_add_url_param($url, $param, $filter_xss = true) {
1863
    if (empty($param)) {
1864
        return $url;
1865
    }
1866
    if (strpos($url, '?') !== false) {
1867
        if ($param[0] != '&') {
1868
            $param = '&'.$param;
1869
        }
1870
        list (, $query_string) = explode('?', $url);
1871
        $param_list1 = explode('&', $param);
1872
        $param_list2 = explode('&', $query_string);
1873
        $param_list1_keys = $param_list1_vals = array();
1874
        foreach ($param_list1 as $key => $enreg) {
1875
            list ($param_list1_keys[$key], $param_list1_vals[$key]) = explode('=', $enreg);
1876
        }
1877
        $param_list1 = array ('keys' => $param_list1_keys, 'vals' => $param_list1_vals);
1878
        foreach ($param_list2 as $enreg) {
1879
            $enreg = explode('=', $enreg);
1880
            $key = array_search($enreg[0], $param_list1['keys']);
1881
            if (!is_null($key) && !is_bool($key)) {
1882
                $url = str_replace($enreg[0].'='.$enreg[1], $enreg[0].'='.$param_list1['vals'][$key], $url);
1883
                $param = str_replace('&'.$enreg[0].'='.$param_list1['vals'][$key], '', $param);
1884
            }
1885
        }
1886
        $url .= $param;
1887
    } else {
1888
        $url = $url.'?'.$param;
1889
    }
1890
    if ($filter_xss === true) {
1891
        $url = Security::remove_XSS(urldecode($url));
1892
    }
1893
    return $url;
1894
}
1895
1896
/**
1897
 * Returns a difficult to guess password.
1898
 * @param int $length the length of the password
1899
 * @return string the generated password
1900
 */
1901
function api_generate_password($length = 8)
1902
{
1903
    $characters = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
1904
    $numbers = '23456789';
1905
1906
    if ($length < 2) {
1907
        $length = 2;
1908
    }
1909
    $password = '';
1910
    for ($i = 0; $i < $length; $i ++) {
1911
        $password .= $characters[rand() % strlen($characters)];
1912
    }
1913
1914
    // At least 2 digits
1915
    for ($i = 0; $i < 2; $i ++) {
1916
        $password .= $numbers[rand() % strlen($numbers)];
1917
    }
1918
1919
    return $password;
1920
}
1921
1922
/**
1923
 * Checks a password to see wether it is OK to use.
1924
 * @param string $password
1925
 * @return boolean if the password is acceptable, false otherwise
1926
 * Notes about what a password "OK to use" is:
1927
 * 1. The password should be at least 5 characters long.
1928
 * 2. Only English letters (uppercase or lowercase, it doesn't matter) and digits are allowed.
1929
 * 3. The password should contain at least 3 letters.
1930
 * 4. It should contain at least 2 digits.
1931
 * 5. It should not contain 3 or more consequent (according to ASCII table) characters.
1932
 */
1933
function api_check_password($password) {
1934
    $password_length = api_strlen($password);
1935
    if ($password_length < 5) {
1936
        return false;
1937
    }
1938
    $password = api_strtolower($password);
1939
    $letters = 0;
1940
    $digits = 0;
1941
    $consequent_characters = 0;
1942
    $previous_character_code = 0;
1943
    for ($i = 0; $i < $password_length; $i ++) {
1944
        $current_character_code = api_ord(api_substr($password, $i, 1));
0 ignored issues
show
Security Bug introduced by
It seems like api_substr($password, $i, 1) targeting api_substr() can also be of type false; however, api_ord() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
1945
        if ($i && abs($current_character_code - $previous_character_code) <= 1) {
1946
            $consequent_characters ++;
1947
            if ($consequent_characters == 3) {
1948
                return false;
1949
            }
1950
        } else {
1951
            $consequent_characters = 1;
1952
        }
1953
        if ($current_character_code >= 97 && $current_character_code <= 122) {
1954
            $letters ++;
1955
        } elseif ($current_character_code >= 48 && $current_character_code <= 57) {
1956
            $digits ++;
1957
        } else {
1958
            return false;
1959
        }
1960
        $previous_character_code = $current_character_code;
1961
    }
1962
    return ($letters >= 3 && $digits >= 2);
1963
}
1964
1965
/**
1966
 * Clears the user ID from the session if it was the anonymous user. Generally
1967
 * used on out-of-tools pages to remove a user ID that could otherwise be used
1968
 * in the wrong context.
1969
 * This function is to be used in conjunction with the api_set_anonymous()
1970
 * function to simulate the user existence in case of an anonymous visit.
1971
 * @param bool      database check switch - passed to api_is_anonymous()
1972
 * @return bool     true if succesfully unregistered, false if not anonymous.
1973
 */
1974
function api_clear_anonymous($db_check = false)
1975
{
1976
    global $_user;
1977
    if (api_is_anonymous($_user['user_id'], $db_check)) {
1978
        unset($_user['user_id']);
1979
        Session::erase('_uid');
1980
        return true;
1981
    }
1982
    return false;
1983
}
1984
1985
/**
1986
 * Returns the status string corresponding to the status code
1987
 * @author Noel Dieschburg
1988
 * @param the int status code
1989
 */
1990
function get_status_from_code($status_code)
1991
{
1992
    switch ($status_code) {
1993
        case STUDENT:
1994
            return get_lang('Student', '');
1995
        case TEACHER:
1996
            return get_lang('Teacher', '');
1997
        case COURSEMANAGER:
1998
            return get_lang('Manager', '');
1999
        case SESSIONADMIN:
2000
            return get_lang('SessionsAdmin', '');
2001
        case DRH:
2002
            return get_lang('Drh', '');
2003
    }
2004
}
2005
2006
/**
2007
 * Sets the current user as anonymous if it hasn't been identified yet. This
2008
 * function should be used inside a tool only. The function api_clear_anonymous()
2009
 * acts in the opposite direction by clearing the anonymous user's data every
2010
 * time we get on a course homepage or on a neutral page (index, admin, my space)
2011
 * @return bool     true if set user as anonymous, false if user was already logged in or anonymous id could not be found
2012
 */
2013
function api_set_anonymous() {
2014
    $_user = Session::read('_user');
2015
2016
    if (!empty($_user['user_id'])) {
2017
        return false;
2018
    }
2019
    $user_id = api_get_anonymous_id();
2020
    if ($user_id == 0) {
2021
        return false;
2022
    }
2023
    Session::erase('_user');
2024
    $_user['user_id'] = $user_id;
2025
    $_user['is_anonymous'] = true;
2026
    $GLOBALS['_user'] = $_user;
2027
    Session::write('_user', $_user);
2028
    return true;
2029
}
2030
2031
/**
2032
 * Gets the current Chamilo (not PHP/cookie) session ID
2033
 * @return  int     O if no active session, the session ID otherwise
2034
 */
2035
function api_get_session_id()
2036
{
2037
    return Session::read('id_session', 0);
2038
}
2039
2040
/**
2041
 * Gets the current Chamilo (not social network) group ID
2042
 * @return  int     O if no active session, the session ID otherwise
2043
 */
2044
function api_get_group_id()
2045
{
2046
    return Session::read('_gid', 0);
2047
}
2048
2049
/**
2050
 * Gets the current or given session name
2051
 * @param   int     Session ID (optional)
2052
 * @return  string  The session name, or null if unfound
2053
 */
2054
function api_get_session_name($session_id = 0)
2055
{
2056
    if (empty($session_id)) {
2057
        $session_id = api_get_session_id();
2058
        if (empty($session_id)) {
2059
            return null;
2060
        }
2061
    }
2062
    $t = Database::get_main_table(TABLE_MAIN_SESSION);
2063
    $s = "SELECT name FROM $t WHERE id = ".(int)$session_id;
2064
    $r = Database::query($s);
2065
    $c = Database::num_rows($r);
2066
    if ($c > 0) {
2067
        //technically, there can be only one, but anyway we take the first
2068
        $rec = Database::fetch_array($r);
2069
        return $rec['name'];
2070
    }
2071
    return null;
2072
}
2073
2074
/**
2075
 * Gets the session info by id
2076
 * @param int       Session ID
2077
 * @return array    information of the session
2078
 */
2079
function api_get_session_info($session_id)
2080
{
2081
    return SessionManager::fetch($session_id);
2082
}
2083
2084
/**
2085
 * Gets the session visibility by session id
2086
 * @param int $session_id
2087
 * @param int $courseId
2088
 * @param bool $ignore_visibility_for_admins
2089
 * @return int
2090
 *  0 = session still available,
2091
 *  SESSION_VISIBLE_READ_ONLY = 1,
2092
 *  SESSION_VISIBLE = 2,
2093
 *  SESSION_INVISIBLE = 3
2094
 */
2095
function api_get_session_visibility(
2096
    $session_id,
2097
    $courseId = null,
2098
    $ignore_visibility_for_admins = true
2099
) {
2100
    // Means that the session is still available.
2101
    $visibility = 0;
2102
2103
    if (api_is_platform_admin()) {
2104
        if ($ignore_visibility_for_admins) {
2105
            return SESSION_AVAILABLE;
2106
        }
2107
    }
2108
2109
    $now = time();
2110
    if (!empty($session_id)) {
2111
        $session_id = intval($session_id);
2112
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2113
2114
        $sql = "SELECT * FROM $tbl_session
2115
                WHERE id = $session_id ";
2116
2117
        $result = Database::query($sql);
2118
2119
        if (Database::num_rows($result) > 0) {
2120
            $row = Database::fetch_array($result, 'ASSOC');
2121
            $visibility = $original_visibility = $row['visibility'];
2122
2123
            // I don't care the session visibility.
2124
            if (empty($row['access_start_date']) && empty($row['access_end_date'])) {
2125
                // Session duration per student.
2126
                if (isset($row['duration']) && !empty($row['duration'])) {
2127
                    $duration = $row['duration'] * 24 * 60 * 60;
2128
2129
                    $courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser(
2130
                        $session_id,
2131
                        api_get_user_id()
2132
                    );
2133
2134
                    // If there is a session duration but there is no previous
2135
                    // access by the user, then the session is still available
2136
                    if (count($courseAccess) == 0) {
2137
                        return SESSION_AVAILABLE;
2138
                    }
2139
2140
                    $currentTime = time();
2141
                    $firstAccess = 0;
2142
                    if (isset($courseAccess['login_course_date'])) {
2143
                        $firstAccess = api_strtotime(
2144
                            $courseAccess['login_course_date'],
2145
                            'UTC'
2146
                        );
2147
                    }
2148
                    $userDurationData = SessionManager::getUserSession(
2149
                        api_get_user_id(),
2150
                        $session_id
2151
                    );
2152
                    $userDuration = 0;
2153 View Code Duplication
                    if (isset($userDurationData['duration'])) {
2154
                        $userDuration = intval($userDurationData['duration']) * 24 * 60 * 60;
2155
                    }
2156
2157
                    $totalDuration = $firstAccess + $duration + $userDuration;
2158
                    if ($totalDuration > $currentTime) {
2159
                        return SESSION_AVAILABLE;
2160
                    } else {
2161
                        return SESSION_INVISIBLE;
2162
                    }
2163
                }
2164
2165
                return SESSION_AVAILABLE;
2166
            } else {
2167
                // If start date was set.
2168
                if (!empty($row['access_start_date'])) {
2169
                    if ($now > api_strtotime($row['access_start_date'], 'UTC')) {
2170
                        $visibility = SESSION_AVAILABLE;
2171
                    } else {
2172
                        $visibility = SESSION_INVISIBLE;
2173
                    }
2174
                }
2175
2176
                // If the end date was set.
2177
                if (!empty($row['access_end_date'])) {
2178
                    // Only if date_start said that it was ok
2179
                    if ($visibility === SESSION_AVAILABLE) {
2180
                        if ($now < api_strtotime($row['access_end_date'], 'UTC')) {
2181
                            // Date still available
2182
                            $visibility = SESSION_AVAILABLE;
2183
                        } else {
2184
                            // Session ends
2185
                            $visibility = $row['visibility'];
2186
                        }
2187
                    }
2188
                }
2189
            }
2190
2191
            /* If I'm a coach the visibility can change in my favor depending in
2192
             the coach dates */
2193
            $isCoach = api_is_coach($session_id, $courseId);
2194
2195
            if ($isCoach) {
2196
                // Test end date.
2197
                if (!empty($row['coach_access_end_date'])) {
2198
                    $endDateCoach = api_strtotime($row['coach_access_end_date'], 'UTC');
2199
2200
                    if ($endDateCoach >= $now) {
2201
                        $visibility = SESSION_AVAILABLE;
2202
                    } else {
2203
                        $visibility = SESSION_INVISIBLE;
2204
                    }
2205
                }
2206
2207
                // Test start date.
2208
                if (!empty($row['coach_access_start_date'])) {
2209
                    $start = api_strtotime($row['coach_access_start_date'], 'UTC');
2210
                    if ($start < $now) {
2211
                        $visibility = SESSION_AVAILABLE;
2212
                    } else {
2213
                        $visibility = SESSION_INVISIBLE;
2214
                    }
2215
                }
2216
            }
2217
        } else {
2218
            $visibility = SESSION_INVISIBLE;
2219
        }
2220
    }
2221
    return $visibility;
2222
}
2223
2224
/**
2225
 * This function returns a (star) session icon if the session is not null and
2226
 * the user is not a student
2227
 * @param int   $session_id
2228
 * @param int   $status_id User status id - if 5 (student), will return empty
2229
 * @return string   Session icon
2230
 */
2231
function api_get_session_image($session_id, $status_id)
2232
{
2233
    $session_id = (int)$session_id;
2234
    $session_img = '';
2235
    if ((int)$status_id != 5) { //check whether is not a student
2236
        if ($session_id > 0) {
2237
            $session_img = "&nbsp;&nbsp;".Display::return_icon(
2238
                'star.png',
2239
                get_lang('SessionSpecificResource'),
2240
                array('align' => 'absmiddle'),
2241
                ICON_SIZE_SMALL
2242
            );
2243
        }
2244
    }
2245
    return $session_img;
2246
}
2247
2248
/**
2249
 * This function add an additional condition according to the session of the course
2250
 * @param int       $session_id session id
2251
 * @param bool      $and optional, true if more than one condition false if the only condition in the query
2252
 * @param bool      $with_base_content optional, true to accept content with session=0 as well, false for strict session condition
2253
 * @return string   condition of the session
2254
 */
2255
function api_get_session_condition(
2256
    $session_id,
2257
    $and = true,
2258
    $with_base_content = false,
2259
    $session_field = "session_id"
2260
) {
2261
    $session_id = intval($session_id);
2262
2263
    if (empty($session_field)) {
2264
        $session_field = "session_id";
2265
    }
2266
    // Condition to show resources by session
2267
    $condition_add = $and ? " AND " : " WHERE ";
2268
2269
    if ($with_base_content) {
2270
        $condition_session = $condition_add." ( $session_field = $session_id OR $session_field = 0 OR $session_field IS NULL) ";
2271
    } else {
2272
        if (empty($session_id)) {
2273
            $condition_session = $condition_add." ($session_field = $session_id OR $session_field IS NULL)";
2274
        } else {
2275
            $condition_session = $condition_add." $session_field = $session_id ";
2276
        }
2277
    }
2278
    return $condition_session;
2279
}
2280
2281
/**
2282
 * @param string $variable
2283
 * @param string $option
2284
 * @return bool
2285
 */
2286
function api_get_setting_in_list($variable, $option)
2287
{
2288
    $value = api_get_setting($variable);
2289
2290
    return in_array($option, $value);
2291
}
2292
2293
2294
/**
2295
 * Returns the value of a setting from the web-adjustable admin config settings.
2296
 *
2297
 * WARNING true/false are stored as string, so when comparing you need to check e.g.
2298
 * if (api_get_setting('course.show_navigation_menu') == 'true') //CORRECT
2299
 * instead of
2300
 * if (api_get_setting('course.show_navigation_menu') == true) //INCORRECT
2301
 * @param string    $variable The variable name
2302
 * @return string
2303
 *
2304
 * @author Julio Montoya
2305
 */
2306
function api_get_setting($variable, $subVariable = '')
2307
{
2308
    $variable = trim($variable);
2309
2310
    switch ($variable) {
2311 View Code Duplication
        case 'header_extra_content':
2312
            $filename = api_get_path(SYS_PATH).api_get_home_path().'header_extra_content.txt';
2313
            if (file_exists($filename)) {
2314
                $value = file_get_contents($filename);
2315
                    return $value ;
2316
            } else {
2317
                return '';
2318
            }
2319
            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...
2320 View Code Duplication
        case 'footer_extra_content':
2321
            $filename = api_get_path(SYS_PATH).api_get_home_path().'footer_extra_content.txt';
2322
            if (file_exists($filename)) {
2323
                $value = file_get_contents($filename);
2324
                return $value ;
2325
            } else {
2326
                return '';
2327
            }
2328
            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...
2329
        case 'server_type':
2330
            $test = ['dev', 'test'];
2331
            $environment = Container::getEnvironment();
2332
            if (in_array($environment, $test)) {
2333
                return 'test';
2334
            }
2335
            return 'prod';
2336
        case 'stylesheets':
2337
            $variable = 'platform.theme';
2338
            break;
2339
        // deprecated settings
2340
        case 'openid_authentication':
2341
        case 'sso_authentication':
2342
        case 'service_ppt2lp':
2343
        case 'add_cas_login_button_cas_button_label':
2344
        case 'add_cas_login_button_cas_button_comment':
2345
        case 'add_cas_login_button_cas_image_url':
2346
        case 'add_cas_logout_button_cas_logout_label':
2347
        case 'add_cas_logout_button_cas_logout_comment':
2348
        case 'add_cas_logout_button_cas_logout_image_url':
2349
        case 'add_facebook_login_button_facebook_button_url':
2350
        case 'add_shibboleth_login_button_shibboleth_button_label':
2351
        case 'add_shibboleth_login_button_shibboleth_button_comment':
2352
        case 'add_shibboleth_login_button_shibboleth_image_url':
2353
        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...
2354
2355
            break;
2356
        default:
2357
            return Container::getSettingsManager()->getSetting($variable);
2358
    }
2359
}
2360
2361
/**
2362
 * @param string $plugin
2363
 * @param string $variable
2364
 * @return string
2365
 */
2366
function api_get_plugin_setting($plugin, $variable)
2367
{
2368
    $variableName = $plugin.'_'.$variable;
2369
    $params = [
2370
        'category = ? AND subkey = ? AND variable = ?' => [
2371
            'Plugins',
2372
            $plugin,
2373
            $variableName,
2374
        ],
2375
    ];
2376
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2377
    $result = Database::select(
2378
        'selected_value',
2379
        $table,
2380
        array('where' => $params),
2381
        'one'
2382
    );
2383
    if ($result) {
2384
        $result = $result['selected_value'];
2385
        return $result;
2386
    }
2387
2388
    return null;
2389
}
2390
2391
/**
2392
 * Returns the value of a setting from the web-adjustable admin config settings.
2393
 **/
2394
function api_get_settings_params($params) {
2395
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2396
    $result = Database::select('*', $table, array('where' => $params));
2397
    return $result;
2398
}
2399
2400
function api_get_settings_params_simple($params) {
2401
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2402
    $result = Database::select('*', $table, array('where' => $params), 'one');
2403
    return $result;
2404
}
2405
2406
/**
2407
 * Returns the value of a setting from the web-adjustable admin config settings.
2408
 **/
2409
function api_delete_settings_params($params) {
2410
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2411
    $result = Database::delete($table, $params);
2412
    return $result;
2413
}
2414
2415
/**
2416
 * Returns an escaped version of $_SERVER['PHP_SELF'] to avoid XSS injection
2417
 * @return string   Escaped version of $_SERVER['PHP_SELF']
2418
 */
2419
function api_get_self() {
2420
    return htmlentities($_SERVER['PHP_SELF']);
2421
}
2422
2423
/**
2424
 * Checks whether current user is a platform administrator
2425
 * @param boolean $allowSessionAdmins Whether session admins should be considered admins or not
2426
 * @param boolean $allowDrh Whether HR directors should be considered admins or not
2427
 * @return boolean True if the user has platform admin rights,
2428
 * false otherwise.
2429
 * @see usermanager::is_admin(user_id) for a user-id specific function
2430
 */
2431
function api_is_platform_admin($allowSessionAdmins = false, $allowDrh = false)
2432
{
2433
    $checker = Container::getAuthorizationChecker();
2434
    if ($checker) {
2435
        if ($checker->isGranted('ROLE_ADMIN')) {
2436
            return true;
2437
        }
2438
        if ($allowSessionAdmins) {
2439
            if ($checker->isGranted('ROLE_SESSION_MANAGER')) {
2440
                return true;
2441
            }
2442
        }
2443
    }
2444
2445
    return false;
2446
2447
    $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...
2448
    if ($isPlatformAdmin) {
2449
        return true;
2450
    }
2451
    $_user = api_get_user_info();
2452
2453
    return
2454
        isset($_user['status']) &&
2455
        (
2456
            ($allowSessionAdmins && $_user['status'] == SESSIONADMIN) ||
2457
            ($allowDrh && $_user['status'] == DRH)
2458
        );
2459
}
2460
2461
/**
2462
 * Checks whether the user given as user id is in the admin table.
2463
 * @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...
2464
 * @param int $url URL ID. If provided, also check if the user is active on given URL
2465
 * @result bool True if the user is admin, false otherwise
2466
 */
2467
function api_is_platform_admin_by_id($user_id = null, $url = null)
2468
{
2469
    $user_id = intval($user_id);
2470
    if (empty($user_id)) {
2471
        $user_id = api_get_user_id();
2472
    }
2473
2474
    $em = Container::getEntityManager();
2475
    $user = $em->getRepository('ChamiloUserBundle:User')->find($user_id);
2476
    $is_admin = $user->hasRole('ROLE_ADMIN');
2477
2478
    if (!$is_admin or !isset($url)) {
2479
        return $is_admin;
2480
    }
2481
2482
    // We get here only if $url is set
2483
    $url = intval($url);
2484
    $url_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
2485
    $sql = "SELECT * FROM $url_user_table
2486
            WHERE access_url_id = $url AND user_id = $user_id";
2487
    $res = Database::query($sql);
2488
    $is_on_url = Database::num_rows($res) === 1;
2489
2490
    return $is_on_url;
2491
}
2492
2493
/**
2494
 * Returns the user's numeric status ID from the users table
2495
 * @param int $user_id If none provided, will use current user
2496
 * @return int User's status (1 for teacher, 5 for student, etc)
2497
 */
2498 View Code Duplication
function api_get_user_status($user_id = null)
2499
{
2500
    $user_id = intval($user_id);
2501
    if (empty($user_id)) {
2502
        $user_id = api_get_user_id();
2503
    }
2504
    $table = Database::get_main_table(TABLE_MAIN_USER);
2505
    $sql = "SELECT status FROM $table WHERE user_id = $user_id ";
2506
    $result = Database::query($sql);
2507
    $status = null;
2508
    if (Database::num_rows($result)) {
2509
        $row = Database::fetch_array($result);
2510
        $status = $row['status'];
2511
    }
2512
    return $status;
2513
}
2514
2515
/**
2516
 * Checks whether current user is allowed to create courses
2517
 * @return boolean True if the user has course creation rights,
2518
 * false otherwise.
2519
 */
2520
function api_is_allowed_to_create_course()
2521
{
2522
    if (api_is_platform_admin()) {
2523
        return true;
2524
    }
2525
2526
    // Teachers can only create courses
2527
    if (api_is_teacher()) {
2528
        if (api_get_setting('allow_users_to_create_courses') === 'true') {
2529
            return true;
2530
        } else {
2531
            return false;
2532
        }
2533
    }
2534
2535
    return Session::read('is_allowedCreateCourse');
2536
}
2537
2538
/**
2539
 * Checks whether the current user is a course administrator
2540
 * @return boolean True if current user is a course administrator
2541
 */
2542
function api_is_course_admin() {
2543
    if (api_is_platform_admin()) {
2544
        return true;
2545
    }
2546
    return Session::read('is_courseAdmin');
2547
}
2548
2549
/**
2550
 * Checks whether the current user is a course coach
2551
 * @return bool     True if current user is a course coach
2552
 */
2553
function api_is_course_coach() {
2554
    return Session::read('is_courseCoach');
2555
}
2556
2557
/**
2558
 * Checks whether the current user is a course tutor
2559
 * @return bool     True if current user is a course tutor
2560
 */
2561
function api_is_course_tutor() {
2562
    return Session::read('is_courseTutor');
2563
}
2564
2565
/**
2566
 * @param int $user_id
2567
 * @param int $courseId
2568
 * @param int $session_id
2569
 * @return bool
2570
 */
2571
function api_is_course_session_coach($user_id, $courseId, $session_id)
2572
{
2573
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2574
    $session_rel_course_rel_user_table  = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2575
2576
    $user_id = intval($user_id);
2577
    $session_id = intval($session_id);
2578
    $courseId = intval($courseId);
2579
2580
    $sql = "SELECT DISTINCT session.id
2581
            FROM $session_table
2582
            INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2583
            ON session.id = session_rc_ru.session_id
2584
            WHERE
2585
                session_rc_ru.user_id = '".$user_id."'  AND
2586
                session_rc_ru.c_id = '$courseId' AND
2587
                session_rc_ru.status = 2 AND
2588
                session_rc_ru.session_id = '$session_id'";
2589
    $result = Database::query($sql);
2590
2591
    return Database::num_rows($result) > 0;
2592
}
2593
2594
/**
2595
 * Checks whether the current user is a course or session coach
2596
 * @param int $session_id
2597
 * @param int $courseId
2598
 * @param bool  Check whether we are in student view and, if we are, return false
2599
 * @return boolean True if current user is a course or session coach
2600
 */
2601
function api_is_coach($session_id = 0, $courseId = null, $check_student_view = true)
2602
{
2603
    $userId = api_get_user_id();
2604
2605
    if (!empty($session_id)) {
2606
        $session_id = intval($session_id);
2607
    } else {
2608
        $session_id = api_get_session_id();
2609
    }
2610
2611
    // The student preview was on
2612
    if ($check_student_view &&
2613
        isset($_SESSION['studentview']) && $_SESSION['studentview'] == "studentview"
2614
    ) {
2615
        return false;
2616
    }
2617
2618
    if (!empty($courseId)) {
2619
        $courseId = intval($courseId);
2620
    } else {
2621
        $courseId = api_get_course_int_id();
2622
    }
2623
2624
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2625
    $session_rel_course_rel_user_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2626
    $sessionIsCoach = null;
2627
2628
    if (!empty($courseId)) {
2629
        $sql = "SELECT DISTINCT s.id, name, access_start_date, access_end_date
2630
                FROM $session_table s
2631
                INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2632
                ON session_rc_ru.session_id = s.id AND session_rc_ru.user_id = '".$userId."'
2633
                WHERE
2634
                    session_rc_ru.c_id = '$courseId' AND
2635
                    session_rc_ru.status = 2 AND
2636
                    session_rc_ru.session_id = '$session_id'";
2637
        $result = Database::query($sql);
2638
        $sessionIsCoach = Database::store_result($result);
2639
    }
2640
2641
    if (!empty($session_id)) {
2642
        $sql = "SELECT DISTINCT id, name, access_start_date, access_end_date
2643
                FROM $session_table
2644
                WHERE session.id_coach = $userId AND id = $session_id
2645
                ORDER BY access_start_date, access_end_date, name";
2646
        $result = Database::query($sql);
2647
        if (!empty($sessionIsCoach)) {
2648
            $sessionIsCoach = array_merge($sessionIsCoach , Database::store_result($result));
2649
        } else {
2650
            $sessionIsCoach = Database::store_result($result);
2651
        }
2652
    }
2653
2654
    return (count($sessionIsCoach) > 0);
2655
}
2656
2657
/**
2658
 * Checks whether the current user is a session administrator
2659
 * @return boolean True if current user is a course administrator
2660
 */
2661
function api_is_session_admin()
2662
{
2663
    $user = api_get_user_info();
2664
    return isset($user['status']) && $user['status'] == SESSIONADMIN;
2665
}
2666
2667
/**
2668
 * Checks whether the current user is a human resources manager
2669
 * @return boolean True if current user is a human resources manager
2670
 */
2671
function api_is_drh()
2672
{
2673
    $user = api_get_user_info();
2674
    return isset($user['status']) && $user['status'] == DRH;
2675
}
2676
2677
/**
2678
 * Checks whether the current user is a student
2679
 * @return boolean True if current user is a human resources manager
2680
 */
2681
function api_is_student()
2682
{
2683
    $user = api_get_user_info();
2684
    return isset($user['status']) && $user['status'] == STUDENT;
2685
}
2686
2687
/**
2688
 * Checks whether the current user has the status 'teacher'
2689
 * @return boolean True if current user is a human resources manager
2690
 */
2691
function api_is_teacher()
2692
{
2693
    $user = api_get_user_info();
2694
    return isset($user['status']) && $user['status'] == COURSEMANAGER;
2695
}
2696
2697
/**
2698
 * Checks whether the current user is a invited user
2699
 * @return boolean
2700
 */
2701
function api_is_invitee()
2702
{
2703
    $user = api_get_user_info();
2704
2705
    return isset($user['status']) && $user['status'] == INVITEE;
2706
}
2707
2708
/**
2709
 * This function checks whether a session is assigned into a category
2710
 * @param int       - session id
2711
 * @param string    - category name
2712
 * @return bool     - true if is found, otherwise false
2713
 */
2714
function api_is_session_in_category($session_id, $category_name)
2715
{
2716
    $session_id = intval($session_id);
2717
    $category_name = Database::escape_string($category_name);
2718
2719
    $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2720
    $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
2721
2722
    $sql = "SELECT 1
2723
            FROM $tbl_session
2724
            WHERE $session_id IN (
2725
                SELECT s.id FROM $tbl_session s, $tbl_session_category sc
2726
                WHERE
2727
                  s.session_category_id = sc.id AND
2728
                  sc.name LIKE '%$category_name'
2729
            )";
2730
    $rs = Database::query($sql);
2731
2732
    if (Database::num_rows($rs) > 0) {
2733
        return true;
2734
    } else {
2735
        return false;
2736
    }
2737
}
2738
2739
/**
2740
 * Displays the title of a tool.
2741
 * Normal use: parameter is a string:
2742
 * api_display_tool_title("My Tool")
2743
 *
2744
 * Optionally, there can be a subtitle below
2745
 * the normal title, and / or a supra title above the normal title.
2746
 *
2747
 * e.g. supra title:
2748
 * group
2749
 * GROUP PROPERTIES
2750
 *
2751
 * e.g. subtitle:
2752
 * AGENDA
2753
 * calender & events tool
2754
 *
2755
 * @author Hugues Peeters <[email protected]>
2756
 * @param  mixed $title_element - it could either be a string or an array
2757
 *                               containing 'supraTitle', 'mainTitle',
2758
 *                               'subTitle'
2759
 * @return void
2760
 */
2761
function api_display_tool_title($title_element) {
2762
    if (is_string($title_element)) {
2763
        $tit = $title_element;
2764
        unset ($title_element);
2765
        $title_element['mainTitle'] = $tit;
2766
    }
2767
    echo '<h3>';
2768
    if (!empty($title_element['supraTitle'])) {
2769
        echo '<small>'.$title_element['supraTitle'].'</small><br />';
2770
    }
2771
    if (!empty($title_element['mainTitle'])) {
2772
        echo $title_element['mainTitle'];
2773
    }
2774
    if (!empty($title_element['subTitle'])) {
2775
        echo '<br /><small>'.$title_element['subTitle'].'</small>';
2776
    }
2777
    echo '</h3>';
2778
}
2779
2780
/**
2781
 * Displays options for switching between student view and course manager view
2782
 *
2783
 * Changes in version 1.2 (Patrick Cool)
2784
 * Student view switch now behaves as a real switch. It maintains its current state until the state
2785
 * is changed explicitly
2786
 *
2787
 * Changes in version 1.1 (Patrick Cool)
2788
 * student view now works correctly in subfolders of the document tool
2789
 * student view works correctly in the new links tool
2790
 *
2791
 * Example code for using this in your tools:
2792
 * //if ($is_courseAdmin && api_get_setting('student_view_enabled') == 'true') {
2793
 * //   display_tool_view_option($isStudentView);
2794
 * //}
2795
 * //and in later sections, use api_is_allowed_to_edit()
2796
 *
2797
 * @author Roan Embrechts
2798
 * @author Patrick Cool
2799
 * @author Julio Montoya, changes added in Chamilo
2800
 * @version 1.2
2801
 * @todo rewrite code so it is easier to understand
2802
 */
2803
function api_display_tool_view_option() {
2804
    if (api_get_setting('student_view_enabled') != 'true') {
2805
        return '';
2806
    }
2807
2808
    $sourceurl = '';
2809
    $is_framed = false;
2810
    // Exceptions apply for all multi-frames pages
2811
    if (strpos($_SERVER['REQUEST_URI'], 'chat/chat_banner.php') !== false) {
2812
        // The chat is a multiframe bit that doesn't work too well with the student_view, so do not show the link
2813
        return '';
2814
    }
2815
2816
    // Uncomment to remove student view link from document view page
2817
    if (strpos($_SERVER['REQUEST_URI'], 'lp/lp_header.php') !== false) {
2818
        if (empty($_GET['lp_id'])) {
2819
            return '';
2820
        }
2821
        $sourceurl = substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], '?'));
2822
        $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);
2823
        //showinframes doesn't handle student view anyway...
2824
        //return '';
2825
        $is_framed = true;
2826
    }
2827
2828
    // Check whether the $_SERVER['REQUEST_URI'] contains already url parameters (thus a questionmark)
2829
    if (!$is_framed) {
2830
        if (strpos($_SERVER['REQUEST_URI'], '?') === false) {
2831
            $sourceurl = api_get_self().'?'.api_get_cidreq();
2832
        } else {
2833
            $sourceurl = $_SERVER['REQUEST_URI'];
2834
        }
2835
    }
2836
2837
    $output_string = '';
2838
    if (!empty($_SESSION['studentview'])) {
2839
        if ($_SESSION['studentview'] == 'studentview') {
2840
            // We have to remove the isStudentView=true from the $sourceurl
2841
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
2842
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
2843
            $output_string .= '<a class="btn btn-primary btn-sm" href="'.$sourceurl.'&isStudentView=false" target="_self">'.Display::returnFontAwesomeIcon('eye').' '.get_lang('SwitchToTeacherView').'</a>';
2844
        } elseif ($_SESSION['studentview'] == 'teacherview') {
2845
            // Switching to teacherview
2846
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
2847
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
2848
            $output_string .= '<a class="btn btn-default btn-sm" href="'.$sourceurl.'&isStudentView=true" target="_self">'.Display::returnFontAwesomeIcon('eye').' '.get_lang('SwitchToStudentView').'</a>';
2849
        }
2850
    } else {
2851
        $output_string .= '<a class="btn btn-default btn-sm" href="'.$sourceurl.'&isStudentView=true" target="_self">'.Display::returnFontAwesomeIcon('eye').' '.get_lang('SwitchToStudentView').'</a>';
2852
    }
2853
    $html = Display::tag('div', $output_string, array('class'=>'view-options'));
2854
    return $html;
2855
}
2856
2857
// TODO: This is for the permission section.
2858
/**
2859
 * Function that removes the need to directly use is_courseAdmin global in
2860
 * tool scripts. It returns true or false depending on the user's rights in
2861
 * this particular course.
2862
 * Optionally checking for tutor and coach roles here allows us to use the
2863
 * student_view feature altogether with these roles as well.
2864
 * @param bool  Whether to check if the user has the tutor role
2865
 * @param bool  Whether to check if the user has the coach role
2866
 * @param bool  Whether to check if the user has the session coach role
2867
 * @param bool  check the student view or not
2868
 *
2869
 * @author Roan Embrechts
2870
 * @author Patrick Cool
2871
 * @author Julio Montoya
2872
 * @version 1.1, February 2004
2873
 * @return boolean true: the user has the rights to edit, false: he does not
2874
 */
2875
2876
function api_is_allowed_to_edit(
2877
    $tutor = false,
2878
    $coach = false,
2879
    $session_coach = false,
2880
    $check_student_view = true
2881
) {
2882
    $my_session_id = api_get_session_id();
2883
    $is_allowed_coach_to_edit = api_is_coach(null, null, $check_student_view);
2884
    $session_visibility = api_get_session_visibility($my_session_id);
2885
2886
    // Admins can edit anything.
2887
    if (api_is_platform_admin(false)) {
2888
        // The student preview was on
2889
        if ($check_student_view && api_is_student_view_active()) {
2890
            return false;
2891
        } else {
2892
            return true;
2893
        }
2894
    }
2895
2896
    $is_courseAdmin = api_is_course_admin();
2897
2898
    if (!$is_courseAdmin && $tutor) {
2899
        // If we also want to check if the user is a tutor...
2900
        $is_courseAdmin = $is_courseAdmin || api_is_course_tutor();
2901
    }
2902
2903
    if (!$is_courseAdmin && $coach) {
2904
        // If we also want to check if the user is a coach...';
2905
        // Check if session visibility is read only for coaches.
2906
        if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
2907
            $is_allowed_coach_to_edit = false;
2908
        }
2909
2910
        if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
2911
            // Check if coach is allowed to edit a course.
2912
            $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
2913
        }
2914
    }
2915
2916
    if (!$is_courseAdmin && $session_coach) {
2917
        $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
2918
    }
2919
2920
    // Check if the student_view is enabled, and if so, if it is activated.
2921
    if (api_get_setting('student_view_enabled') == 'true') {
2922
        if (!empty($my_session_id)) {
2923
            // Check if session visibility is read only for coaches.
2924
            if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
2925
                $is_allowed_coach_to_edit = false;
2926
            }
2927
2928
            if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
2929
                // Check if coach is allowed to edit a course.
2930
                $is_allowed = $is_allowed_coach_to_edit;
2931
            } else {
2932
                $is_allowed = false;
2933
            }
2934
            if ($check_student_view) {
2935
                $is_allowed = $is_allowed && $_SESSION['studentview'] != 'studentview';
2936
            }
2937
        } else {
2938
            if ($check_student_view) {
2939
                $is_allowed = $is_courseAdmin && $_SESSION['studentview'] != 'studentview';
2940
            } else {
2941
                $is_allowed = $is_courseAdmin;
2942
            }
2943
        }
2944
2945
        return $is_allowed;
2946
    } else {
2947
2948
        return $is_courseAdmin;
2949
    }
2950
}
2951
2952
/**
2953
 * Returns true if user is a course coach of at least one course in session
2954
 * @param int $sessionId
2955
 * @return bool
2956
 */
2957
function api_is_coach_of_course_in_session($sessionId)
2958
{
2959
    if (api_is_platform_admin()) {
2960
        return true;
2961
    }
2962
2963
    $userId = api_get_user_id();
2964
    $courseList = UserManager::get_courses_list_by_session(
2965
        $userId,
2966
        $sessionId
2967
    );
2968
2969
    // Session visibility.
2970
    $visibility = api_get_session_visibility(
2971
        $sessionId,
2972
        null,
2973
        false
2974
    );
2975
2976 View Code Duplication
    if ($visibility != SESSION_VISIBLE && !empty($courseList)) {
2977
        // Course Coach session visibility.
2978
        $blockedCourseCount = 0;
2979
        $closedVisibilityList = array(
2980
            COURSE_VISIBILITY_CLOSED,
2981
            COURSE_VISIBILITY_HIDDEN
2982
        );
2983
2984
        foreach ($courseList as $course) {
2985
            // Checking session visibility
2986
            $sessionCourseVisibility = api_get_session_visibility(
2987
                $sessionId,
2988
                $course['real_id'],
2989
                $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...
2990
            );
2991
2992
            $courseIsVisible = !in_array(
2993
                $course['visibility'],
2994
                $closedVisibilityList
2995
            );
2996
            if ($courseIsVisible === false || $sessionCourseVisibility == SESSION_INVISIBLE) {
2997
                $blockedCourseCount++;
2998
            }
2999
        }
3000
3001
        // If all courses are blocked then no show in the list.
3002
        if ($blockedCourseCount === count($courseList)) {
3003
            $visibility = SESSION_INVISIBLE;
3004
        } else {
3005
            $visibility = SESSION_VISIBLE;
3006
        }
3007
    }
3008
3009
    switch ($visibility) {
3010
        case SESSION_VISIBLE_READ_ONLY:
3011
        case SESSION_VISIBLE:
3012
        case SESSION_AVAILABLE:
3013
            return true;
3014
            break;
3015
        case SESSION_INVISIBLE:
3016
            return false;
3017
    }
3018
3019
    return false;
3020
}
3021
3022
/**
3023
* Checks if a student can edit contents in a session depending
3024
* on the session visibility
3025
* @param bool $tutor  Whether to check if the user has the tutor role
3026
* @param bool  $coach Whether to check if the user has the coach role
3027
* @return boolean true: the user has the rights to edit, false: he does not
3028
*/
3029
function api_is_allowed_to_session_edit($tutor = false, $coach = false)
3030
{
3031
    if (api_is_allowed_to_edit($tutor, $coach)) {
3032
        // If I'm a teacher, I will return true in order to not affect the normal behaviour of Chamilo tools.
3033
        return true;
3034
    } else {
3035
        if (api_get_session_id() == 0) {
3036
            // I'm not in a session so i will return true to not affect the normal behaviour of Chamilo tools.
3037
            return true;
3038
        } else {
3039
            // I'm in a session and I'm a student
3040
            $session_id = api_get_session_id();
3041
3042
            // Get the session visibility
3043
            $session_visibility = api_get_session_visibility($session_id);
3044
            // if 5 the session is still available
3045
3046
            //@todo We could load the session_rel_course_rel_user permission to increase the level of detail.
3047
            //echo api_get_user_id();
3048
            //echo api_get_course_id();
3049
3050
            switch ($session_visibility) {
3051
                case SESSION_VISIBLE_READ_ONLY: // 1
3052
                    return false;
3053
                case SESSION_VISIBLE:           // 2
3054
                    return true;
3055
                case SESSION_INVISIBLE:         // 3
3056
                    return false;
3057
                case SESSION_AVAILABLE:         //5
3058
                    return true;
3059
            }
3060
        }
3061
    }
3062
}
3063
3064
/**
3065
* Checks whether the user is allowed in a specific tool for a specific action
3066
* @param string $tool the tool we are checking if the user has a certain permission
3067
* @param string $action the action we are checking (add, edit, delete, move, visibility)
3068
* @author Patrick Cool <[email protected]>, Ghent University
3069
* @author Julio Montoya
3070
* @version 1.0
3071
*/
3072
function api_is_allowed($tool, $action, $task_id = 0)
3073
{
3074
    $_user = api_get_user_info();
3075
    $_course = api_get_course_info();
3076
3077
    if (api_is_course_admin()) {
3078
        return true;
3079
    }
3080
    //if (!$_SESSION['total_permissions'][$_course['code']] and $_course)
3081
    if (is_array($_course) and count($_course) > 0) {
3082
        require_once api_get_path(SYS_CODE_PATH).'permissions/permissions_functions.inc.php';
3083
3084
        // Getting the permissions of this user.
3085
        if ($task_id == 0) {
3086
            $user_permissions = get_permissions('user', $_user['user_id']);
3087
            $_SESSION['total_permissions'][$_course['code']] = $user_permissions;
3088
        }
3089
3090
        // Getting the permissions of the task.
3091
        if ($task_id != 0) {
3092
            $task_permissions = get_permissions('task', $task_id);
3093
            /* !!! */$_SESSION['total_permissions'][$_course['code']] = $task_permissions;
3094
        }
3095
        //print_r($_SESSION['total_permissions']);
3096
3097
        // Getting the permissions of the groups of the user
3098
        //$groups_of_user = GroupManager::get_group_ids($_course['db_name'], $_user['user_id']);
3099
3100
        //foreach($groups_of_user as $group)
3101
        //   $this_group_permissions = get_permissions('group', $group);
3102
3103
        // Getting the permissions of the courseroles of the user
3104
        $user_courserole_permissions = get_roles_permissions('user', $_user['user_id']);
3105
3106
        // Getting the permissions of the platformroles of the user
3107
        //$user_platformrole_permissions = get_roles_permissions('user', $_user['user_id'], ', platform');
3108
3109
        // Getting the permissions of the roles of the groups of the user
3110
        //foreach($groups_of_user as $group)
3111
        //    $this_group_courserole_permissions = get_roles_permissions('group', $group);
3112
3113
        // Getting the permissions of the platformroles of the groups of the user
3114
        //foreach($groups_of_user as $group)
3115
        //    $this_group_platformrole_permissions = get_roles_permissions('group', $group, 'platform');
3116
    }
3117
3118
    // If the permissions are limited, we have to map the extended ones to the limited ones.
3119
    if (api_get_setting('permissions') == 'limited') {
3120
        if ($action == 'Visibility') {
3121
            $action = 'Edit';
3122
        }
3123
        if ($action == 'Move') {
3124
            $action = 'Edit';
3125
        }
3126
    }
3127
3128
    // The session that contains all the permissions already exists for this course
3129
    // so there is no need to requery everything.
3130
    //my_print_r($_SESSION['total_permissions'][$_course['code']][$tool]);
3131
    if (is_array($_SESSION['total_permissions'][$_course['code']][$tool])) {
3132
        if (in_array($action, $_SESSION['total_permissions'][$_course['code']][$tool])) {
3133
            return true;
3134
        } else {
3135
            return false;
3136
        }
3137
    }
3138
}
3139
3140
/**
3141
 * Tells whether this user is an anonymous user
3142
 * @param int  $user_id      User ID (optional, will take session ID if not provided)
3143
 * @param bool $db_check     Whether to check in the database (true) or simply in
3144
 * the session (false) to see if the current user is the anonymous user
3145
 * @return bool     true if this user is anonymous, false otherwise
3146
 */
3147
function api_is_anonymous($user_id = null, $db_check = false)
3148
{
3149
    if ($db_check) {
3150
         if (!isset($user_id)) {
3151
            $user_id = api_get_user_id();
3152
        }
3153
        $info = api_get_user_info($user_id);
3154
3155
        if ($info['status'] == 6 || $user_id == 0 || empty($info)) {
3156
            return true;
3157
        }
3158
    }
3159
3160
    $checker = Container::getAuthorizationChecker();
3161
    if ($checker) {
3162
        if ($checker->isGranted('IS_AUTHENTICATED_FULLY')) {
3163
            return false;
3164
        }
3165
    }
3166
3167
    return true;
3168
3169
    $_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...
3170
3171
    if (!isset($_user) || (isset($_user['user_id']) && $_user['user_id'] == 0)) {
3172
        // In some cases, api_set_anonymous doesn't seem to be triggered in local.inc.php. Make sure it is.
3173
        // Occurs in agenda for admin links - YW
3174
        /*global $use_anonymous;
3175
        if (isset($use_anonymous) && $use_anonymous) {*/
3176
        api_set_anonymous();
3177
        //}
3178
        return true;
3179
    }
3180
    return isset($_user['is_anonymous']) && $_user['is_anonymous'] === true;
3181
}
3182
3183
/**
3184
 * Displays message "You are not allowed here..." and exits the entire script.
3185
 * @param bool   $print_headers    Whether or not to print headers (default = false -> does not print them)
3186
 * @param string $message
3187
 */
3188
function api_not_allowed($print_headers = false, $message = null)
3189
{
3190
    if (empty($message)) {
3191
        $message = get_lang('NotAllowed');
3192
    }
3193
    throw new Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException($message);
3194
3195
    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...
3196
        global $osso;
3197
        if ($osso) {
3198
            $osso->logout();
3199
        }
3200
    }
3201
    $home_url = api_get_path(WEB_PATH);
3202
    $user_id = api_get_user_id();
3203
    $course = api_get_course_id();
3204
3205
    global $this_section;
3206
3207
    if (CustomPages::enabled() && !isset($user_id)) {
3208
3209
        if (empty($user_id)) {
3210
            // Why the CustomPages::enabled() need to be to set the request_uri
3211
            $_SESSION['request_uri'] = $_SERVER['REQUEST_URI'];
3212
        }
3213
3214
        CustomPages::display(CustomPages::INDEX_UNLOGGED);
3215
    }
3216
3217
    $origin = isset($_GET['origin']) ? $_GET['origin'] : '';
3218
3219
    $msg = null;
3220
    if (isset($message)) {
3221
        $msg = $message;
3222 View Code Duplication
    } else {
3223
        $msg = Display::return_message(
3224
            get_lang('NotAllowedClickBack').'<br/><br/><a href="'.$home_url.'">'.get_lang('ReturnToCourseHomepage').'</a>',
3225
            'error',
3226
            false
3227
        );
3228
    }
3229
3230
    $msg = Display::div($msg, array('align'=>'center'));
3231
3232
    $show_headers = 0;
3233
3234
    if ($print_headers && $origin != 'learnpath') {
3235
        $show_headers = 1;
3236
    }
3237
3238
    $tpl = new Template(null, $show_headers, $show_headers);
3239
    $tpl->assign('hide_login_link', 1);
3240
    $tpl->assign('content', $msg);
3241
3242
    if (($user_id != 0 && !api_is_anonymous()) &&
3243
        (!isset($course) || $course == -1) &&
3244
        empty($_GET['cidReq'])
3245
    ) {
3246
        // if the access is not authorized and there is some login information
3247
        // but the cidReq is not found, assume we are missing course data and send the user
3248
        // to the user_portal
3249
        $tpl->display_one_col_template();
3250
        exit;
3251
    }
3252
3253
    if (!empty($_SERVER['REQUEST_URI']) &&
3254
        (!empty($_GET['cidReq']) ||
3255
            $this_section == SECTION_MYPROFILE ||
3256
            $this_section == SECTION_PLATFORM_ADMIN
3257
        )
3258
    ) {
3259
        $courseCode = api_get_course_id();
3260
        // Only display form and return to the previous URL if there was a course ID included
3261
        if ($user_id != 0 && !api_is_anonymous()) {
3262
            //if there is a user ID, then the user is not allowed but the session is still there. Say so and exit
3263
            $tpl->assign('content', $msg);
3264
            $tpl->display_one_col_template();
3265
            exit;
3266
        }
3267
3268
        if (!is_null($courseCode)) {
3269
            api_set_firstpage_parameter($courseCode);
3270
        }
3271
3272
        // If the user has no user ID, then his session has expired
3273
        $action = api_get_self().'?'.Security::remove_XSS($_SERVER['QUERY_STRING']);
3274
        $action = str_replace('&amp;', '&', $action);
3275
        $form = new FormValidator(
3276
            'formLogin',
3277
            'post',
3278
            $action,
3279
            null,
3280
            array(),
3281
            FormValidator::LAYOUT_BOX_NO_LABEL
3282
        );
3283
        $form->addElement(
3284
            'text',
3285
            'login',
3286
            null,
3287
            array('placeholder' => get_lang('UserName'), 'autocapitalize' => 'none')
3288
        );
3289
        $form->addElement(
3290
            'password',
3291
            'password',
3292
            null,
3293
            array('placeholder' => get_lang('Password'), 'autocapitalize' => 'none')
3294
        );
3295
        $form->addButton('submitAuth', get_lang('LoginEnter'), '', 'primary');
3296
3297
        // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (above)
3298
        $content = Display::return_message(get_lang('NotAllowed'), 'error', false);
3299
3300
        if (!empty($courseCode)) {
3301
            $content .= '<h4>'.get_lang('LoginToGoToThisCourse').'</h4>';
3302
        }
3303
3304
        if (api_is_cas_activated()) {
3305
            $content .= Display::return_message(sprintf(get_lang('YouHaveAnInstitutionalAccount'), api_get_setting("Institution")), '', false);
3306
            $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'));
3307
            $content .= Display::return_message(get_lang('YouDontHaveAnInstitutionAccount'));
3308
            $content .= "<p style='text-align:center'><a href='#' onclick='$(this).parent().next().toggle()'>".get_lang('LoginWithExternalAccount')."</a></p>";
3309
            $content .= "<div style='display:none;'>";
3310
        }
3311
        $content .= '<div class="well">';
3312
        $content .= $form->returnForm();
3313
        $content .='</div>';
3314
        if (api_is_cas_activated()) {
3315
            $content .= "</div>";
3316
        }
3317
3318
        if (!empty($courseCode)) {
3319
            $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
3320
                get_lang('ReturnToCourseHomepage').'</a></p>';
3321
        } else {
3322
            $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
3323
                get_lang('BackHome').'</a></p>';
3324
        }
3325
3326
        $tpl->setLoginBodyClass();
3327
        $tpl->assign('content', $content);
3328
        $tpl->display_one_col_template();
3329
        exit;
3330
    }
3331
3332
    if ($user_id != 0 && !api_is_anonymous()) {
3333
        $tpl->display_one_col_template();
3334
        exit;
3335
    }
3336
3337
    $msg = null;
3338
3339
    // The session is over and we were not in a course,
3340
    // or we try to get directly to a private course without being logged
3341
    $courseId = api_get_course_int_id();
3342
    if (!empty($courseId)) {
3343
        api_set_firstpage_parameter(api_get_course_id());
3344
        $tpl->setLoginBodyClass();
3345
        $action = api_get_self().'?'.Security::remove_XSS($_SERVER['QUERY_STRING']);
3346
        $action = str_replace('&amp;', '&', $action);
3347
        $form = new FormValidator('formLogin', 'post', $action, null, array('class'=>'form-stacked'));
3348
        $form->addElement('text', 'login', null, array('autocapitalize' => 'none', 'placeholder' => get_lang('UserName'), 'class' => 'col-md-3'));
3349
        $form->addElement('password', 'password', null, array('placeholder' => get_lang('Password'), 'class' => 'col-md-3')); //new
3350
        $form->addButtonNext(get_lang('LoginEnter'), 'submitAuth');
3351
3352
        // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (bellow)
3353
        $msg = Display::return_message(get_lang('NotAllowed'), 'error', false);
3354
        $msg .= '<h4>'.get_lang('LoginToGoToThisCourse').'</h4>';
3355
        $casEnabled = api_is_cas_activated();
3356
        if ($casEnabled) {
3357
            $msg .= Display::return_message(sprintf(get_lang('YouHaveAnInstitutionalAccount'), api_get_setting("Institution")), '', false);
3358
            $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'));
3359
            $msg .= Display::return_message(get_lang('YouDontHaveAnInstitutionAccount'));
3360
            $msg .= "<p style='text-align:center'><a href='#' onclick='$(this).parent().next().toggle()'>".get_lang('LoginWithExternalAccount')."</a></p>";
3361
            $msg .= "<div style='display:none;'>";
3362
        }
3363
        $msg .= '<div class="well">';
3364
        $msg .= $form->returnForm();
3365
        $msg .='</div>';
3366
        if ($casEnabled) {
3367
            $msg .= "</div>";
3368
        }
3369 View Code Duplication
    } else {
3370
        // we were not in a course, return to home page
3371
        $msg = Display::return_message(
3372
            get_lang('NotAllowed').'<br/><br/><a href="'.$home_url.'">'.get_lang('BackHome').'</a><br />',
3373
            'error',
3374
            false
3375
        );
3376
    }
3377
3378
    $tpl->assign('content', $msg);
3379
    $tpl->display_one_col_template();
3380
    exit;
3381
}
3382
3383
/**
3384
 * Gets a UNIX timestamp from a database (MySQL) datetime format string
3385
 * @param $last_post_datetime standard output date in a sql query
3386
 * @return integer timestamp
3387
 * @author Toon Van Hoecke <[email protected]>
3388
 * @version October 2003
3389
 * @desc convert sql date to unix timestamp
3390
 */
3391
function convert_sql_date($last_post_datetime) {
3392
    list ($last_post_date, $last_post_time) = explode(' ', $last_post_datetime);
3393
    list ($year, $month, $day) = explode('-', $last_post_date);
3394
    list ($hour, $min, $sec) = explode(':', $last_post_time);
3395
    return mktime((int)$hour, (int)$min, (int)$sec, (int)$month, (int)$day, (int)$year);
3396
}
3397
3398
/**
3399
 * Gets item visibility from the item_property table
3400
 *
3401
 * Getting the visibility is done by getting the last updated visibility entry,
3402
 * using the largest session ID found if session 0 and another was found (meaning
3403
 * the only one that is actually from the session, in case there are results from
3404
 * session 0 *AND* session n).
3405
 * @param array     Course properties array (result of api_get_course_info())
3406
 * @param string    Tool (learnpath, document, etc)
3407
 * @param int       The item ID in the given tool
3408
 * @param int       The session ID (optional)
3409
 * @param string $tool
3410
 * @param integer $user_id
3411
 * @param string $type
3412
 * @return int      -1 on error, 0 if invisible, 1 if visible
3413
 */
3414
function api_get_item_visibility(
3415
    $_course,
3416
    $tool,
3417
    $id,
3418
    $session = 0,
3419
    $user_id = null,
3420
    $type = null,
3421
    $group_id = null
3422
) {
3423
    if (!is_array($_course) || count($_course) == 0 || empty($tool) || empty($id)) {
3424
        return -1;
3425
    }
3426
3427
    $tool = Database::escape_string($tool);
3428
    $id = intval($id);
3429
    $session = (int) $session;
3430
    $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
3431
    $course_id = intval($_course['real_id']);
3432
3433
    $userCondition = '';
3434
    if (!empty($user_id)) {
3435
        $user_id = intval($user_id);
3436
        $userCondition = " AND to_user_id = $user_id ";
3437
    }
3438
3439
    $typeCondition = '';
3440
    if (!empty($type)) {
3441
        $type = Database::escape_string($type);
3442
        $typeCondition = " AND lastedit_type = '$type' ";
3443
    }
3444
3445
    $groupCondition = '';
3446
    if (!empty($group_id)) {
3447
        $group_id = intval($group_id);
3448
        $groupCondition = " AND to_group_id = '$group_id' ";
3449
    }
3450
3451
    $sql = "SELECT visibility
3452
            FROM $TABLE_ITEMPROPERTY
3453
            WHERE
3454
                c_id = $course_id AND
3455
                tool = '$tool' AND
3456
                ref = $id AND
3457
                (session_id = $session OR session_id = 0 OR session_id IS NULL)
3458
                $userCondition $typeCondition $groupCondition
3459
            ORDER BY session_id DESC, lastedit_date DESC
3460
            LIMIT 1";
3461
3462
    $res = Database::query($sql);
3463
    if ($res === false || Database::num_rows($res) == 0) {
3464
        return -1;
3465
    }
3466
    $row = Database::fetch_array($res);
3467
3468
    return $row['visibility'];
3469
}
3470
3471
/**
3472
 * Delete a row in the c_item_property table
3473
 *
3474
 * @param array $courseInfo
3475
 * @param string $tool
3476
 * @param int $itemId
3477
 * @param int $userId
3478
 * @param int $groupId
3479
 * @param int $sessionId
3480
 * @return false|null
3481
 */
3482
function api_item_property_delete(
3483
    $courseInfo,
3484
    $tool,
3485
    $itemId,
3486
    $userId,
3487
    $groupId = 0,
3488
    $sessionId = 0
3489
) {
3490
    if (empty($courseInfo)) {
3491
        return false;
3492
    }
3493
3494
    $courseId = intval($courseInfo['real_id']);
3495
3496
    if (empty($courseId) || empty($tool) || empty($itemId)) {
3497
        return false;
3498
    }
3499
3500
    $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3501
    $tool = Database::escape_string($tool);
3502
    $itemId = intval($itemId);
3503
    $userId = intval($userId);
3504
    $groupId = intval($groupId);
3505
    $sessionId = intval($sessionId);
3506
3507
    $groupCondition = " AND to_group_id = $groupId ";
3508
    if (empty($groupId)) {
3509
        $groupCondition = " AND (to_group_id is NULL OR to_group_id = 0) ";
3510
    }
3511
3512
    $userCondition = " AND to_user_id = $userId ";
3513
    if (empty($userId)) {
3514
        $userCondition = " AND (to_user_id is NULL OR to_user_id = 0) ";
3515
    }
3516
    $sessionCondition = api_get_session_condition($sessionId, true, false, 'session_id');
3517
    $sql = "DELETE FROM $table
3518
            WHERE
3519
                c_id = $courseId AND
3520
                tool  = '$tool' AND
3521
                ref = $itemId
3522
                $sessionCondition
3523
                $userCondition
3524
                $groupCondition
3525
            ";
3526
3527
    Database::query($sql);
3528
}
3529
3530
/**
3531
 * Updates or adds item properties to the Item_propetry table
3532
 * Tool and lastedit_type are language independant strings (langvars->get_lang!)
3533
 *
3534
 * @param array $_course array with course properties
3535
 * @param string $tool tool id, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
3536
 * @param int $item_id id of the item itself, linked to key of every tool ('id', ...)
3537
 * @param string $last_edit_type add or update action
3538
 * (1) message to be translated (in trad4all) : e.g. DocumentAdded, DocumentUpdated;
3539
 * (2) "delete"
3540
 * (3) "visible"
3541
 * (4) "invisible"
3542
 * @param int $user_id id of the editing/adding user
3543
 * @param int $to_group_id group.iid
3544
 * @param int $to_user_id id of the intended user (always has priority over $to_group_id !), only relevant for $type (1)
3545
 * @param string $start_visible 0000-00-00 00:00:00 format
3546
 * @param string $end_visible 0000-00-00 00:00:00 format
3547
 * @param int $session_id The session ID, if any, otherwise will default to 0
3548
 * @return boolean False if update fails.
3549
 * @author Toon Van Hoecke <[email protected]>, Ghent University
3550
 * @version January 2005
3551
 * @desc update the item_properties table (if entry not exists, insert) of the course
3552
 */
3553
function api_item_property_update(
3554
    $_course,
3555
    $tool,
3556
    $item_id,
3557
    $last_edit_type,
3558
    $user_id,
3559
    $to_group_id = 0,
3560
    $to_user_id = null,
3561
    $start_visible = '',
3562
    $end_visible = '',
3563
    $session_id = 0
3564
) {
3565
    if (empty($_course)) {
3566
        return false;
3567
    }
3568
3569
    $course_id = $_course['real_id'];
3570
3571
    if (empty($course_id)) {
3572
        return false;
3573
    }
3574
3575
    $em = Database::getManager();
3576
3577
    // Definition of variables.
3578
    $tool = Database::escape_string($tool);
3579
    $item_id = intval($item_id);
3580
    $lastEditTypeNoFilter = $last_edit_type;
3581
    $last_edit_type = Database::escape_string($last_edit_type);
3582
    $user_id = intval($user_id);
3583
3584
    $startVisible = "NULL";
3585
    if (!empty($start_visible)) {
3586
        $start_visible = Database::escape_string($start_visible);
3587
        $startVisible = "'$start_visible'";
3588
    }
3589
3590
    $endVisible = "NULL";
3591
    if (!empty($end_visible)) {
3592
        $end_visible = Database::escape_string($end_visible);
3593
        $endVisible = "'$end_visible'";
3594
    }
3595
3596
    $to_filter = '';
3597
    $time = api_get_utc_datetime();
3598
3599
    if (!empty($session_id)) {
3600
        $session_id = intval($session_id);
3601
    } else {
3602
        $session_id = api_get_session_id();
3603
    }
3604
3605
    // Definition of tables.
3606
    $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
3607
3608
    if ($to_user_id <= 0) {
3609
        $to_user_id = null; // No to_user_id set
3610
    }
3611
3612
    if (!is_null($to_user_id)) {
3613
        // $to_user_id has more priority than $to_group_id
3614
        $to_user_id = intval($to_user_id);
3615
        $to_field = 'to_user_id';
3616
        $to_value = $to_user_id;
3617
    } else {
3618
        // $to_user_id is not set.
3619
        $to_field = 'to_group_id';
3620
        $to_value = $to_group_id;
3621
    }
3622
3623
    $toValueCondition = empty($to_value) ? "NULL" : "'$to_value'";
3624
3625
    // Set filters for $to_user_id and $to_group_id, with priority for $to_user_id
3626
    $condition_session = " AND session_id = $session_id ";
3627
    if (empty($session_id)) {
3628
        $condition_session = " AND (session_id = 0 OR session_id IS NULL) ";
3629
    }
3630
3631
    $filter = " c_id = $course_id AND tool = '$tool' AND ref = $item_id $condition_session ";
3632
3633
    // Check whether $to_user_id and $to_group_id are passed in the function call.
3634
    // If both are not passed (both are null) then it is a message for everybody and $to_group_id should be 0 !
3635
    if (is_null($to_user_id) && is_null($to_group_id)) {
3636
        $to_group_id = 0;
3637
    }
3638
3639
    if (!is_null($to_user_id)) {
3640
        // Set filter to intended user.
3641
        $to_filter = " AND to_user_id = $to_user_id $condition_session";
3642
    } else {
3643
        // Set filter to intended group.
3644
        if (($to_group_id != 0) && $to_group_id == strval(intval($to_group_id))) {
3645
            $to_filter = " AND to_group_id = $to_group_id $condition_session";
3646
        }
3647
    }
3648
3649
    // Adding filter if set.
3650
    $filter .= $to_filter;
3651
3652
    // Update if possible
3653
    $set_type = '';
3654
3655
    switch ($lastEditTypeNoFilter) {
3656 View Code Duplication
        case 'delete':
3657
            // delete = make item only visible for the platform admin.
3658
            $visibility = '2';
3659
            if (!empty($session_id)) {
3660
                // Check whether session id already exist into item_properties for updating visibility or add it.
3661
                $sql = "SELECT session_id FROM $tableItemProperty
3662
                        WHERE
3663
                            c_id = $course_id AND
3664
                            tool = '$tool' AND
3665
                            ref = $item_id AND
3666
                            session_id = $session_id";
3667
                $rs = Database::query($sql);
3668
                if (Database::num_rows($rs) > 0) {
3669
                    $sql = "UPDATE $tableItemProperty
3670
                            SET lastedit_type       = '".str_replace('_', '', ucwords($tool))."Deleted',
3671
                                lastedit_date       = '$time',
3672
                                lastedit_user_id    = $user_id,
3673
                                visibility          = $visibility,
3674
                                session_id          = $session_id $set_type
3675
                            WHERE $filter";
3676
                    $result = Database::query($sql);
3677
                } else {
3678
                    $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)
3679
                            VALUES ($course_id, '$tool',$item_id, '$time', $user_id, '$time', '$last_edit_type',$user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3680
                    $result = Database::query($sql);
3681
                    $id = Database::insert_id();
3682
                    if ($id) {
3683
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3684
                        Database::query($sql);
3685
                    }
3686
                }
3687
            } else {
3688
                $sql = "UPDATE $tableItemProperty
3689
                        SET
3690
                            lastedit_type='".str_replace('_', '', ucwords($tool))."Deleted',
3691
                            lastedit_date='$time',
3692
                            lastedit_user_id = $user_id,
3693
                            visibility = $visibility $set_type
3694
                        WHERE $filter";
3695
                $result = Database::query($sql);
3696
            }
3697
            break;
3698 View Code Duplication
        case 'visible' : // Change item to visible.
3699
            $visibility = '1';
3700
            if (!empty($session_id)) {
3701
                // Check whether session id already exist into item_properties for updating visibility or add it.
3702
                $sql = "SELECT session_id FROM $tableItemProperty
3703
                        WHERE
3704
                            c_id = $course_id AND
3705
                            tool = '$tool' AND
3706
                            ref = $item_id AND
3707
                            session_id = $session_id";
3708
                $rs = Database::query($sql);
3709
                if (Database::num_rows($rs) > 0) {
3710
                    $sql = "UPDATE $tableItemProperty
3711
                            SET
3712
                                lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
3713
                                lastedit_date='$time',
3714
                                lastedit_user_id = $user_id,
3715
                                visibility = $visibility,
3716
                                session_id = $session_id $set_type
3717
                            WHERE $filter";
3718
                    $result = Database::query($sql);
3719
                } else {
3720
                    $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)
3721
                            VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3722
                    $result = Database::query($sql);
3723
                    $id = Database::insert_id();
3724
                    if ($id) {
3725
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3726
                        Database::query($sql);
3727
                    }
3728
                }
3729
            } else {
3730
                $sql = "UPDATE $tableItemProperty
3731
                        SET
3732
                            lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
3733
                            lastedit_date='$time',
3734
                            lastedit_user_id = $user_id,
3735
                            visibility = $visibility $set_type
3736
                        WHERE $filter";
3737
                $result = Database::query($sql);
3738
            }
3739
            break;
3740 View Code Duplication
        case 'invisible' : // Change item to invisible.
3741
            $visibility = '0';
3742
            if (!empty($session_id)) {
3743
                // Check whether session id already exist into item_properties for updating visibility or add it
3744
                $sql = "SELECT session_id FROM $tableItemProperty
3745
                        WHERE
3746
                            c_id = $course_id AND
3747
                            tool = '$tool' AND
3748
                            ref = $item_id AND
3749
                            session_id = $session_id";
3750
                $rs = Database::query($sql);
3751
                if (Database::num_rows($rs) > 0) {
3752
                    $sql = "UPDATE $tableItemProperty
3753
                            SET
3754
                                lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
3755
                                lastedit_date = '$time',
3756
                                lastedit_user_id = $user_id,
3757
                                visibility = $visibility,
3758
                                session_id = $session_id $set_type
3759
                            WHERE $filter";
3760
                    $result = Database::query($sql);
3761
                } else {
3762
                    $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)
3763
                            VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3764
                    $result = Database::query($sql);
3765
                    $id = Database::insert_id();
3766
                    if ($id) {
3767
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3768
                        Database::query($sql);
3769
                    }
3770
                }
3771
            } else {
3772
                $sql = "UPDATE $tableItemProperty
3773
                        SET
3774
                            lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
3775
                            lastedit_date = '$time',
3776
                            lastedit_user_id = $user_id,
3777
                            visibility = $visibility $set_type
3778
                        WHERE $filter";
3779
                $result = Database::query($sql);
3780
            }
3781
            break;
3782
        default: // The item will be added or updated.
3783
            $set_type = ", lastedit_type = '$last_edit_type' ";
3784
            $visibility = '1';
3785
            //$filter .= $to_filter; already added
3786
            $sql = "UPDATE $tableItemProperty
3787
                    SET
3788
                      lastedit_date = '$time',
3789
                      lastedit_user_id = $user_id $set_type
3790
                    WHERE $filter";
3791
            $result = Database::query($sql);
3792
    }
3793
3794
    // Insert if no entries are found (can only happen in case of $last_edit_type switch is 'default').
3795
    if ($result == false || Database::affected_rows($result) == 0) {
0 ignored issues
show
Bug introduced by
It seems like $result can be null; however, affected_rows() does not accept null, maybe add an additional type check?

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

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

function doesNotAcceptNull(stdClass $x) { }

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

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

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

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

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

function doesNotAcceptNull(stdClass $x) { }

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

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

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

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

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

function doesNotAcceptNull(stdClass $x) { }

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

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

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