Completed
Push — master ( 83f4f4...7038dd )
by Julito
11:28
created

api_get_setting()   B

Complexity

Conditions 10
Paths 15

Size

Total Lines 58
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 28
c 0
b 0
f 0
nc 15
nop 1
dl 0
loc 58
rs 7.6666

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CoreBundle\Entity\AccessUrl;
5
use Chamilo\CoreBundle\Entity\Course;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Course. Consider defining an alias.

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

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
1063
            isset($course_info['registration_code']) &&
1064
            !empty($course_info['registration_code'])
1065
        ) {
1066
            $is_visible = false;
1067
        }
1068
    }
1069
1070
    if (!empty($checkTool)) {
1071
        if (!api_is_allowed_to_edit(true, true, true)) {
1072
            $toolInfo = api_get_tool_information_by_name($checkTool);
1073
            if (!empty($toolInfo) && isset($toolInfo['visibility']) && 0 == $toolInfo['visibility']) {
1074
                api_not_allowed(true);
1075
1076
                return false;
1077
            }
1078
        }
1079
    }
1080
1081
    // Check session visibility
1082
    $session_id = api_get_session_id();
1083
1084
    if (!empty($session_id)) {
1085
        // $isAllowedInCourse was set in local.inc.php
1086
        if (!$isAllowedInCourse) {
1087
            $is_visible = false;
1088
        }
1089
    }
1090
1091
    if (!$is_visible) {
1092
        api_not_allowed($print_headers);
1093
1094
        return false;
1095
    }
1096
1097
    return true;
1098
}
1099
1100
/**
1101
 * Function used to protect an admin script.
1102
 *
1103
 * The function blocks access when the user has no platform admin rights
1104
 * with an error message printed on default output
1105
 *
1106
 * @param bool Whether to allow session admins as well
1107
 * @param bool Whether to allow HR directors as well
1108
 * @param string An optional message (already passed through get_lang)
1109
 *
1110
 * @return bool True if user is allowed, false otherwise.
1111
 *              The function also outputs an error message in case not allowed
1112
 *
1113
 * @author Roan Embrechts (original author)
1114
 */
1115
function api_protect_admin_script($allow_sessions_admins = false, $allow_drh = false, $message = null)
1116
{
1117
    if (!api_is_platform_admin($allow_sessions_admins, $allow_drh)) {
1118
        api_not_allowed(true, $message);
1119
1120
        return false;
1121
    }
1122
1123
    return true;
1124
}
1125
1126
/**
1127
 * Function used to protect a teacher script.
1128
 * The function blocks access when the user has no teacher rights.
1129
 *
1130
 * @return bool True if the current user can access the script, false otherwise
1131
 *
1132
 * @author Yoselyn Castillo
1133
 */
1134
function api_protect_teacher_script()
1135
{
1136
    if (!api_is_allowed_to_edit()) {
1137
        api_not_allowed(true);
1138
1139
        return false;
1140
    }
1141
1142
    return true;
1143
}
1144
1145
/**
1146
 * Function used to prevent anonymous users from accessing a script.
1147
 *
1148
 * @param bool|true $printHeaders
1149
 *
1150
 * @author Roan Embrechts
1151
 *
1152
 * @return bool
1153
 */
1154
function api_block_anonymous_users($printHeaders = true)
1155
{
1156
    $user = api_get_user_info();
1157
1158
    if (!(isset($user['user_id']) && $user['user_id']) || api_is_anonymous($user['user_id'], true)) {
1159
        api_not_allowed($printHeaders);
1160
1161
        return false;
1162
    }
1163
1164
    return true;
1165
}
1166
1167
/**
1168
 * Returns a rough evaluation of the browser's name and version based on very
1169
 * simple regexp.
1170
 *
1171
 * @return array with the navigator name and version ['name' => '...', 'version' => '...']
1172
 */
1173
function api_get_navigator()
1174
{
1175
    $navigator = 'Unknown';
1176
    $version = 0;
1177
1178
    if (!isset($_SERVER['HTTP_USER_AGENT'])) {
1179
        return ['name' => 'Unknown', 'version' => '0.0.0'];
1180
    }
1181
1182
    if (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Opera')) {
1183
        $navigator = 'Opera';
1184
        list(, $version) = explode('Opera', $_SERVER['HTTP_USER_AGENT']);
1185
    } elseif (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Edge')) {
1186
        $navigator = 'Edge';
1187
        list(, $version) = explode('Edge', $_SERVER['HTTP_USER_AGENT']);
1188
    } elseif (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE')) {
1189
        $navigator = 'Internet Explorer';
1190
        list(, $version) = explode('MSIE ', $_SERVER['HTTP_USER_AGENT']);
1191
    } elseif (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome')) {
1192
        $navigator = 'Chrome';
1193
        list(, $version) = explode('Chrome', $_SERVER['HTTP_USER_AGENT']);
1194
    } elseif (false !== stripos($_SERVER['HTTP_USER_AGENT'], 'Safari')) {
1195
        $navigator = 'Safari';
1196
        if (false !== stripos($_SERVER['HTTP_USER_AGENT'], 'Version/')) {
1197
            // If this Safari does have the "Version/" string in its user agent
1198
            // then use that as a version indicator rather than what's after
1199
            // "Safari/" which is rather a "build number" or something
1200
            list(, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1201
        } else {
1202
            list(, $version) = explode('Safari/', $_SERVER['HTTP_USER_AGENT']);
1203
        }
1204
    } elseif (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Firefox')) {
1205
        $navigator = 'Firefox';
1206
        list(, $version) = explode('Firefox', $_SERVER['HTTP_USER_AGENT']);
1207
    } elseif (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Netscape')) {
1208
        $navigator = 'Netscape';
1209
        if (false !== stripos($_SERVER['HTTP_USER_AGENT'], 'Netscape/')) {
1210
            list(, $version) = explode('Netscape', $_SERVER['HTTP_USER_AGENT']);
1211
        } else {
1212
            list(, $version) = explode('Navigator', $_SERVER['HTTP_USER_AGENT']);
1213
        }
1214
    } elseif (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Konqueror')) {
1215
        $navigator = 'Konqueror';
1216
        list(, $version) = explode('Konqueror', $_SERVER['HTTP_USER_AGENT']);
1217
    } elseif (false !== stripos($_SERVER['HTTP_USER_AGENT'], 'applewebkit')) {
1218
        $navigator = 'AppleWebKit';
1219
        list(, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1220
    } elseif (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Gecko')) {
1221
        $navigator = 'Mozilla';
1222
        list(, $version) = explode('; rv:', $_SERVER['HTTP_USER_AGENT']);
1223
    }
1224
1225
    // Now cut extra stuff around (mostly *after*) the version number
1226
    $version = preg_replace('/^([\/\s])?([\d\.]+)?.*/', '\2', $version);
1227
1228
    if (false === strpos($version, '.')) {
1229
        $version = number_format(doubleval($version), 1);
1230
    }
1231
    $return = ['name' => $navigator, 'version' => $version];
1232
1233
    return $return;
1234
}
1235
1236
/**
1237
 * @return true if user self registration is allowed, false otherwise
1238
 */
1239
function api_is_self_registration_allowed()
1240
{
1241
    return isset($GLOBALS['allowSelfReg']) ? $GLOBALS['allowSelfReg'] : false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return IssetNode ? $GLOB...'allowSelfReg'] : false could also return false which is incompatible with the documented return type true. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
1242
}
1243
1244
/**
1245
 * This function returns the id of the user which is stored in the $_user array.
1246
 *
1247
 * example: The function can be used to check if a user is logged in
1248
 *          if (api_get_user_id())
1249
 *
1250
 * @return int the id of the current user, 0 if is empty
1251
 */
1252
function api_get_user_id()
1253
{
1254
    $userInfo = Session::read('_user');
1255
    if ($userInfo && isset($userInfo['user_id'])) {
1256
        return (int) $userInfo['user_id'];
1257
    }
1258
1259
    return 0;
1260
}
1261
1262
/**
1263
 * Gets the list of courses a specific user is subscribed to.
1264
 *
1265
 * @param int       User ID
1266
 * @param bool $fetch_session Whether to get session courses or not - NOT YET IMPLEMENTED
1267
 *
1268
 * @return array Array of courses in the form [0]=>('code'=>xxx,'db'=>xxx,'dir'=>xxx,'status'=>d)
1269
 *
1270
 * @deprecated use CourseManager::get_courses_list_by_user_id()
1271
 */
1272
function api_get_user_courses($userId, $fetch_session = true)
1273
{
1274
    // Get out if not integer
1275
    if ($userId != strval(intval($userId))) {
1276
        return [];
1277
    }
1278
1279
    $t_course = Database::get_main_table(TABLE_MAIN_COURSE);
1280
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1281
1282
    $sql = "SELECT cc.id as real_id, cc.code code, cc.directory dir, cu.status status
1283
            FROM $t_course cc, $t_course_user cu
1284
            WHERE
1285
                cc.id = cu.c_id AND
1286
                cu.user_id = $userId AND
1287
                cu.relation_type <> ".COURSE_RELATION_TYPE_RRHH;
1288
    $result = Database::query($sql);
1289
    if (false === $result) {
1290
        return [];
1291
    }
1292
1293
    $courses = [];
1294
    while ($row = Database::fetch_array($result)) {
1295
        // we only need the database name of the course
1296
        $courses[] = $row;
1297
    }
1298
1299
    return $courses;
1300
}
1301
1302
/**
1303
 * Formats user information into a standard array
1304
 * This function should be only used inside api_get_user_info().
1305
 *
1306
 * @param array Non-standard user array
0 ignored issues
show
Documentation Bug introduced by
The doc comment Non-standard at position 0 could not be parsed: Unknown type name 'Non-standard' at position 0 in Non-standard.
Loading history...
1307
 * @param bool $add_password
1308
 * @param bool $loadAvatars  turn off to improve performance
1309
 *
1310
 * @return array Standard user array
1311
 */
1312
function _api_format_user($user, $add_password = false, $loadAvatars = true)
1313
{
1314
    $result = [];
1315
1316
    if (!isset($user['user_id'])) {
1317
        return [];
1318
    }
1319
1320
    $result['firstname'] = null;
1321
    $result['lastname'] = null;
1322
1323
    if (isset($user['firstname']) && isset($user['lastname'])) {
1324
        // with only lowercase
1325
        $result['firstname'] = $user['firstname'];
1326
        $result['lastname'] = $user['lastname'];
1327
    } elseif (isset($user['firstName']) && isset($user['lastName'])) {
1328
        // with uppercase letters
1329
        $result['firstname'] = isset($user['firstName']) ? $user['firstName'] : null;
1330
        $result['lastname'] = isset($user['lastName']) ? $user['lastName'] : null;
1331
    }
1332
1333
    if (isset($user['email'])) {
1334
        $result['mail'] = isset($user['email']) ? $user['email'] : null;
1335
        $result['email'] = isset($user['email']) ? $user['email'] : null;
1336
    } else {
1337
        $result['mail'] = isset($user['mail']) ? $user['mail'] : null;
1338
        $result['email'] = isset($user['mail']) ? $user['mail'] : null;
1339
    }
1340
1341
    $result['complete_name'] = api_get_person_name($result['firstname'], $result['lastname']);
1342
    $result['complete_name_with_username'] = $result['complete_name'];
1343
1344
    if (!empty($user['username']) && 'false' === api_get_setting('profile.hide_username_with_complete_name')) {
1345
        $result['complete_name_with_username'] = $result['complete_name'].' ('.$user['username'].')';
1346
    }
1347
1348
    $showEmail = 'true' === api_get_setting('show_email_addresses');
1349
    if (!empty($user['email'])) {
1350
        $result['complete_name_with_email_forced'] = $result['complete_name'].' ('.$user['email'].')';
1351
        if ($showEmail) {
1352
            $result['complete_name_with_email'] = $result['complete_name'].' ('.$user['email'].')';
1353
        }
1354
    } else {
1355
        $result['complete_name_with_email'] = $result['complete_name'];
1356
        $result['complete_name_with_email_forced'] = $result['complete_name'];
1357
    }
1358
1359
    // Kept for historical reasons
1360
    $result['firstName'] = $result['firstname'];
1361
    $result['lastName'] = $result['lastname'];
1362
1363
    $attributes = [
1364
        'phone',
1365
        'address',
1366
        'picture_uri',
1367
        'official_code',
1368
        'status',
1369
        'active',
1370
        'auth_source',
1371
        'username',
1372
        'theme',
1373
        'language',
1374
        'creator_id',
1375
        'registration_date',
1376
        'hr_dept_id',
1377
        'expiration_date',
1378
        'last_login',
1379
        'user_is_online',
1380
    ];
1381
1382
    if ('true' === api_get_setting('extended_profile')) {
1383
        $attributes[] = 'competences';
1384
        $attributes[] = 'diplomas';
1385
        $attributes[] = 'teach';
1386
        $attributes[] = 'openarea';
1387
    }
1388
1389
    foreach ($attributes as $attribute) {
1390
        $result[$attribute] = isset($user[$attribute]) ? $user[$attribute] : null;
1391
    }
1392
1393
    $user_id = (int) $user['user_id'];
1394
    // Maintain the user_id index for backwards compatibility
1395
    $result['user_id'] = $result['id'] = $user_id;
1396
1397
    $hasCertificates = Certificate::getCertificateByUser($user_id);
1398
    $result['has_certificates'] = 0;
1399
    if (!empty($hasCertificates)) {
1400
        $result['has_certificates'] = 1;
1401
    }
1402
1403
    $result['icon_status'] = '';
1404
    $result['icon_status_medium'] = '';
1405
    $result['is_admin'] = UserManager::is_admin($user_id);
1406
1407
    // Getting user avatar.
1408
    if ($loadAvatars) {
1409
        $result['avatar'] = '';
1410
        $result['avatar_no_query'] = '';
1411
        $result['avatar_small'] = '';
1412
        $result['avatar_medium'] = '';
1413
1414
        /*if (!isset($user['avatar'])) {
1415
            $originalFile = UserManager::getUserPicture(
1416
                $user_id,
1417
                USER_IMAGE_SIZE_ORIGINAL,
1418
                null,
1419
                $result
1420
            );
1421
            $result['avatar'] = $originalFile;
1422
            $avatarString = explode('?', $result['avatar']);
1423
            $result['avatar_no_query'] = reset($avatarString);
1424
        } else {
1425
            $result['avatar'] = $user['avatar'];
1426
            $avatarString = explode('?', $user['avatar']);
1427
            $result['avatar_no_query'] = reset($avatarString);
1428
        }
1429
1430
        if (!isset($user['avatar_small'])) {
1431
            $smallFile = UserManager::getUserPicture(
1432
                $user_id,
1433
                USER_IMAGE_SIZE_SMALL,
1434
                null,
1435
                $result
1436
            );
1437
            $result['avatar_small'] = $smallFile;
1438
        } else {
1439
            $result['avatar_small'] = $user['avatar_small'];
1440
        }
1441
1442
        if (!isset($user['avatar_medium'])) {
1443
            $mediumFile = UserManager::getUserPicture(
1444
                $user_id,
1445
                USER_IMAGE_SIZE_MEDIUM,
1446
                null,
1447
                $result
1448
            );
1449
            $result['avatar_medium'] = $mediumFile;
1450
        } else {
1451
            $result['avatar_medium'] = $user['avatar_medium'];
1452
        }*/
1453
1454
        $urlImg = api_get_path(WEB_IMG_PATH);
1455
        $iconStatus = '';
1456
        $iconStatusMedium = '';
1457
1458
        switch ($result['status']) {
1459
            case STUDENT:
1460
                if ($result['has_certificates']) {
1461
                    $iconStatus = $urlImg.'icons/svg/identifier_graduated.svg';
1462
                } else {
1463
                    $iconStatus = $urlImg.'icons/svg/identifier_student.svg';
1464
                }
1465
                break;
1466
            case COURSEMANAGER:
1467
                if ($result['is_admin']) {
1468
                    $iconStatus = $urlImg.'icons/svg/identifier_admin.svg';
1469
                } else {
1470
                    $iconStatus = $urlImg.'icons/svg/identifier_teacher.svg';
1471
                }
1472
                break;
1473
            case STUDENT_BOSS:
1474
                $iconStatus = $urlImg.'icons/svg/identifier_teacher.svg';
1475
                break;
1476
        }
1477
1478
        if (!empty($iconStatus)) {
1479
            $iconStatusMedium = '<img src="'.$iconStatus.'" width="32px" height="32px">';
1480
            $iconStatus = '<img src="'.$iconStatus.'" width="22px" height="22px">';
1481
        }
1482
1483
        $result['icon_status'] = $iconStatus;
1484
        $result['icon_status_medium'] = $iconStatusMedium;
1485
    }
1486
1487
    if (isset($user['user_is_online'])) {
1488
        $result['user_is_online'] = true == $user['user_is_online'] ? 1 : 0;
1489
    }
1490
    if (isset($user['user_is_online_in_chat'])) {
1491
        $result['user_is_online_in_chat'] = (int) $user['user_is_online_in_chat'];
1492
    }
1493
1494
    if ($add_password) {
1495
        $result['password'] = $user['password'];
1496
    }
1497
1498
    if (isset($result['profile_completed'])) {
1499
        $result['profile_completed'] = $user['profile_completed'];
1500
    }
1501
1502
    $result['profile_url'] = api_get_path(WEB_CODE_PATH).'social/profile.php?u='.$user_id;
1503
1504
    // Send message link
1505
    $sendMessage = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&user_id='.$user_id;
1506
    $result['complete_name_with_message_link'] = Display::url(
1507
        $result['complete_name_with_username'],
1508
        $sendMessage,
1509
        ['class' => 'ajax']
1510
    );
1511
1512
    if (isset($user['extra'])) {
1513
        $result['extra'] = $user['extra'];
1514
    }
1515
1516
    return $result;
1517
}
1518
1519
/**
1520
 * Finds all the information about a user.
1521
 * If no parameter is passed you find all the information about the current user.
1522
 *
1523
 * @param int  $user_id
1524
 * @param bool $checkIfUserOnline
1525
 * @param bool $showPassword
1526
 * @param bool $loadExtraData
1527
 * @param bool $loadOnlyVisibleExtraData Get the user extra fields that are visible
1528
 * @param bool $loadAvatars              turn off to improve performance and if avatars are not needed
1529
 * @param bool $updateCache              update apc cache if exists
1530
 *
1531
 * @return mixed $user_info user_id, lastname, firstname, username, email, etc or false on error
1532
 *
1533
 * @author Patrick Cool <[email protected]>
1534
 * @author Julio Montoya
1535
 *
1536
 * @version 21 September 2004
1537
 */
1538
function api_get_user_info(
1539
    $user_id = 0,
1540
    $checkIfUserOnline = false,
1541
    $showPassword = false,
1542
    $loadExtraData = false,
1543
    $loadOnlyVisibleExtraData = false,
1544
    $loadAvatars = true,
1545
    $updateCache = false
1546
) {
1547
    // Make sure user_id is safe
1548
    $user_id = (int) $user_id;
1549
    $user = false;
1550
    if (empty($user_id)) {
1551
        $userFromSession = Session::read('_user');
1552
        if (isset($userFromSession) && !empty($userFromSession)) {
1553
            return $userFromSession;
1554
            /*
1555
            return _api_format_user(
1556
                $userFromSession,
1557
                $showPassword,
1558
                $loadAvatars
1559
            );*/
1560
        }
1561
1562
        return false;
1563
    }
1564
1565
    $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_USER)."
1566
            WHERE id = $user_id";
1567
    $result = Database::query($sql);
1568
    if (Database::num_rows($result) > 0) {
1569
        $result_array = Database::fetch_array($result);
1570
        $result_array['user_is_online_in_chat'] = 0;
1571
        if ($checkIfUserOnline) {
1572
            $use_status_in_platform = user_is_online($user_id);
1573
            $result_array['user_is_online'] = $use_status_in_platform;
1574
            $user_online_in_chat = 0;
1575
            if ($use_status_in_platform) {
1576
                $user_status = UserManager::get_extra_user_data_by_field(
1577
                    $user_id,
1578
                    'user_chat_status',
1579
                    false,
1580
                    true
1581
                );
1582
                if (1 == (int) $user_status['user_chat_status']) {
1583
                    $user_online_in_chat = 1;
1584
                }
1585
            }
1586
            $result_array['user_is_online_in_chat'] = $user_online_in_chat;
1587
        }
1588
1589
        if ($loadExtraData) {
1590
            $fieldValue = new ExtraFieldValue('user');
1591
            $result_array['extra'] = $fieldValue->getAllValuesForAnItem(
1592
                $user_id,
1593
                $loadOnlyVisibleExtraData
1594
            );
1595
        }
1596
        $user = _api_format_user($result_array, $showPassword, $loadAvatars);
1597
    }
1598
1599
    return $user;
1600
}
1601
1602
function api_get_user_info_from_entity(
1603
    User $user,
1604
    $checkIfUserOnline = false,
1605
    $showPassword = false,
1606
    $loadExtraData = false,
1607
    $loadOnlyVisibleExtraData = false,
1608
    $loadAvatars = true,
1609
    $loadCertificate = false
1610
) {
1611
    if (!$user instanceof UserInterface) {
1612
        return false;
1613
    }
1614
1615
    // Make sure user_id is safe
1616
    $user_id = (int) $user->getId();
1617
1618
    if (empty($user_id)) {
1619
        $userFromSession = Session::read('_user');
1620
1621
        if (isset($userFromSession) && !empty($userFromSession)) {
1622
            return $userFromSession;
1623
        }
1624
1625
        return false;
1626
    }
1627
1628
    $result = [];
1629
    $result['user_is_online_in_chat'] = 0;
1630
    if ($checkIfUserOnline) {
1631
        $use_status_in_platform = user_is_online($user_id);
1632
        $result['user_is_online'] = $use_status_in_platform;
1633
        $user_online_in_chat = 0;
1634
        if ($use_status_in_platform) {
1635
            $user_status = UserManager::get_extra_user_data_by_field(
1636
                $user_id,
1637
                'user_chat_status',
1638
                false,
1639
                true
1640
            );
1641
            if (1 == (int) $user_status['user_chat_status']) {
1642
                $user_online_in_chat = 1;
1643
            }
1644
        }
1645
        $result['user_is_online_in_chat'] = $user_online_in_chat;
1646
    }
1647
1648
    if ($loadExtraData) {
1649
        $fieldValue = new ExtraFieldValue('user');
1650
        $result['extra'] = $fieldValue->getAllValuesForAnItem(
1651
            $user_id,
1652
            $loadOnlyVisibleExtraData
1653
        );
1654
    }
1655
1656
    $result['username'] = $user->getUsername();
1657
    $result['status'] = $user->getStatus();
1658
    $result['firstname'] = $user->getFirstname();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $result['firstname'] is correct as $user->getFirstname() targeting Chamilo\CoreBundle\Entity\User::getFirstname() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
1659
    $result['lastname'] = $user->getLastname();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $result['lastname'] is correct as $user->getLastname() targeting Chamilo\CoreBundle\Entity\User::getLastname() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
1660
    $result['email'] = $result['mail'] = $user->getEmail();
1661
    $result['complete_name'] = api_get_person_name($result['firstname'], $result['lastname']);
1662
    $result['complete_name_with_username'] = $result['complete_name'];
1663
1664
    if (!empty($result['username']) && 'false' === api_get_setting('profile.hide_username_with_complete_name')) {
1665
        $result['complete_name_with_username'] = $result['complete_name'].' ('.$result['username'].')';
1666
    }
1667
1668
    $showEmail = 'true' === api_get_setting('show_email_addresses');
1669
    if (!empty($result['email'])) {
1670
        $result['complete_name_with_email_forced'] = $result['complete_name'].' ('.$result['email'].')';
1671
        if ($showEmail) {
1672
            $result['complete_name_with_email'] = $result['complete_name'].' ('.$result['email'].')';
1673
        }
1674
    } else {
1675
        $result['complete_name_with_email'] = $result['complete_name'];
1676
        $result['complete_name_with_email_forced'] = $result['complete_name'];
1677
    }
1678
1679
    // Kept for historical reasons
1680
    $result['firstName'] = $result['firstname'];
1681
    $result['lastName'] = $result['lastname'];
1682
1683
    $attributes = [
1684
        'picture_uri',
1685
        'last_login',
1686
        'user_is_online',
1687
    ];
1688
1689
    $result['phone'] = $user->getPhone();
1690
    $result['address'] = $user->getAddress();
1691
    $result['official_code'] = $user->getOfficialCode();
1692
    $result['active'] = $user->getActive();
1693
    $result['auth_source'] = $user->getAuthSource();
1694
    $result['language'] = $user->getLanguage();
1695
    $result['creator_id'] = $user->getCreatorId();
1696
    $result['registration_date'] = $user->getRegistrationDate()->format('Y-m-d H:i:s');
1697
    $result['hr_dept_id'] = $user->getHrDeptId();
1698
    $result['expiration_date'] = '';
1699
    if ($user->getExpirationDate()) {
1700
        $result['expiration_date'] = $user->getExpirationDate()->format('Y-m-d H:i:s');
1701
    }
1702
1703
    $result['last_login'] = null;
1704
    if ($user->getLastLogin()) {
1705
        $result['last_login'] = $user->getLastLogin()->format('Y-m-d H:i:s');
1706
    }
1707
1708
    $result['competences'] = $user->getCompetences();
1709
    $result['diplomas'] = $user->getDiplomas();
1710
    $result['teach'] = $user->getTeach();
1711
    $result['openarea'] = $user->getOpenarea();
1712
    $user_id = (int) $user->getId();
1713
1714
    // Maintain the user_id index for backwards compatibility
1715
    $result['user_id'] = $result['id'] = $user_id;
1716
1717
    if ($loadCertificate) {
1718
        $hasCertificates = Certificate::getCertificateByUser($user_id);
1719
        $result['has_certificates'] = 0;
1720
        if (!empty($hasCertificates)) {
1721
            $result['has_certificates'] = 1;
1722
        }
1723
    }
1724
1725
    $result['icon_status'] = '';
1726
    $result['icon_status_medium'] = '';
1727
    $result['is_admin'] = UserManager::is_admin($user_id);
1728
1729
    // Getting user avatar.
1730
    if ($loadAvatars) {
1731
        $result['avatar'] = '';
1732
        $result['avatar_no_query'] = '';
1733
        $result['avatar_small'] = '';
1734
        $result['avatar_medium'] = '';
1735
1736
        /*if (!isset($user['avatar'])) {
1737
            $originalFile = UserManager::getUserPicture(
1738
                $user_id,
1739
                USER_IMAGE_SIZE_ORIGINAL,
1740
                null,
1741
                $result
1742
            );
1743
            $result['avatar'] = $originalFile;
1744
            $avatarString = explode('?', $result['avatar']);
1745
            $result['avatar_no_query'] = reset($avatarString);
1746
        } else {
1747
            $result['avatar'] = $user['avatar'];
1748
            $avatarString = explode('?', $user['avatar']);
1749
            $result['avatar_no_query'] = reset($avatarString);
1750
        }
1751
1752
        if (!isset($user['avatar_small'])) {
1753
            $smallFile = UserManager::getUserPicture(
1754
                $user_id,
1755
                USER_IMAGE_SIZE_SMALL,
1756
                null,
1757
                $result
1758
            );
1759
            $result['avatar_small'] = $smallFile;
1760
        } else {
1761
            $result['avatar_small'] = $user['avatar_small'];
1762
        }
1763
1764
        if (!isset($user['avatar_medium'])) {
1765
            $mediumFile = UserManager::getUserPicture(
1766
                $user_id,
1767
                USER_IMAGE_SIZE_MEDIUM,
1768
                null,
1769
                $result
1770
            );
1771
            $result['avatar_medium'] = $mediumFile;
1772
        } else {
1773
            $result['avatar_medium'] = $user['avatar_medium'];
1774
        }*/
1775
1776
        //$urlImg = api_get_path(WEB_IMG_PATH);
1777
        $urlImg = '/';
1778
        $iconStatus = '';
1779
        $iconStatusMedium = '';
1780
1781
        switch ($user->getStatus()) {
1782
            case STUDENT:
1783
                if (isset($result['has_certificates']) && $result['has_certificates']) {
1784
                    $iconStatus = $urlImg.'icons/svg/identifier_graduated.svg';
1785
                } else {
1786
                    $iconStatus = $urlImg.'icons/svg/identifier_student.svg';
1787
                }
1788
                break;
1789
            case COURSEMANAGER:
1790
                if ($result['is_admin']) {
1791
                    $iconStatus = $urlImg.'icons/svg/identifier_admin.svg';
1792
                } else {
1793
                    $iconStatus = $urlImg.'icons/svg/identifier_teacher.svg';
1794
                }
1795
                break;
1796
            case STUDENT_BOSS:
1797
                $iconStatus = $urlImg.'icons/svg/identifier_teacher.svg';
1798
                break;
1799
        }
1800
1801
        if (!empty($iconStatus)) {
1802
            $iconStatusMedium = '<img src="'.$iconStatus.'" width="32px" height="32px">';
1803
            $iconStatus = '<img src="'.$iconStatus.'" width="22px" height="22px">';
1804
        }
1805
1806
        $result['icon_status'] = $iconStatus;
1807
        $result['icon_status_medium'] = $iconStatusMedium;
1808
    }
1809
1810
    if (isset($result['user_is_online'])) {
1811
        $result['user_is_online'] = true == $result['user_is_online'] ? 1 : 0;
1812
    }
1813
    if (isset($result['user_is_online_in_chat'])) {
1814
        $result['user_is_online_in_chat'] = (int) $result['user_is_online_in_chat'];
1815
    }
1816
1817
    $result['password'] = '';
1818
    if ($showPassword) {
1819
        $result['password'] = $user->getPassword();
1820
    }
1821
1822
    if (isset($result['profile_completed'])) {
1823
        $result['profile_completed'] = $result['profile_completed'];
1824
    }
1825
1826
    $result['profile_url'] = api_get_path(WEB_CODE_PATH).'social/profile.php?u='.$user_id;
1827
1828
    // Send message link
1829
    $sendMessage = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&user_id='.$user_id;
1830
    $result['complete_name_with_message_link'] = Display::url(
1831
        $result['complete_name_with_username'],
1832
        $sendMessage,
1833
        ['class' => 'ajax']
1834
    );
1835
1836
    if (isset($result['extra'])) {
1837
        $result['extra'] = $result['extra'];
1838
    }
1839
1840
    return $result;
1841
}
1842
1843
/**
1844
 * @param int $userId
1845
 *
1846
 * @return User
1847
 */
1848
function api_get_user_entity($userId)
1849
{
1850
    $userId = (int) $userId;
1851
    $repo = UserManager::getRepository();
1852
1853
    /** @var User $user */
1854
    $user = $repo->find($userId);
1855
1856
    return $user;
1857
}
1858
1859
/**
1860
 * @return User|null
1861
 */
1862
function api_get_current_user()
1863
{
1864
    $isLoggedIn = Container::$container->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_REMEMBERED');
1865
    if (false === $isLoggedIn) {
1866
        return null;
1867
    }
1868
1869
    $token = Container::$container->get('security.token_storage')->getToken();
1870
1871
    if (null !== $token) {
1872
        return $token->getUser();
1873
    }
1874
1875
    return null;
1876
}
1877
1878
/**
1879
 * Finds all the information about a user from username instead of user id.
1880
 *
1881
 * @param string $username
1882
 *
1883
 * @return mixed $user_info array user_id, lastname, firstname, username, email or false on error
1884
 *
1885
 * @author Yannick Warnier <[email protected]>
1886
 */
1887
function api_get_user_info_from_username($username)
1888
{
1889
    if (empty($username)) {
1890
        return false;
1891
    }
1892
    $username = trim($username);
1893
1894
    $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_USER)."
1895
            WHERE username='".Database::escape_string($username)."'";
1896
    $result = Database::query($sql);
1897
    if (Database::num_rows($result) > 0) {
1898
        $resultArray = Database::fetch_array($result);
1899
1900
        return _api_format_user($resultArray);
1901
    }
1902
1903
    return false;
1904
}
1905
1906
/**
1907
 * Get first user with an email.
1908
 *
1909
 * @param string $email
1910
 *
1911
 * @return array|bool
1912
 */
1913
function api_get_user_info_from_email($email = '')
1914
{
1915
    if (empty($email)) {
1916
        return false;
1917
    }
1918
    $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_USER)."
1919
            WHERE email ='".Database::escape_string($email)."' LIMIT 1";
1920
    $result = Database::query($sql);
1921
    if (Database::num_rows($result) > 0) {
1922
        $resultArray = Database::fetch_array($result);
1923
1924
        return _api_format_user($resultArray);
1925
    }
1926
1927
    return false;
1928
}
1929
1930
/**
1931
 * @return string
1932
 */
1933
function api_get_course_id()
1934
{
1935
    return Session::read('_cid', null);
1936
}
1937
1938
/**
1939
 * Returns the current course id (integer).
1940
 *
1941
 * @param string $code Optional course code
1942
 *
1943
 * @return int
1944
 */
1945
function api_get_course_int_id($code = null)
1946
{
1947
    if (!empty($code)) {
1948
        $code = Database::escape_string($code);
1949
        $row = Database::select(
1950
            'id',
1951
            Database::get_main_table(TABLE_MAIN_COURSE),
1952
            ['where' => ['code = ?' => [$code]]],
1953
            'first'
1954
        );
1955
1956
        if (is_array($row) && isset($row['id'])) {
1957
            return $row['id'];
1958
        } else {
1959
            return false;
1960
        }
1961
    }
1962
1963
    return Session::read('_real_cid', 0);
1964
}
1965
1966
/**
1967
 * Returns the current course directory.
1968
 *
1969
 * This function relies on api_get_course_info()
1970
 *
1971
 * @param string    The course code - optional (takes it from session if not given)
1972
 *
1973
 * @return string The directory where the course is located inside the Chamilo "courses" directory
1974
 *
1975
 * @author Yannick Warnier <[email protected]>
1976
 */
1977
function api_get_course_path($course_code = null)
1978
{
1979
    $info = !empty($course_code) ? api_get_course_info($course_code) : api_get_course_info();
1980
1981
    return $info['path'];
1982
}
1983
1984
/**
1985
 * Gets a course setting from the current course_setting table. Try always using integer values.
1986
 *
1987
 * @param string $settingName The name of the setting we want from the table
1988
 * @param array  $courseInfo
1989
 * @param bool   $force       force checking the value in the database
1990
 *
1991
 * @return mixed The value of that setting in that table. Return -1 if not found.
1992
 */
1993
function api_get_course_setting($settingName, $courseInfo = [], $force = false)
1994
{
1995
    if (empty($courseInfo)) {
1996
        $courseInfo = api_get_course_info();
1997
    }
1998
1999
    if (empty($courseInfo) || empty($settingName)) {
2000
        return -1;
2001
    }
2002
2003
    $courseId = isset($courseInfo['real_id']) && !empty($courseInfo['real_id']) ? $courseInfo['real_id'] : 0;
2004
2005
    if (empty($courseId)) {
2006
        return -1;
2007
    }
2008
2009
    static $courseSettingInfo = [];
2010
2011
    if ($force) {
2012
        $courseSettingInfo = [];
2013
    }
2014
2015
    if (!isset($courseSettingInfo[$courseId])) {
2016
        $table = Database::get_course_table(TABLE_COURSE_SETTING);
2017
        $settingName = Database::escape_string($settingName);
2018
2019
        $sql = "SELECT variable, value FROM $table
2020
                WHERE c_id = $courseId ";
2021
        $res = Database::query($sql);
2022
        if (Database::num_rows($res) > 0) {
2023
            $result = Database::store_result($res, 'ASSOC');
2024
            $courseSettingInfo[$courseId] = array_column($result, 'value', 'variable');
2025
2026
            if (isset($courseSettingInfo[$courseId]['email_alert_manager_on_new_quiz'])) {
2027
                $value = $courseSettingInfo[$courseId]['email_alert_manager_on_new_quiz'];
2028
                if (!is_null($value)) {
2029
                    $result = explode(',', $value);
2030
                    $courseSettingInfo[$courseId]['email_alert_manager_on_new_quiz'] = $result;
2031
                }
2032
            }
2033
        }
2034
    }
2035
2036
    if (isset($courseSettingInfo[$courseId]) && isset($courseSettingInfo[$courseId][$settingName])) {
2037
        return $courseSettingInfo[$courseId][$settingName];
2038
    }
2039
2040
    return -1;
2041
}
2042
2043
function api_get_course_plugin_setting($plugin, $settingName, $courseInfo = [])
2044
{
2045
    $value = api_get_course_setting($settingName, $courseInfo, true);
2046
2047
    if (-1 === $value) {
2048
        // Check global settings
2049
        $value = api_get_plugin_setting($plugin, $settingName);
2050
        if ($value === 'true') {
2051
            return 1;
2052
        }
2053
        if ($value === 'false') {
2054
            return 0;
2055
        }
2056
        if (null === $value) {
2057
            return -1;
2058
        }
2059
    }
2060
2061
    return $value;
2062
}
2063
2064
/**
2065
 * Gets an anonymous user ID.
2066
 *
2067
 * For some tools that need tracking, like the learnpath tool, it is necessary
2068
 * to have a usable user-id to enable some kind of tracking, even if not
2069
 * perfect. An anonymous ID is taken from the users table by looking for a
2070
 * status of "6" (anonymous).
2071
 *
2072
 * @return int User ID of the anonymous user, or O if no anonymous user found
2073
 */
2074
function api_get_anonymous_id()
2075
{
2076
    // Find if another anon is connected now
2077
    $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
2078
    $tableU = Database::get_main_table(TABLE_MAIN_USER);
2079
    $ip = Database::escape_string(api_get_real_ip());
2080
    $max = (int) api_get_configuration_value('max_anonymous_users');
2081
    if ($max >= 2) {
2082
        $sql = "SELECT * FROM $table as TEL
2083
                JOIN $tableU as U
2084
                ON U.user_id = TEL.login_user_id
2085
                WHERE TEL.user_ip = '$ip'
2086
                    AND U.status = ".ANONYMOUS."
2087
                    AND U.user_id != 2 ";
2088
2089
        $result = Database::query($sql);
2090
        if (empty(Database::num_rows($result))) {
2091
            $login = uniqid('anon_');
2092
            $anonList = UserManager::get_user_list(['status' => ANONYMOUS], ['registration_date ASC']);
2093
            if (count($anonList) >= $max) {
2094
                foreach ($anonList as $userToDelete) {
2095
                    UserManager::delete_user($userToDelete['user_id']);
2096
                    break;
2097
                }
2098
            }
2099
            $userId = UserManager::create_user(
2100
                $login,
2101
                'anon',
2102
                ANONYMOUS,
2103
                ' anonymous@localhost',
2104
                $login,
2105
                $login
2106
            );
2107
2108
            return $userId;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $userId could also return false which is incompatible with the documented return type integer. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
2109
        } else {
2110
            $row = Database::fetch_array($result, 'ASSOC');
2111
2112
            return $row['user_id'];
2113
        }
2114
    }
2115
2116
    $table = Database::get_main_table(TABLE_MAIN_USER);
2117
    $sql = "SELECT user_id
2118
            FROM $table
2119
            WHERE status = ".ANONYMOUS." ";
2120
    $res = Database::query($sql);
2121
    if (Database::num_rows($res) > 0) {
2122
        $row = Database::fetch_array($res, 'ASSOC');
2123
2124
        return $row['user_id'];
2125
    }
2126
2127
    // No anonymous user was found.
2128
    return 0;
2129
}
2130
2131
/**
2132
 * @param string $courseCode
2133
 * @param int    $sessionId
2134
 * @param int    $groupId
2135
 *
2136
 * @return string
2137
 */
2138
function api_get_cidreq_params($courseCode, $sessionId = 0, $groupId = 0)
2139
{
2140
    $courseCode = !empty($courseCode) ? htmlspecialchars($courseCode) : '';
2141
    $sessionId = !empty($sessionId) ? (int) $sessionId : 0;
2142
    $groupId = !empty($groupId) ? (int) $groupId : 0;
2143
2144
    $url = 'cidReq='.$courseCode;
2145
    $url .= '&id_session='.$sessionId;
2146
    $url .= '&gidReq='.$groupId;
2147
2148
    return $url;
2149
}
2150
2151
/**
2152
 * Returns the current course url part including session, group, and gradebook params.
2153
 *
2154
 * @param bool   $addSessionId
2155
 * @param bool   $addGroupId
2156
 * @param string $origin
2157
 *
2158
 * @return string Course & session references to add to a URL
2159
 */
2160
function api_get_cidreq($addSessionId = true, $addGroupId = true, $origin = '')
2161
{
2162
    $courseId = api_get_course_int_id();
2163
    $url = empty($courseId) ? '' : 'cid='.$courseId;
2164
    $origin = empty($origin) ? api_get_origin() : Security::remove_XSS($origin);
2165
2166
    if ($addSessionId) {
2167
        if (!empty($url)) {
2168
            $url .= 0 == api_get_session_id() ? '&sid=0' : '&sid='.api_get_session_id();
2169
        }
2170
    }
2171
2172
    if ($addGroupId) {
2173
        if (!empty($url)) {
2174
            $url .= 0 == api_get_group_id() ? '&gid=0' : '&gid='.api_get_group_id();
2175
        }
2176
    }
2177
2178
    if (!empty($url)) {
2179
        $url .= '&gradebook='.(int) api_is_in_gradebook();
2180
        $url .= '&origin='.$origin;
2181
    }
2182
2183
    return $url;
2184
}
2185
2186
/**
2187
 * Get if we visited a gradebook page.
2188
 *
2189
 * @return bool
2190
 */
2191
function api_is_in_gradebook()
2192
{
2193
    return Session::read('in_gradebook', false);
2194
}
2195
2196
/**
2197
 * Set that we are in a page inside a gradebook.
2198
 */
2199
function api_set_in_gradebook()
2200
{
2201
    Session::write('in_gradebook', true);
2202
}
2203
2204
/**
2205
 * Remove gradebook session.
2206
 */
2207
function api_remove_in_gradebook()
2208
{
2209
    Session::erase('in_gradebook');
2210
}
2211
2212
/**
2213
 * Returns the current course info array see api_format_course_array()
2214
 * If the course_code is given, the returned array gives info about that
2215
 * particular course, if none given it gets the course info from the session.
2216
 *
2217
 * @param string $course_code
2218
 *
2219
 * @return array
2220
 */
2221
function api_get_course_info($course_code = null)
2222
{
2223
    if (!empty($course_code)) {
2224
        $course = Container::getCourseRepository()->findOneByCode($course_code);
2225
        if (empty($course)) {
2226
            return [];
2227
        }
2228
2229
        $courseInfo = api_format_course_array($course);
2230
2231
        return $courseInfo;
2232
    }
2233
2234
    /*$course_code = Database::escape_string($course_code);
2235
    $courseId = api_get_course_int_id($course_code);
2236
    if (empty($courseId)) {
2237
        return [];
2238
    }
2239
2240
    $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
2241
    $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
2242
    $sql = "SELECT
2243
                course.*,
2244
                course_category.code faCode,
2245
                course_category.name faName
2246
            FROM $course_table
2247
            LEFT JOIN $course_cat_table
2248
            ON course.category_code = course_category.code
2249
            WHERE course.id = $courseId";
2250
    $result = Database::query($sql);
2251
    $courseInfo = [];
2252
    if (Database::num_rows($result) > 0) {
2253
        $data = Database::fetch_array($result);
2254
        $courseInfo = api_format_course_array($data);
2255
    }
2256
2257
    return $courseInfo;*/
2258
2259
    $course = Session::read('_course');
2260
    if ('-1' == $course) {
2261
        $course = [];
2262
    }
2263
2264
    return $course;
2265
}
2266
2267
/**
2268
 * @param int $courseId
2269
 *
2270
 * @return Course
2271
 */
2272
function api_get_course_entity($courseId = 0)
2273
{
2274
    if (empty($courseId)) {
2275
        $courseId = api_get_course_int_id();
2276
    }
2277
2278
    return CourseManager::getManager()->find($courseId);
0 ignored issues
show
Deprecated Code introduced by
The function CourseManager::getManager() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

2278
    return /** @scrutinizer ignore-deprecated */ CourseManager::getManager()->find($courseId);
Loading history...
2279
}
2280
2281
/**
2282
 * @param int $id
2283
 *
2284
 * @return SessionEntity|null
2285
 */
2286
function api_get_session_entity($id = 0)
2287
{
2288
    if (empty($id)) {
2289
        $id = api_get_session_id();
2290
    }
2291
2292
    if (empty($id)) {
2293
        return null;
2294
    }
2295
2296
    return Database::getManager()->getRepository('ChamiloCoreBundle:Session')->find($id);
2297
}
2298
2299
/**
2300
 * @param int $id
2301
 *
2302
 * @return CGroupInfo
2303
 */
2304
function api_get_group_entity($id = 0)
2305
{
2306
    if (empty($id)) {
2307
        $id = api_get_group_id();
2308
    }
2309
2310
    return Database::getManager()->getRepository('ChamiloCourseBundle:CGroupInfo')->find($id);
2311
}
2312
2313
/**
2314
 * @param int $id
2315
 *
2316
 * @return AccessUrl
2317
 */
2318
function api_get_url_entity($id = 0)
2319
{
2320
    if (empty($id)) {
2321
        $id = api_get_current_access_url_id();
2322
    }
2323
2324
    return Container::getAccessUrlRepository()->find($id);
2325
}
2326
2327
/**
2328
 * Returns the current course info array.
2329
2330
 * Now if the course_code is given, the returned array gives info about that
2331
 * particular course, not specially the current one.
2332
 *
2333
 * @param int $id Numeric ID of the course
2334
 *
2335
 * @return array The course info as an array formatted by api_format_course_array, including category.name
2336
 */
2337
function api_get_course_info_by_id($id = 0)
2338
{
2339
    $id = (int) $id;
2340
    if (empty($id)) {
2341
        $course = Session::read('_course', []);
2342
2343
        return $course;
2344
    }
2345
2346
    $course = Container::getCourseRepository()->find($id);
2347
    if (empty($course)) {
2348
        return [];
2349
    }
2350
2351
    return api_format_course_array($course);
2352
}
2353
2354
/**
2355
 * Reformat the course array (output by api_get_course_info()) in order, mostly,
2356
 * to switch from 'code' to 'id' in the array.
2357
 *
2358
 * @return array
2359
 *
2360
 * @todo eradicate the false "id"=code field of the $_course array and use the int id
2361
 */
2362
function api_format_course_array(Course $course)
2363
{
2364
    if (empty($course)) {
2365
        return [];
2366
    }
2367
2368
    $category = $course->getCategory();
2369
2370
    $courseData = [];
2371
    $courseData['categoryCode'] = '';
2372
    $courseData['categoryName'] = '';
2373
    $courseData['category_id'] = 0;
2374
    if ($category) {
0 ignored issues
show
introduced by
$category is of type Chamilo\CoreBundle\Entity\CourseCategory, thus it always evaluated to true.
Loading history...
2375
        $courseData['categoryCode'] = $category->getCode();
2376
        $courseData['categoryName'] = $category->getName();
2377
        $courseData['category_id'] = $category->getId();
2378
    }
2379
2380
    $courseData['id'] = $courseData['real_id'] = $course->getId();
2381
2382
    // Added
2383
    $courseData['code'] = $courseData['sysCode'] = $course->getCode();
2384
    $courseData['name'] = $courseData['title'] = $course->getTitle();
2385
    $courseData['official_code'] = $courseData['visual_code'] = $course->getVisualCode();
2386
    $courseData['path'] = $courseData['directory'] = $course->getDirectory(); // Use as key in path.
2387
    $courseData['creation_date'] = $course->getCreationDate()->format('Y-m-d H:i:s');
2388
    $courseData['titular'] = $course->getTutorName();
2389
    $courseData['language'] = $courseData['course_language'] = $course->getCourseLanguage();
2390
    $courseData['extLink']['url'] = $courseData['department_url'] = $course->getDepartmentUrl();
2391
    $courseData['extLink']['name'] = $courseData['department_name'] = $course->getDepartmentName();
2392
2393
    $courseData['visibility'] = $course->getVisibility();
2394
    $courseData['subscribe_allowed'] = $courseData['subscribe'] = $course->getSubscribe();
2395
    $courseData['unsubscribe'] = $course->getUnsubscribe();
2396
    $courseData['activate_legal'] = $course->getActivateLegal();
2397
    $courseData['legal'] = $course->getLegal();
2398
    $courseData['show_score'] = $course->getShowScore(); //used in the work tool
2399
2400
    $coursePath = api_get_path(WEB_COURSE_PATH);
2401
    $webCourseHome = $coursePath.$courseData['real_id'].'/home';
2402
2403
    // Course password
2404
    $courseData['registration_code'] = $course->getRegistrationCode();
2405
    $courseData['disk_quota'] = $course->getDiskQuota();
2406
    $courseData['course_public_url'] = $webCourseHome;
2407
    $courseData['about_url'] = $coursePath.$courseData['real_id'].'/about';
2408
    $courseData['add_teachers_to_sessions_courses'] = $course->isAddTeachersToSessionsCourses();
2409
    $courseData['entity'] = $course;
2410
2411
    $image = Display::return_icon(
2412
        'course.png',
2413
        null,
2414
        null,
2415
        ICON_SIZE_BIG,
2416
        null,
2417
        true,
2418
        false
2419
    );
2420
2421
    $illustration = Container::getIllustrationRepository()->getIllustrationUrl($course);
2422
    if (!empty($illustration)) {
2423
        $image = $illustration;
2424
    }
2425
2426
    $courseData['course_image'] = $image.'?filter=course_picture_small';
2427
2428
    // Course large image
2429
    /*$courseData['course_image_large_source'] = '';
2430
    if (file_exists($courseSys.'/course-pic.png')) {
2431
        $url_image = $webCourseHome.'/course-pic.png';
2432
        $courseData['course_image_large_source'] = $courseSys.'/course-pic.png';
2433
    } else {
2434
        $url_image = Display::return_icon(
2435
            'session_default.png',
2436
            null,
2437
            null,
2438
            null,
2439
            null,
2440
            true,
2441
            true
2442
        );
2443
    }*/
2444
2445
    $courseData['course_image_large'] = $image.'?filter=course_picture_medium';
2446
2447
    return $courseData;
2448
}
2449
2450
/**
2451
 * Returns a difficult to guess password.
2452
 *
2453
 * @param int $length the length of the password
2454
 *
2455
 * @return string the generated password
2456
 */
2457
function api_generate_password($length = 8)
2458
{
2459
    if ($length < 2) {
2460
        $length = 2;
2461
    }
2462
2463
    $charactersLowerCase = 'abcdefghijkmnopqrstuvwxyz';
2464
    $charactersUpperCase = 'ABCDEFGHJKLMNPQRSTUVWXYZ';
2465
    $minNumbers = 2;
2466
    $length = $length - $minNumbers;
2467
    $minLowerCase = round($length / 2);
2468
    $minUpperCase = $length - $minLowerCase;
2469
2470
    $password = '';
2471
    $passwordRequirements = api_get_configuration_value('password_requirements');
2472
2473
    $factory = new RandomLib\Factory();
2474
    $generator = $factory->getGenerator(new SecurityLib\Strength(SecurityLib\Strength::MEDIUM));
2475
2476
    if (!empty($passwordRequirements)) {
2477
        $length = $passwordRequirements['min']['length'];
2478
        $minNumbers = $passwordRequirements['min']['numeric'];
2479
        $minLowerCase = $passwordRequirements['min']['lowercase'];
2480
        $minUpperCase = $passwordRequirements['min']['uppercase'];
2481
2482
        $rest = $length - $minNumbers - $minLowerCase - $minUpperCase;
2483
        // Add the rest to fill the length requirement
2484
        if ($rest > 0) {
2485
            $password .= $generator->generateString($rest, $charactersLowerCase.$charactersUpperCase);
2486
        }
2487
    }
2488
2489
    // Min digits default 2
2490
    for ($i = 0; $i < $minNumbers; $i++) {
2491
        $password .= $generator->generateInt(2, 9);
2492
    }
2493
2494
    // Min lowercase
2495
    $password .= $generator->generateString($minLowerCase, $charactersLowerCase);
2496
2497
    // Min uppercase
2498
    $password .= $generator->generateString($minUpperCase, $charactersUpperCase);
2499
    $password = str_shuffle($password);
2500
2501
    return $password;
2502
}
2503
2504
/**
2505
 * Checks a password to see wether it is OK to use.
2506
 *
2507
 * @param string $password
2508
 *
2509
 * @return bool if the password is acceptable, false otherwise
2510
 *              Notes about what a password "OK to use" is:
2511
 *              1. The password should be at least 5 characters long.
2512
 *              2. Only English letters (uppercase or lowercase, it doesn't matter) and digits are allowed.
2513
 *              3. The password should contain at least 3 letters.
2514
 *              4. It should contain at least 2 digits.
2515
 *              Settings will change if the configuration value is set: password_requirements
2516
 */
2517
function api_check_password($password)
2518
{
2519
    $passwordRequirements = Security::getPasswordRequirements();
2520
2521
    $minLength = $passwordRequirements['min']['length'];
2522
    $minNumbers = $passwordRequirements['min']['numeric'];
2523
    // Optional
2524
    $minLowerCase = $passwordRequirements['min']['lowercase'];
2525
    $minUpperCase = $passwordRequirements['min']['uppercase'];
2526
2527
    $minLetters = $minLowerCase + $minUpperCase;
2528
    $passwordLength = api_strlen($password);
2529
2530
    $conditions = [
2531
        'min_length' => $passwordLength >= $minLength,
2532
    ];
2533
2534
    $digits = 0;
2535
    $lowerCase = 0;
2536
    $upperCase = 0;
2537
2538
    for ($i = 0; $i < $passwordLength; $i++) {
2539
        $currentCharacterCode = api_ord(api_substr($password, $i, 1));
2540
        if ($currentCharacterCode >= 65 && $currentCharacterCode <= 90) {
2541
            $upperCase++;
2542
        }
2543
2544
        if ($currentCharacterCode >= 97 && $currentCharacterCode <= 122) {
2545
            $lowerCase++;
2546
        }
2547
        if ($currentCharacterCode >= 48 && $currentCharacterCode <= 57) {
2548
            $digits++;
2549
        }
2550
    }
2551
2552
    // Min number of digits
2553
    $conditions['min_numeric'] = $digits >= $minNumbers;
2554
2555
    if (!empty($minUpperCase)) {
2556
        // Uppercase
2557
        $conditions['min_uppercase'] = $upperCase >= $minUpperCase;
2558
    }
2559
2560
    if (!empty($minLowerCase)) {
2561
        // Lowercase
2562
        $conditions['min_lowercase'] = $upperCase >= $minLowerCase;
2563
    }
2564
2565
    // Min letters
2566
    $letters = $upperCase + $lowerCase;
2567
    $conditions['min_letters'] = $letters >= $minLetters;
2568
2569
    $isPasswordOk = true;
2570
    foreach ($conditions as $condition) {
2571
        if (false === $condition) {
2572
            $isPasswordOk = false;
2573
            break;
2574
        }
2575
    }
2576
2577
    if (false === $isPasswordOk) {
2578
        $output = get_lang('The new password does not match the minimum security requirements').'<br />';
2579
        $output .= Security::getPasswordRequirementsToString($conditions);
2580
2581
        Display::addFlash(Display::return_message($output, 'warning', false));
2582
    }
2583
2584
    return $isPasswordOk;
2585
}
2586
2587
/**
2588
 * Returns the status string corresponding to the status code.
2589
 *
2590
 * @author Noel Dieschburg
2591
 *
2592
 * @param the int status code
2593
 *
2594
 * @return string
2595
 */
2596
function get_status_from_code($status_code)
2597
{
2598
    switch ($status_code) {
2599
        case STUDENT:
2600
            return get_lang('Student', '');
2601
        case COURSEMANAGER:
2602
            return get_lang('Teacher', '');
2603
        case SESSIONADMIN:
2604
            return get_lang('SessionsAdmin', '');
2605
        case DRH:
2606
            return get_lang('Drh', '');
2607
    }
2608
}
2609
2610
/**
2611
 * Gets the current Chamilo (not PHP/cookie) session ID.
2612
 *
2613
 * @return int O if no active session, the session ID otherwise
2614
 */
2615
function api_get_session_id()
2616
{
2617
    return (int) Session::read('sid', 0);
2618
}
2619
2620
/**
2621
 * Gets the current Chamilo (not social network) group ID.
2622
 *
2623
 * @return int O if no active session, the session ID otherwise
2624
 */
2625
function api_get_group_id()
2626
{
2627
    return Session::read('gid', 0);
2628
}
2629
2630
/**
2631
 * Gets the current or given session name.
2632
 *
2633
 * @param   int     Session ID (optional)
2634
 *
2635
 * @return string The session name, or null if not found
2636
 */
2637
function api_get_session_name($session_id = 0)
2638
{
2639
    if (empty($session_id)) {
2640
        $session_id = api_get_session_id();
2641
        if (empty($session_id)) {
2642
            return null;
2643
        }
2644
    }
2645
    $t = Database::get_main_table(TABLE_MAIN_SESSION);
2646
    $s = "SELECT name FROM $t WHERE id = ".(int) $session_id;
2647
    $r = Database::query($s);
2648
    $c = Database::num_rows($r);
2649
    if ($c > 0) {
2650
        //technically, there can be only one, but anyway we take the first
2651
        $rec = Database::fetch_array($r);
2652
2653
        return $rec['name'];
2654
    }
2655
2656
    return null;
2657
}
2658
2659
/**
2660
 * Gets the session info by id.
2661
 *
2662
 * @param int $id Session ID
2663
 *
2664
 * @return array information of the session
2665
 */
2666
function api_get_session_info($id)
2667
{
2668
    return SessionManager::fetch($id);
2669
}
2670
2671
/**
2672
 * Gets the session visibility by session id.
2673
 *
2674
 * @param int  $session_id
2675
 * @param int  $courseId
2676
 * @param bool $ignore_visibility_for_admins
2677
 *
2678
 * @return int
2679
 *             0 = session still available,
2680
 *             SESSION_VISIBLE_READ_ONLY = 1,
2681
 *             SESSION_VISIBLE = 2,
2682
 *             SESSION_INVISIBLE = 3
2683
 */
2684
function api_get_session_visibility(
2685
    $session_id,
2686
    $courseId = null,
2687
    $ignore_visibility_for_admins = true
2688
) {
2689
    if (api_is_platform_admin()) {
2690
        if ($ignore_visibility_for_admins) {
2691
            return SESSION_AVAILABLE;
2692
        }
2693
    }
2694
2695
    $now = time();
2696
    if (empty($session_id)) {
2697
        return 0; // Means that the session is still available.
2698
    }
2699
2700
    $session_id = (int) $session_id;
2701
    $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2702
2703
    $result = Database::query("SELECT * FROM $tbl_session WHERE id = $session_id");
2704
2705
    if (Database::num_rows($result) <= 0) {
2706
        return SESSION_INVISIBLE;
2707
    }
2708
2709
    $row = Database::fetch_array($result, 'ASSOC');
2710
    $visibility = $row['visibility'];
2711
2712
    // I don't care the session visibility.
2713
    if (empty($row['access_start_date']) && empty($row['access_end_date'])) {
2714
        // Session duration per student.
2715
        if (isset($row['duration']) && !empty($row['duration'])) {
2716
            $duration = $row['duration'] * 24 * 60 * 60;
2717
            $courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser($session_id, api_get_user_id());
2718
2719
            // If there is a session duration but there is no previous
2720
            // access by the user, then the session is still available
2721
            if (0 == count($courseAccess)) {
2722
                return SESSION_AVAILABLE;
2723
            }
2724
2725
            $currentTime = time();
2726
            $firstAccess = isset($courseAccess['login_course_date'])
2727
                ? api_strtotime($courseAccess['login_course_date'], 'UTC')
2728
                : 0;
2729
            $userDurationData = SessionManager::getUserSession(
2730
                api_get_user_id(),
2731
                $session_id
2732
            );
2733
            $userDuration = isset($userDurationData['duration'])
2734
                ? (intval($userDurationData['duration']) * 24 * 60 * 60)
2735
                : 0;
2736
2737
            $totalDuration = $firstAccess + $duration + $userDuration;
2738
2739
            return $totalDuration > $currentTime ? SESSION_AVAILABLE : SESSION_VISIBLE_READ_ONLY;
2740
        }
2741
2742
        return SESSION_AVAILABLE;
2743
    }
2744
2745
    // If start date was set.
2746
    if (!empty($row['access_start_date'])) {
2747
        $visibility = $now > api_strtotime($row['access_start_date'], 'UTC') ? SESSION_AVAILABLE : SESSION_INVISIBLE;
2748
    }
2749
2750
    // If the end date was set.
2751
    if (!empty($row['access_end_date'])) {
2752
        // Only if date_start said that it was ok
2753
        if (SESSION_AVAILABLE === $visibility) {
2754
            $visibility = $now < api_strtotime($row['access_end_date'], 'UTC')
2755
                ? SESSION_AVAILABLE // Date still available
2756
                : $row['visibility']; // Session ends
2757
        }
2758
    }
2759
2760
    // If I'm a coach the visibility can change in my favor depending in the coach dates.
2761
    $isCoach = api_is_coach($session_id, $courseId);
2762
2763
    if ($isCoach) {
2764
        // Test start date.
2765
        if (!empty($row['coach_access_start_date'])) {
2766
            $start = api_strtotime($row['coach_access_start_date'], 'UTC');
2767
            $visibility = $start < $now ? SESSION_AVAILABLE : SESSION_INVISIBLE;
2768
        }
2769
2770
        // Test end date.
2771
        if (!empty($row['coach_access_end_date'])) {
2772
            if (SESSION_AVAILABLE === $visibility) {
2773
                $endDateCoach = api_strtotime($row['coach_access_end_date'], 'UTC');
2774
                $visibility = $endDateCoach >= $now ? SESSION_AVAILABLE : $row['visibility'];
2775
            }
2776
        }
2777
    }
2778
2779
    return $visibility;
2780
}
2781
2782
/**
2783
 * This function returns a (star) session icon if the session is not null and
2784
 * the user is not a student.
2785
 *
2786
 * @param int $sessionId
2787
 * @param int $statusId  User status id - if 5 (student), will return empty
2788
 *
2789
 * @return string Session icon
2790
 */
2791
function api_get_session_image($sessionId, $statusId)
2792
{
2793
    $sessionId = (int) $sessionId;
2794
    $image = '';
2795
    if (STUDENT != $statusId) {
2796
        // Check whether is not a student
2797
        if ($sessionId > 0) {
2798
            $image = '&nbsp;&nbsp;'.Display::return_icon(
2799
                'star.png',
2800
                get_lang('Session-specific resource'),
2801
                ['align' => 'absmiddle'],
2802
                ICON_SIZE_SMALL
2803
            );
2804
        }
2805
    }
2806
2807
    return $image;
2808
}
2809
2810
/**
2811
 * This function add an additional condition according to the session of the course.
2812
 *
2813
 * @param int    $session_id        session id
2814
 * @param bool   $and               optional, true if more than one condition false if the only condition in the query
2815
 * @param bool   $with_base_content optional, true to accept content with session=0 as well,
2816
 *                                  false for strict session condition
2817
 * @param string $session_field
2818
 *
2819
 * @return string condition of the session
2820
 */
2821
function api_get_session_condition(
2822
    $session_id,
2823
    $and = true,
2824
    $with_base_content = false,
2825
    $session_field = 'session_id'
2826
) {
2827
    $session_id = (int) $session_id;
2828
2829
    if (empty($session_field)) {
2830
        $session_field = 'session_id';
2831
    }
2832
    // Condition to show resources by session
2833
    $condition_add = $and ? ' AND ' : ' WHERE ';
2834
2835
    if ($with_base_content) {
2836
        $condition_session = $condition_add." ( $session_field = $session_id OR $session_field = 0 OR $session_field IS NULL) ";
2837
    } else {
2838
        if (empty($session_id)) {
2839
            $condition_session = $condition_add." ($session_field = $session_id OR $session_field IS NULL)";
2840
        } else {
2841
            $condition_session = $condition_add." $session_field = $session_id ";
2842
        }
2843
    }
2844
2845
    return $condition_session;
2846
}
2847
2848
/**
2849
 * Returns the value of a setting from the web-adjustable admin config settings.
2850
 *
2851
 * WARNING true/false are stored as string, so when comparing you need to check e.g.
2852
 * if (api_get_setting('show_navigation_menu') == 'true') //CORRECT
2853
 * instead of
2854
 * if (api_get_setting('show_navigation_menu') == true) //INCORRECT
2855
 *
2856
 * @param string $variable The variable name
2857
 *
2858
 * @return string
2859
 */
2860
function api_get_setting($variable)
2861
{
2862
    $settingsManager = Container::getSettingsManager();
2863
    if (empty($settingsManager)) {
2864
        return '';
2865
    }
2866
    $variable = trim($variable);
2867
2868
    switch ($variable) {
2869
        /*case 'header_extra_content':
2870
            $filename = api_get_path(SYS_PATH).api_get_home_path().'header_extra_content.txt';
2871
            if (file_exists($filename)) {
2872
                $value = file_get_contents($filename);
2873
2874
                return $value;
2875
            } else {
2876
                return '';
2877
            }
2878
            break;
2879
        case 'footer_extra_content':
2880
            $filename = api_get_path(SYS_PATH).api_get_home_path().'footer_extra_content.txt';
2881
            if (file_exists($filename)) {
2882
                $value = file_get_contents($filename);
2883
2884
                return $value;
2885
            } else {
2886
                return '';
2887
            }
2888
            break;*/
2889
        case 'server_type':
2890
            $test = ['dev', 'test'];
2891
            $environment = Container::getEnvironment();
2892
            if (in_array($environment, $test)) {
2893
                return 'test';
2894
            }
2895
2896
            return 'prod';
2897
        case 'stylesheets':
2898
            $variable = 'platform.theme';
2899
        // deprecated settings
2900
        // no break
2901
        case 'openid_authentication':
2902
        case 'service_ppt2lp':
2903
        case 'formLogin_hide_unhide_label':
2904
            return false;
2905
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
2906
        case 'tool_visible_by_default_at_creation':
2907
            $values = $settingsManager->getSetting($variable);
2908
            $newResult = [];
2909
            foreach ($values as $parameter) {
2910
                $newResult[$parameter] = 'true';
2911
            }
2912
2913
            return $newResult;
2914
            break;
2915
        default:
2916
            return $settingsManager->getSetting($variable);
2917
            break;
2918
    }
2919
}
2920
2921
/**
2922
 * @param string $variable
2923
 * @param string $option
2924
 *
2925
 * @return bool
2926
 */
2927
function api_get_setting_in_list($variable, $option)
2928
{
2929
    $value = api_get_setting($variable);
2930
2931
    return in_array($option, $value);
2932
}
2933
2934
/**
2935
 * @param string $plugin
2936
 * @param string $variable
2937
 *
2938
 * @return string
2939
 */
2940
function api_get_plugin_setting($plugin, $variable)
2941
{
2942
    $variableName = $plugin.'_'.$variable;
2943
    //$result = api_get_setting($variableName);
2944
    $params = [
2945
        'category = ? AND subkey = ? AND variable = ?' => [
2946
            'Plugins',
2947
            $plugin,
2948
            $variableName,
2949
        ],
2950
    ];
2951
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2952
    $result = Database::select(
2953
        'selected_value',
2954
        $table,
2955
        ['where' => $params],
2956
        'one'
2957
    );
2958
    if ($result) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $result of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2959
        $value = $result['selected_value'];
2960
        $serializedValue = @unserialize($result['selected_value'], []);
2961
        if (false !== $serializedValue) {
2962
            $value = $serializedValue;
2963
        }
2964
2965
        return $value;
2966
    }
2967
2968
    return null;
2969
    /// Old code
2970
2971
    $variableName = $plugin.'_'.$variable;
0 ignored issues
show
Unused Code introduced by
$variableName = $plugin . '_' . $variable is not 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...
2972
    $result = api_get_setting($variableName);
2973
2974
    if (isset($result[$plugin])) {
2975
        $value = $result[$plugin];
2976
2977
        $unserialized = UnserializeApi::unserialize('not_allowed_classes', $value, true);
2978
2979
        if (false !== $unserialized) {
2980
            $value = $unserialized;
2981
        }
2982
2983
        return $value;
2984
    }
2985
2986
    return null;
2987
}
2988
2989
/**
2990
 * Returns the value of a setting from the web-adjustable admin config settings.
2991
 */
2992
function api_get_settings_params($params)
2993
{
2994
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2995
    $result = Database::select('*', $table, ['where' => $params]);
2996
2997
    return $result;
2998
}
2999
3000
/**
3001
 * @param array $params example: [id = ? => '1']
3002
 *
3003
 * @return array
3004
 */
3005
function api_get_settings_params_simple($params)
3006
{
3007
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
3008
    $result = Database::select('*', $table, ['where' => $params], 'one');
3009
3010
    return $result;
3011
}
3012
3013
/**
3014
 * Returns the value of a setting from the web-adjustable admin config settings.
3015
 */
3016
function api_delete_settings_params($params)
3017
{
3018
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
3019
    $result = Database::delete($table, $params);
3020
3021
    return $result;
3022
}
3023
3024
/**
3025
 * Returns an escaped version of $_SERVER['PHP_SELF'] to avoid XSS injection.
3026
 *
3027
 * @return string Escaped version of $_SERVER['PHP_SELF']
3028
 */
3029
function api_get_self()
3030
{
3031
    return htmlentities($_SERVER['PHP_SELF']);
3032
}
3033
3034
/* USER PERMISSIONS */
3035
3036
/**
3037
 * Checks whether current user is a platform administrator.
3038
 *
3039
 * @param bool $allowSessionAdmins Whether session admins should be considered admins or not
3040
 * @param bool $allowDrh           Whether HR directors should be considered admins or not
3041
 *
3042
 * @return bool true if the user has platform admin rights,
3043
 *              false otherwise
3044
 *
3045
 * @see usermanager::is_admin(user_id) for a user-id specific function
3046
 */
3047
function api_is_platform_admin($allowSessionAdmins = false, $allowDrh = false)
3048
{
3049
    $currentUser = api_get_current_user();
3050
3051
    if (null === $currentUser) {
3052
        return false;
3053
    }
3054
3055
    $isAdmin = Session::read('is_platformAdmin');
3056
    if ($isAdmin) {
3057
        return true;
3058
    }
3059
    $user = api_get_user_info();
3060
3061
    return
3062
        isset($user['status']) &&
3063
        (
3064
            ($allowSessionAdmins && SESSIONADMIN == $user['status']) ||
3065
            ($allowDrh && DRH == $user['status'])
3066
        );
3067
}
3068
3069
/**
3070
 * Checks whether the user given as user id is in the admin table.
3071
 *
3072
 * @param int $user_id If none provided, will use current user
3073
 * @param int $url     URL ID. If provided, also check if the user is active on given URL
3074
 *
3075
 * @return bool True if the user is admin, false otherwise
3076
 */
3077
function api_is_platform_admin_by_id($user_id = null, $url = null)
3078
{
3079
    $user_id = (int) $user_id;
3080
    if (empty($user_id)) {
3081
        $user_id = api_get_user_id();
3082
    }
3083
    $admin_table = Database::get_main_table(TABLE_MAIN_ADMIN);
3084
    $sql = "SELECT * FROM $admin_table WHERE user_id = $user_id";
3085
    $res = Database::query($sql);
3086
    $is_admin = 1 === Database::num_rows($res);
3087
    if (!$is_admin || !isset($url)) {
3088
        return $is_admin;
3089
    }
3090
    // We get here only if $url is set
3091
    $url = (int) $url;
3092
    $url_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
3093
    $sql = "SELECT * FROM $url_user_table
3094
            WHERE access_url_id = $url AND user_id = $user_id";
3095
    $res = Database::query($sql);
3096
    $result = 1 === Database::num_rows($res);
3097
3098
    return $result;
3099
}
3100
3101
/**
3102
 * Returns the user's numeric status ID from the users table.
3103
 *
3104
 * @param int $user_id If none provided, will use current user
3105
 *
3106
 * @return int User's status (1 for teacher, 5 for student, etc)
3107
 */
3108
function api_get_user_status($user_id = null)
3109
{
3110
    $user_id = (int) $user_id;
3111
    if (empty($user_id)) {
3112
        $user_id = api_get_user_id();
3113
    }
3114
    $table = Database::get_main_table(TABLE_MAIN_USER);
3115
    $sql = "SELECT status FROM $table WHERE user_id = $user_id ";
3116
    $result = Database::query($sql);
3117
    $status = null;
3118
    if (Database::num_rows($result)) {
3119
        $row = Database::fetch_array($result);
3120
        $status = $row['status'];
3121
    }
3122
3123
    return $status;
3124
}
3125
3126
/**
3127
 * Checks whether current user is allowed to create courses.
3128
 *
3129
 * @return bool true if the user has course creation rights,
3130
 *              false otherwise
3131
 */
3132
function api_is_allowed_to_create_course()
3133
{
3134
    if (api_is_platform_admin()) {
3135
        return true;
3136
    }
3137
3138
    // Teachers can only create courses
3139
    if (api_is_teacher()) {
3140
        if ('true' === api_get_setting('allow_users_to_create_courses')) {
3141
            return true;
3142
        } else {
3143
            return false;
3144
        }
3145
    }
3146
3147
    return Session::read('is_allowedCreateCourse');
3148
}
3149
3150
/**
3151
 * Checks whether the current user is a course administrator.
3152
 *
3153
 * @return bool True if current user is a course administrator
3154
 */
3155
function api_is_course_admin()
3156
{
3157
    if (api_is_platform_admin()) {
3158
        return true;
3159
    }
3160
3161
    $user = api_get_current_user();
3162
    if ($user) {
3163
        if (
3164
            $user->hasRole('ROLE_CURRENT_SESSION_COURSE_TEACHER') ||
3165
            $user->hasRole('ROLE_CURRENT_COURSE_TEACHER')
3166
        ) {
3167
            return true;
3168
        }
3169
    }
3170
3171
    return false;
3172
    //return Session::read('is_courseAdmin');
3173
}
3174
3175
/**
3176
 * Checks whether the current user is a course coach
3177
 * Based on the presence of user in session.id_coach (session general coach).
3178
 *
3179
 * @return bool True if current user is a course coach
3180
 */
3181
function api_is_session_general_coach()
3182
{
3183
    return Session::read('is_session_general_coach');
3184
}
3185
3186
/**
3187
 * Checks whether the current user is a course tutor
3188
 * Based on the presence of user in session_rel_course_rel_user.user_id with status = 2.
3189
 *
3190
 * @return bool True if current user is a course tutor
3191
 */
3192
function api_is_course_tutor()
3193
{
3194
    return Session::read('is_courseTutor');
3195
}
3196
3197
/**
3198
 * @param int $user_id
3199
 * @param int $courseId
3200
 * @param int $session_id
3201
 *
3202
 * @return bool
3203
 */
3204
function api_is_course_session_coach($user_id, $courseId, $session_id)
3205
{
3206
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
3207
    $session_rel_course_rel_user_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
3208
3209
    $user_id = (int) $user_id;
3210
    $session_id = (int) $session_id;
3211
    $courseId = (int) $courseId;
3212
3213
    $sql = "SELECT DISTINCT session.id
3214
            FROM $session_table
3215
            INNER JOIN $session_rel_course_rel_user_table session_rc_ru
3216
            ON session.id = session_rc_ru.session_id
3217
            WHERE
3218
                session_rc_ru.user_id = '".$user_id."'  AND
3219
                session_rc_ru.c_id = '$courseId' AND
3220
                session_rc_ru.status = 2 AND
3221
                session_rc_ru.session_id = '$session_id'";
3222
    $result = Database::query($sql);
3223
3224
    return Database::num_rows($result) > 0;
3225
}
3226
3227
/**
3228
 * Checks whether the current user is a course or session coach.
3229
 *
3230
 * @param int $session_id
3231
 * @param int $courseId
3232
 * @param bool  Check whether we are in student view and, if we are, return false
3233
 *
3234
 * @return bool True if current user is a course or session coach
3235
 */
3236
function api_is_coach($session_id = 0, $courseId = null, $check_student_view = true)
3237
{
3238
    $userId = api_get_user_id();
3239
3240
    if (!empty($session_id)) {
3241
        $session_id = (int) $session_id;
3242
    } else {
3243
        $session_id = api_get_session_id();
3244
    }
3245
3246
    // The student preview was on
3247
    if ($check_student_view && api_is_student_view_active()) {
3248
        return false;
3249
    }
3250
3251
    if (!empty($courseId)) {
3252
        $courseId = (int) $courseId;
3253
    } else {
3254
        $courseId = api_get_course_int_id();
3255
    }
3256
3257
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
3258
    $session_rel_course_rel_user_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
3259
    $sessionIsCoach = [];
3260
3261
    if (!empty($courseId)) {
3262
        $sql = "SELECT DISTINCT s.id, name, access_start_date, access_end_date
3263
                FROM $session_table s
3264
                INNER JOIN $session_rel_course_rel_user_table session_rc_ru
3265
                ON session_rc_ru.session_id = s.id AND session_rc_ru.user_id = '".$userId."'
3266
                WHERE
3267
                    session_rc_ru.c_id = '$courseId' AND
3268
                    session_rc_ru.status = 2 AND
3269
                    session_rc_ru.session_id = '$session_id'";
3270
        $result = Database::query($sql);
3271
        $sessionIsCoach = Database::store_result($result);
3272
    }
3273
3274
    if (!empty($session_id)) {
3275
        $sql = "SELECT DISTINCT id, name, access_start_date, access_end_date
3276
                FROM $session_table
3277
                WHERE session.id_coach = $userId AND id = $session_id
3278
                ORDER BY access_start_date, access_end_date, name";
3279
        $result = Database::query($sql);
3280
        if (!empty($sessionIsCoach)) {
3281
            $sessionIsCoach = array_merge(
3282
                $sessionIsCoach,
3283
                Database::store_result($result)
3284
            );
3285
        } else {
3286
            $sessionIsCoach = Database::store_result($result);
3287
        }
3288
    }
3289
3290
    return count($sessionIsCoach) > 0;
3291
}
3292
3293
/**
3294
 * Checks whether the current user is a session administrator.
3295
 *
3296
 * @return bool True if current user is a course administrator
3297
 */
3298
function api_is_session_admin()
3299
{
3300
    $user = api_get_user_info();
3301
3302
    return isset($user['status']) && SESSIONADMIN == $user['status'];
3303
}
3304
3305
/**
3306
 * Checks whether the current user is a human resources manager.
3307
 *
3308
 * @return bool True if current user is a human resources manager
3309
 */
3310
function api_is_drh()
3311
{
3312
    $user = api_get_user_info();
3313
3314
    return isset($user['status']) && DRH == $user['status'];
3315
}
3316
3317
/**
3318
 * Checks whether the current user is a student.
3319
 *
3320
 * @return bool True if current user is a human resources manager
3321
 */
3322
function api_is_student()
3323
{
3324
    $user = api_get_user_info();
3325
3326
    return isset($user['status']) && STUDENT == $user['status'];
3327
}
3328
3329
/**
3330
 * Checks whether the current user has the status 'teacher'.
3331
 *
3332
 * @return bool True if current user is a human resources manager
3333
 */
3334
function api_is_teacher()
3335
{
3336
    $user = api_get_user_info();
3337
3338
    return isset($user['status']) && COURSEMANAGER == $user['status'];
3339
}
3340
3341
/**
3342
 * Checks whether the current user is a invited user.
3343
 *
3344
 * @return bool
3345
 */
3346
function api_is_invitee()
3347
{
3348
    $user = api_get_user_info();
3349
3350
    return isset($user['status']) && INVITEE == $user['status'];
3351
}
3352
3353
/**
3354
 * This function checks whether a session is assigned into a category.
3355
 *
3356
 * @param int       - session id
0 ignored issues
show
Documentation Bug introduced by
The doc comment - at position 0 could not be parsed: Unknown type name '-' at position 0 in -.
Loading history...
3357
 * @param string    - category name
3358
 *
3359
 * @return bool - true if is found, otherwise false
3360
 */
3361
function api_is_session_in_category($session_id, $category_name)
3362
{
3363
    $session_id = (int) $session_id;
3364
    $category_name = Database::escape_string($category_name);
3365
    $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
3366
    $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3367
3368
    $sql = "SELECT 1
3369
            FROM $tbl_session
3370
            WHERE $session_id IN (
3371
                SELECT s.id FROM $tbl_session s, $tbl_session_category sc
3372
                WHERE
3373
                  s.session_category_id = sc.id AND
3374
                  sc.name LIKE '%$category_name'
3375
            )";
3376
    $rs = Database::query($sql);
3377
3378
    if (Database::num_rows($rs) > 0) {
3379
        return true;
3380
    } else {
3381
        return false;
3382
    }
3383
}
3384
3385
/**
3386
 * Displays the title of a tool.
3387
 * Normal use: parameter is a string:
3388
 * api_display_tool_title("My Tool").
3389
 *
3390
 * Optionally, there can be a subtitle below
3391
 * the normal title, and / or a supra title above the normal title.
3392
 *
3393
 * e.g. supra title:
3394
 * group
3395
 * GROUP PROPERTIES
3396
 *
3397
 * e.g. subtitle:
3398
 * AGENDA
3399
 * calender & events tool
3400
 *
3401
 * @author Hugues Peeters <[email protected]>
3402
 *
3403
 * @param mixed $title_element - it could either be a string or an array
3404
 *                             containing 'supraTitle', 'mainTitle',
3405
 *                             'subTitle'
3406
 */
3407
function api_display_tool_title($title_element)
3408
{
3409
    if (is_string($title_element)) {
3410
        $tit = $title_element;
3411
        unset($title_element);
3412
        $title_element['mainTitle'] = $tit;
3413
    }
3414
    echo '<h3>';
3415
    if (!empty($title_element['supraTitle'])) {
3416
        echo '<small>'.$title_element['supraTitle'].'</small><br />';
3417
    }
3418
    if (!empty($title_element['mainTitle'])) {
3419
        echo $title_element['mainTitle'];
3420
    }
3421
    if (!empty($title_element['subTitle'])) {
3422
        echo '<br /><small>'.$title_element['subTitle'].'</small>';
3423
    }
3424
    echo '</h3>';
3425
}
3426
3427
/**
3428
 * Displays options for switching between student view and course manager view.
3429
 *
3430
 * Changes in version 1.2 (Patrick Cool)
3431
 * Student view switch now behaves as a real switch. It maintains its current state until the state
3432
 * is changed explicitly
3433
 *
3434
 * Changes in version 1.1 (Patrick Cool)
3435
 * student view now works correctly in subfolders of the document tool
3436
 * student view works correctly in the new links tool
3437
 *
3438
 * Example code for using this in your tools:
3439
 * //if ($is_courseAdmin && api_get_setting('student_view_enabled') == 'true') {
3440
 * //   display_tool_view_option($isStudentView);
3441
 * //}
3442
 * //and in later sections, use api_is_allowed_to_edit()
3443
 *
3444
 * @author Roan Embrechts
3445
 * @author Patrick Cool
3446
 * @author Julio Montoya, changes added in Chamilo
3447
 *
3448
 * @version 1.2
3449
 *
3450
 * @todo rewrite code so it is easier to understand
3451
 */
3452
function api_display_tool_view_option()
3453
{
3454
    if ('true' != api_get_setting('student_view_enabled')) {
3455
        return '';
3456
    }
3457
3458
    $sourceurl = '';
3459
    $is_framed = false;
3460
    // Exceptions apply for all multi-frames pages
3461
    if (false !== strpos($_SERVER['REQUEST_URI'], 'chat/chat_banner.php')) {
3462
        // The chat is a multiframe bit that doesn't work too well with the student_view, so do not show the link
3463
        return '';
3464
    }
3465
3466
    // Uncomment to remove student view link from document view page
3467
    if (false !== strpos($_SERVER['REQUEST_URI'], 'lp/lp_header.php')) {
3468
        if (empty($_GET['lp_id'])) {
3469
            return '';
3470
        }
3471
        $sourceurl = substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], '?'));
3472
        $sourceurl = str_replace(
3473
            'lp/lp_header.php',
3474
            'lp/lp_controller.php?'.api_get_cidreq().'&action=view&lp_id='.intval($_GET['lp_id']).'&isStudentView='.('studentview' == $_SESSION['studentview'] ? 'false' : 'true'),
3475
            $sourceurl
3476
        );
3477
        //showinframes doesn't handle student view anyway...
3478
        //return '';
3479
        $is_framed = true;
3480
    }
3481
3482
    // Check whether the $_SERVER['REQUEST_URI'] contains already url parameters (thus a questionmark)
3483
    if (!$is_framed) {
3484
        if (false === strpos($_SERVER['REQUEST_URI'], '?')) {
3485
            $sourceurl = api_get_self().'?'.api_get_cidreq();
3486
        } else {
3487
            $sourceurl = $_SERVER['REQUEST_URI'];
3488
        }
3489
    }
3490
3491
    $output_string = '';
3492
    if (!empty($_SESSION['studentview'])) {
3493
        if ('studentview' == $_SESSION['studentview']) {
3494
            // We have to remove the isStudentView=true from the $sourceurl
3495
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
3496
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
3497
            $output_string .= '<a class="btn btn-primary btn-sm" href="'.$sourceurl.'&isStudentView=false" target="_self">'.
3498
                Display::returnFontAwesomeIcon('eye').' '.get_lang('Switch to teacher view').'</a>';
3499
        } elseif ('teacherview' == $_SESSION['studentview']) {
3500
            // Switching to teacherview
3501
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
3502
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
3503
            $output_string .= '<a class="btn btn-default btn-sm" href="'.$sourceurl.'&isStudentView=true" target="_self">'.
3504
                Display::returnFontAwesomeIcon('eye').' '.get_lang('Switch to student view').'</a>';
3505
        }
3506
    } else {
3507
        $output_string .= '<a class="btn btn-default btn-sm" href="'.$sourceurl.'&isStudentView=true" target="_self">'.
3508
            Display::returnFontAwesomeIcon('eye').' '.get_lang('Switch to student view').'</a>';
3509
    }
3510
    $output_string = Security::remove_XSS($output_string);
3511
    $html = Display::tag('div', $output_string, ['class' => 'view-options']);
3512
3513
    return $html;
3514
}
3515
3516
// TODO: This is for the permission section.
3517
/**
3518
 * Function that removes the need to directly use is_courseAdmin global in
3519
 * tool scripts. It returns true or false depending on the user's rights in
3520
 * this particular course.
3521
 * Optionally checking for tutor and coach roles here allows us to use the
3522
 * student_view feature altogether with these roles as well.
3523
 *
3524
 * @param bool  Whether to check if the user has the tutor role
3525
 * @param bool  Whether to check if the user has the coach role
3526
 * @param bool  Whether to check if the user has the session coach role
3527
 * @param bool  check the student view or not
3528
 *
3529
 * @author Roan Embrechts
3530
 * @author Patrick Cool
3531
 * @author Julio Montoya
3532
 *
3533
 * @version 1.1, February 2004
3534
 *
3535
 * @return bool true: the user has the rights to edit, false: he does not
3536
 */
3537
function api_is_allowed_to_edit(
3538
    $tutor = false,
3539
    $coach = false,
3540
    $session_coach = false,
3541
    $check_student_view = true
3542
) {
3543
    $allowSessionAdminEdit = true === api_get_setting('session.session_admins_edit_courses_content');
3544
    // Admins can edit anything.
3545
    if (api_is_platform_admin($allowSessionAdminEdit)) {
3546
        //The student preview was on
3547
        if ($check_student_view && api_is_student_view_active()) {
3548
            return false;
3549
        } else {
3550
            return true;
3551
        }
3552
    }
3553
3554
    $sessionId = api_get_session_id();
3555
3556
    if ($sessionId && api_get_configuration_value('session_courses_read_only_mode')) {
3557
        $efv = new ExtraFieldValue('course');
3558
        $lockExrafieldField = $efv->get_values_by_handler_and_field_variable(
3559
            api_get_course_int_id(),
3560
            'session_courses_read_only_mode'
3561
        );
3562
3563
        if (!empty($lockExrafieldField['value'])) {
3564
            return false;
3565
        }
3566
    }
3567
3568
    $is_allowed_coach_to_edit = api_is_coach(null, null, $check_student_view);
3569
    $session_visibility = api_get_session_visibility($sessionId);
3570
    $is_courseAdmin = api_is_course_admin();
3571
3572
    if (!$is_courseAdmin && $tutor) {
3573
        // If we also want to check if the user is a tutor...
3574
        $is_courseAdmin = $is_courseAdmin || api_is_course_tutor();
3575
    }
3576
3577
    if (!$is_courseAdmin && $coach) {
3578
        // If we also want to check if the user is a coach...';
3579
        // Check if session visibility is read only for coaches.
3580
        if (SESSION_VISIBLE_READ_ONLY == $session_visibility) {
3581
            $is_allowed_coach_to_edit = false;
3582
        }
3583
3584
        if ('true' === api_get_setting('allow_coach_to_edit_course_session')) {
3585
            // Check if coach is allowed to edit a course.
3586
            $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
3587
        }
3588
    }
3589
3590
    if (!$is_courseAdmin && $session_coach) {
3591
        $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
3592
    }
3593
3594
    // Check if the student_view is enabled, and if so, if it is activated.
3595
    if ('true' === api_get_setting('student_view_enabled')) {
3596
        $studentView = api_is_student_view_active();
3597
        if (!empty($sessionId)) {
3598
            // Check if session visibility is read only for coaches.
3599
            if (SESSION_VISIBLE_READ_ONLY == $session_visibility) {
3600
                $is_allowed_coach_to_edit = false;
3601
            }
3602
3603
            $is_allowed = false;
3604
            if ('true' === api_get_setting('allow_coach_to_edit_course_session')) {
3605
                // Check if coach is allowed to edit a course.
3606
                $is_allowed = $is_allowed_coach_to_edit;
3607
            }
3608
            if ($check_student_view) {
3609
                $is_allowed = $is_allowed && false === $studentView;
3610
            }
3611
        } else {
3612
            $is_allowed = $is_courseAdmin;
3613
            if ($check_student_view) {
3614
                $is_allowed = $is_courseAdmin && false === $studentView;
3615
            }
3616
        }
3617
3618
        return $is_allowed;
3619
    } else {
3620
        return $is_courseAdmin;
3621
    }
3622
}
3623
3624
/**
3625
 * Returns true if user is a course coach of at least one course in session.
3626
 *
3627
 * @param int $sessionId
3628
 *
3629
 * @return bool
3630
 */
3631
function api_is_coach_of_course_in_session($sessionId)
3632
{
3633
    if (api_is_platform_admin()) {
3634
        return true;
3635
    }
3636
3637
    $userId = api_get_user_id();
3638
    $courseList = UserManager::get_courses_list_by_session(
3639
        $userId,
3640
        $sessionId
3641
    );
3642
3643
    // Session visibility.
3644
    $visibility = api_get_session_visibility(
3645
        $sessionId,
3646
        null,
3647
        false
3648
    );
3649
3650
    if (SESSION_VISIBLE != $visibility && !empty($courseList)) {
3651
        // Course Coach session visibility.
3652
        $blockedCourseCount = 0;
3653
        $closedVisibilityList = [
3654
            COURSE_VISIBILITY_CLOSED,
3655
            COURSE_VISIBILITY_HIDDEN,
3656
        ];
3657
3658
        foreach ($courseList as $course) {
3659
            // Checking session visibility
3660
            $sessionCourseVisibility = api_get_session_visibility(
3661
                $sessionId,
3662
                $course['real_id']
3663
            );
3664
3665
            $courseIsVisible = !in_array(
3666
                $course['visibility'],
3667
                $closedVisibilityList
3668
            );
3669
            if (false === $courseIsVisible || SESSION_INVISIBLE == $sessionCourseVisibility) {
3670
                $blockedCourseCount++;
3671
            }
3672
        }
3673
3674
        // If all courses are blocked then no show in the list.
3675
        if ($blockedCourseCount === count($courseList)) {
3676
            $visibility = SESSION_INVISIBLE;
3677
        } else {
3678
            $visibility = SESSION_VISIBLE;
3679
        }
3680
    }
3681
3682
    switch ($visibility) {
3683
        case SESSION_VISIBLE_READ_ONLY:
3684
        case SESSION_VISIBLE:
3685
        case SESSION_AVAILABLE:
3686
            return true;
3687
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
3688
        case SESSION_INVISIBLE:
3689
            return false;
3690
    }
3691
3692
    return false;
3693
}
3694
3695
/**
3696
 * Checks if a student can edit contents in a session depending
3697
 * on the session visibility.
3698
 *
3699
 * @param bool $tutor Whether to check if the user has the tutor role
3700
 * @param bool $coach Whether to check if the user has the coach role
3701
 *
3702
 * @return bool true: the user has the rights to edit, false: he does not
3703
 */
3704
function api_is_allowed_to_session_edit($tutor = false, $coach = false)
3705
{
3706
    if (api_is_allowed_to_edit($tutor, $coach)) {
3707
        // If I'm a teacher, I will return true in order to not affect the normal behaviour of Chamilo tools.
3708
        return true;
3709
    } else {
3710
        $sessionId = api_get_session_id();
3711
3712
        if (0 == $sessionId) {
3713
            // I'm not in a session so i will return true to not affect the normal behaviour of Chamilo tools.
3714
            return true;
3715
        } else {
3716
            // I'm in a session and I'm a student
3717
            // Get the session visibility
3718
            $session_visibility = api_get_session_visibility($sessionId);
3719
            // if 5 the session is still available
3720
            switch ($session_visibility) {
3721
                case SESSION_VISIBLE_READ_ONLY: // 1
3722
                    return false;
3723
                case SESSION_VISIBLE:           // 2
3724
                    return true;
3725
                case SESSION_INVISIBLE:         // 3
3726
                    return false;
3727
                case SESSION_AVAILABLE:         //5
3728
                    return true;
3729
            }
3730
        }
3731
    }
3732
3733
    return false;
3734
}
3735
3736
/**
3737
 * Checks whether the user is allowed in a specific tool for a specific action.
3738
 *
3739
 * @param string $tool   the tool we are checking if the user has a certain permission
3740
 * @param string $action the action we are checking (add, edit, delete, move, visibility)
3741
 *
3742
 * @return bool
3743
 *
3744
 * @author Patrick Cool <[email protected]>, Ghent University
3745
 * @author Julio Montoya
3746
 *
3747
 * @version 1.0
3748
 */
3749
function api_is_allowed($tool, $action, $task_id = 0)
3750
{
3751
    $_user = api_get_user_info();
3752
    $_course = api_get_course_info();
3753
3754
    if (api_is_course_admin()) {
3755
        return true;
3756
    }
3757
3758
    if (is_array($_course) and count($_course) > 0) {
3759
        require_once api_get_path(SYS_CODE_PATH).'permissions/permissions_functions.inc.php';
3760
3761
        // Getting the permissions of this user.
3762
        if (0 == $task_id) {
3763
            $user_permissions = get_permissions('user', $_user['user_id']);
3764
            $_SESSION['total_permissions'][$_course['code']] = $user_permissions;
3765
        }
3766
3767
        // Getting the permissions of the task.
3768
        if (0 != $task_id) {
3769
            $task_permissions = get_permissions('task', $task_id);
3770
            /* !!! */$_SESSION['total_permissions'][$_course['code']] = $task_permissions;
3771
        }
3772
        //print_r($_SESSION['total_permissions']);
3773
3774
        // Getting the permissions of the groups of the user
3775
        //$groups_of_user = GroupManager::get_group_ids($_course['db_name'], $_user['user_id']);
3776
3777
        //foreach($groups_of_user as $group)
3778
        //   $this_group_permissions = get_permissions('group', $group);
3779
3780
        // Getting the permissions of the courseroles of the user
3781
        $user_courserole_permissions = get_roles_permissions('user', $_user['user_id']);
3782
3783
        // Getting the permissions of the platformroles of the user
3784
        //$user_platformrole_permissions = get_roles_permissions('user', $_user['user_id'], ', platform');
3785
3786
        // Getting the permissions of the roles of the groups of the user
3787
        //foreach($groups_of_user as $group)
3788
        //    $this_group_courserole_permissions = get_roles_permissions('group', $group);
3789
3790
        // Getting the permissions of the platformroles of the groups of the user
3791
        //foreach($groups_of_user as $group)
3792
        //    $this_group_platformrole_permissions = get_roles_permissions('group', $group, 'platform');
3793
    }
3794
3795
    // If the permissions are limited, we have to map the extended ones to the limited ones.
3796
    if ('limited' == api_get_setting('permissions')) {
3797
        if ('Visibility' == $action) {
3798
            $action = 'Edit';
3799
        }
3800
        if ('Move' == $action) {
3801
            $action = 'Edit';
3802
        }
3803
    }
3804
3805
    // The session that contains all the permissions already exists for this course
3806
    // so there is no need to requery everything.
3807
    //my_print_r($_SESSION['total_permissions'][$_course['code']][$tool]);
3808
    if (is_array($_SESSION['total_permissions'][$_course['code']][$tool])) {
3809
        if (in_array($action, $_SESSION['total_permissions'][$_course['code']][$tool])) {
3810
            return true;
3811
        } else {
3812
            return false;
3813
        }
3814
    }
3815
}
3816
3817
/**
3818
 * Tells whether this user is an anonymous user.
3819
 *
3820
 * @param int  $user_id  User ID (optional, will take session ID if not provided)
3821
 * @param bool $db_check Whether to check in the database (true) or simply in
3822
 *                       the session (false) to see if the current user is the anonymous user
3823
 *
3824
 * @return bool true if this user is anonymous, false otherwise
3825
 */
3826
function api_is_anonymous($user_id = null, $db_check = false)
3827
{
3828
    if ($db_check) {
3829
        if (!isset($user_id)) {
3830
            $user_id = api_get_user_id();
3831
        }
3832
3833
        $info = api_get_user_info($user_id);
3834
3835
        if (6 == $info['status'] || 0 == $user_id || empty($info)) {
3836
            return true;
3837
        }
3838
    }
3839
3840
    return !Container::getAuthorizationChecker()->isGranted('IS_AUTHENTICATED_FULLY');
3841
}
3842
3843
/**
3844
 * Displays message "You are not allowed here..." and exits the entire script.
3845
 *
3846
 * @param bool   $print_headers Whether or not to print headers (default = false -> does not print them)
3847
 * @param string $message
3848
 * @param int    $responseCode
3849
 */
3850
function api_not_allowed(
3851
    $print_headers = false,
3852
    $message = null,
3853
    $responseCode = 0
3854
) {
3855
    throw new Exception('You are not allowed');
3856
}
3857
3858
/**
3859
 * Gets a UNIX timestamp from a database (MySQL) datetime format string.
3860
 *
3861
 * @param $last_post_datetime standard output date in a sql query
3862
 *
3863
 * @return int timestamp
3864
 *
3865
 * @author Toon Van Hoecke <[email protected]>
3866
 *
3867
 * @version October 2003
3868
 * @desc convert sql date to unix timestamp
3869
 */
3870
function convert_sql_date($last_post_datetime)
3871
{
3872
    list($last_post_date, $last_post_time) = explode(' ', $last_post_datetime);
3873
    list($year, $month, $day) = explode('-', $last_post_date);
3874
    list($hour, $min, $sec) = explode(':', $last_post_time);
3875
3876
    return mktime((int) $hour, (int) $min, (int) $sec, (int) $month, (int) $day, (int) $year);
3877
}
3878
3879
/**
3880
 * Gets item visibility from the item_property table.
3881
 *
3882
 * Getting the visibility is done by getting the last updated visibility entry,
3883
 * using the largest session ID found if session 0 and another was found (meaning
3884
 * the only one that is actually from the session, in case there are results from
3885
 * session 0 *AND* session n).
3886
 *
3887
 * @param array  $_course  Course properties array (result of api_get_course_info())
3888
 * @param string $tool     Tool (learnpath, document, etc)
3889
 * @param int    $id       The item ID in the given tool
3890
 * @param int    $session  The session ID (optional)
3891
 * @param int    $user_id
3892
 * @param string $type
3893
 * @param string $group_id
3894
 *
3895
 * @return int -1 on error, 0 if invisible, 1 if visible
3896
 */
3897
function api_get_item_visibility(
3898
    $_course,
3899
    $tool,
3900
    $id,
3901
    $session = 0,
3902
    $user_id = null,
3903
    $type = null,
3904
    $group_id = null
3905
) {
3906
    if (!is_array($_course) || 0 == count($_course) || empty($tool) || empty($id)) {
3907
        return -1;
3908
    }
3909
3910
    // 0 visible
3911
    // 1 visible
3912
    // 2 deleted
3913
3914
    switch ($tool) {
3915
        case 'learnpath':
3916
3917
            break;
3918
    }
3919
3920
    $tool = Database::escape_string($tool);
3921
    $id = (int) $id;
3922
    $session = (int) $session;
3923
    $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
3924
    $course_id = (int) $_course['real_id'];
3925
3926
    $userCondition = '';
3927
    if (!empty($user_id)) {
3928
        $user_id = (int) $user_id;
3929
        $userCondition = " AND to_user_id = $user_id ";
3930
    }
3931
3932
    $typeCondition = '';
3933
    if (!empty($type)) {
3934
        $type = Database::escape_string($type);
3935
        $typeCondition = " AND lastedit_type = '$type' ";
3936
    }
3937
3938
    $groupCondition = '';
3939
    if (!empty($group_id)) {
3940
        $group_id = (int) $group_id;
3941
        $groupCondition = " AND to_group_id = '$group_id' ";
3942
    }
3943
3944
    $sql = "SELECT visibility
3945
            FROM $TABLE_ITEMPROPERTY
3946
            WHERE
3947
                c_id = $course_id AND
3948
                tool = '$tool' AND
3949
                ref = $id AND
3950
                (session_id = $session OR session_id = 0 OR session_id IS NULL)
3951
                $userCondition $typeCondition $groupCondition
3952
            ORDER BY session_id DESC, lastedit_date DESC
3953
            LIMIT 1";
3954
3955
    $res = Database::query($sql);
3956
    if (false === $res || 0 == Database::num_rows($res)) {
3957
        return -1;
3958
    }
3959
    $row = Database::fetch_array($res);
3960
3961
    return (int) $row['visibility'];
3962
}
3963
3964
/**
3965
 * Delete a row in the c_item_property table.
3966
 *
3967
 * @param array  $courseInfo
3968
 * @param string $tool
3969
 * @param int    $itemId
3970
 * @param int    $userId
3971
 * @param int    $groupId    group.iid
3972
 * @param int    $sessionId
3973
 *
3974
 * @return false|null
3975
 */
3976
function api_item_property_delete(
3977
    $courseInfo,
3978
    $tool,
3979
    $itemId,
3980
    $userId,
3981
    $groupId = 0,
3982
    $sessionId = 0
3983
) {
3984
    if (empty($courseInfo)) {
3985
        return false;
3986
    }
3987
3988
    $courseId = (int) $courseInfo['real_id'];
3989
3990
    if (empty($courseId) || empty($tool) || empty($itemId)) {
3991
        return false;
3992
    }
3993
3994
    $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3995
    $tool = Database::escape_string($tool);
3996
    $itemId = intval($itemId);
3997
    $userId = intval($userId);
3998
    $groupId = intval($groupId);
3999
    $sessionId = intval($sessionId);
4000
4001
    $groupCondition = " AND to_group_id = $groupId ";
4002
    if (empty($groupId)) {
4003
        $groupCondition = " AND (to_group_id is NULL OR to_group_id = 0) ";
4004
    }
4005
4006
    $userCondition = " AND to_user_id = $userId ";
4007
    if (empty($userId)) {
4008
        $userCondition = " AND (to_user_id is NULL OR to_user_id = 0) ";
4009
    }
4010
    $sessionCondition = api_get_session_condition($sessionId, true, false, 'session_id');
4011
    $sql = "DELETE FROM $table
4012
            WHERE
4013
                c_id = $courseId AND
4014
                tool  = '$tool' AND
4015
                ref = $itemId
4016
                $sessionCondition
4017
                $userCondition
4018
                $groupCondition
4019
            ";
4020
4021
    Database::query($sql);
4022
}
4023
4024
/**
4025
 * Updates or adds item properties to the Item_propetry table
4026
 * Tool and lastedit_type are language independant strings (langvars->get_lang!).
4027
 *
4028
 * @param array  $_course        array with course properties
4029
 * @param string $tool           tool id, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
4030
 * @param int    $item_id        id of the item itself, linked to key of every tool ('id', ...)
4031
 * @param string $last_edit_type add or update action
4032
 *                               (1) message to be translated (in trad4all) : e.g. DocumentAdded, DocumentUpdated;
4033
 *                               (2) "delete"
4034
 *                               (3) "visible"
4035
 *                               (4) "invisible"
4036
 * @param int    $user_id        id of the editing/adding user
4037
 * @param array  $groupInfo      must include group.iid/group.od
4038
 * @param int    $to_user_id     id of the intended user (always has priority over $to_group_id !), only relevant for $type (1)
4039
 * @param string $start_visible  0000-00-00 00:00:00 format
4040
 * @param string $end_visible    0000-00-00 00:00:00 format
4041
 * @param int    $session_id     The session ID, if any, otherwise will default to 0
4042
 *
4043
 * @return bool false if update fails
4044
 *
4045
 * @author Toon Van Hoecke <[email protected]>, Ghent University
4046
 *
4047
 * @version January 2005
4048
 * @desc update the item_properties table (if entry not exists, insert) of the course
4049
 */
4050
function api_item_property_update(
4051
    $_course,
4052
    $tool,
4053
    $item_id,
4054
    $last_edit_type,
4055
    $user_id,
4056
    $groupInfo = [],
4057
    $to_user_id = null,
4058
    $start_visible = '',
4059
    $end_visible = '',
4060
    $session_id = 0
4061
) {
4062
    if (empty($_course)) {
4063
        return false;
4064
    }
4065
4066
    $course_id = $_course['real_id'];
4067
4068
    if (empty($course_id)) {
4069
        return false;
4070
    }
4071
4072
    $to_group_id = 0;
4073
    if (!empty($groupInfo) && isset($groupInfo['iid'])) {
4074
        $to_group_id = (int) $groupInfo['iid'];
4075
    }
4076
4077
    $em = Database::getManager();
4078
4079
    // Definition of variables.
4080
    $tool = Database::escape_string($tool);
4081
    $item_id = (int) $item_id;
4082
    $lastEditTypeNoFilter = $last_edit_type;
4083
    $last_edit_type = Database::escape_string($last_edit_type);
4084
    $user_id = (int) $user_id;
4085
4086
    $startVisible = "NULL";
4087
    if (!empty($start_visible)) {
4088
        $start_visible = Database::escape_string($start_visible);
4089
        $startVisible = "'$start_visible'";
4090
    }
4091
4092
    $endVisible = "NULL";
4093
    if (!empty($end_visible)) {
4094
        $end_visible = Database::escape_string($end_visible);
4095
        $endVisible = "'$end_visible'";
4096
    }
4097
4098
    $to_filter = '';
4099
    $time = api_get_utc_datetime();
4100
4101
    if (!empty($session_id)) {
4102
        $session_id = (int) $session_id;
4103
    } else {
4104
        $session_id = api_get_session_id();
4105
    }
4106
4107
    // Definition of tables.
4108
    $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
4109
4110
    if ($to_user_id <= 0) {
4111
        $to_user_id = null; // No to_user_id set
4112
    }
4113
4114
    if (!is_null($to_user_id)) {
4115
        // $to_user_id has more priority than $to_group_id
4116
        $to_user_id = (int) $to_user_id;
4117
        $to_field = 'to_user_id';
4118
        $to_value = $to_user_id;
4119
    } else {
4120
        // $to_user_id is not set.
4121
        $to_field = 'to_group_id';
4122
        $to_value = $to_group_id;
4123
    }
4124
4125
    $toValueCondition = empty($to_value) ? 'NULL' : "'$to_value'";
4126
    // Set filters for $to_user_id and $to_group_id, with priority for $to_user_id
4127
    $condition_session = " AND session_id = $session_id ";
4128
    if (empty($session_id)) {
4129
        $condition_session = ' AND (session_id = 0 OR session_id IS NULL) ';
4130
    }
4131
4132
    $filter = " c_id = $course_id AND tool = '$tool' AND ref = $item_id $condition_session ";
4133
4134
    // Check whether $to_user_id and $to_group_id are passed in the function call.
4135
    // If both are not passed (both are null) then it is a message for everybody and $to_group_id should be 0 !
4136
    if (is_null($to_user_id) && is_null($to_group_id)) {
4137
        $to_group_id = 0;
4138
    }
4139
4140
    if (!is_null($to_user_id)) {
4141
        // Set filter to intended user.
4142
        $to_filter = " AND to_user_id = $to_user_id $condition_session";
4143
    } else {
4144
        // Set filter to intended group.
4145
        if ((0 != $to_group_id) && $to_group_id == strval(intval($to_group_id))) {
4146
            $to_filter = " AND to_group_id = $to_group_id $condition_session";
4147
        }
4148
    }
4149
4150
    // Adding filter if set.
4151
    $filter .= $to_filter;
4152
4153
    // Update if possible
4154
    $set_type = '';
4155
4156
    switch ($lastEditTypeNoFilter) {
4157
        case 'delete':
4158
            // delete = make item only visible for the platform admin.
4159
            $visibility = '2';
4160
            if (!empty($session_id)) {
4161
                // Check whether session id already exist into item_properties for updating visibility or add it.
4162
                $sql = "SELECT session_id FROM $tableItemProperty
4163
                        WHERE
4164
                            c_id = $course_id AND
4165
                            tool = '$tool' AND
4166
                            ref = $item_id AND
4167
                            session_id = $session_id";
4168
                $rs = Database::query($sql);
4169
                if (Database::num_rows($rs) > 0) {
4170
                    $sql = "UPDATE $tableItemProperty
4171
                            SET lastedit_type       = '".str_replace('_', '', ucwords($tool))."Deleted',
4172
                                lastedit_date       = '$time',
4173
                                lastedit_user_id    = $user_id,
4174
                                visibility          = $visibility,
4175
                                session_id          = $session_id $set_type
4176
                            WHERE $filter";
4177
                    $result = Database::query($sql);
4178
                } else {
4179
                    $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)
4180
                            VALUES ($course_id, '$tool',$item_id, '$time', $user_id, '$time', '$last_edit_type',$user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
4181
                    $result = Database::query($sql);
4182
                    $id = Database::insert_id();
4183
                    if ($id) {
4184
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
4185
                        Database::query($sql);
4186
                    }
4187
                }
4188
            } else {
4189
                $sql = "UPDATE $tableItemProperty
4190
                        SET
4191
                            lastedit_type='".str_replace('_', '', ucwords($tool))."Deleted',
4192
                            lastedit_date='$time',
4193
                            lastedit_user_id = $user_id,
4194
                            visibility = $visibility $set_type
4195
                        WHERE $filter";
4196
                $result = Database::query($sql);
4197
            }
4198
            break;
4199
        case 'visible': // Change item to visible.
4200
            $visibility = '1';
4201
            if (!empty($session_id)) {
4202
                // Check whether session id already exist into item_properties for updating visibility or add it.
4203
                $sql = "SELECT session_id FROM $tableItemProperty
4204
                        WHERE
4205
                            c_id = $course_id AND
4206
                            tool = '$tool' AND
4207
                            ref = $item_id AND
4208
                            session_id = $session_id";
4209
                $rs = Database::query($sql);
4210
                if (Database::num_rows($rs) > 0) {
4211
                    $sql = "UPDATE $tableItemProperty
4212
                            SET
4213
                                lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
4214
                                lastedit_date='$time',
4215
                                lastedit_user_id = $user_id,
4216
                                visibility = $visibility,
4217
                                session_id = $session_id $set_type
4218
                            WHERE $filter";
4219
                    $result = Database::query($sql);
4220
                } else {
4221
                    $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)
4222
                            VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
4223
                    $result = Database::query($sql);
4224
                    $id = Database::insert_id();
4225
                    if ($id) {
4226
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
4227
                        Database::query($sql);
4228
                    }
4229
                }
4230
            } else {
4231
                $sql = "UPDATE $tableItemProperty
4232
                        SET
4233
                            lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
4234
                            lastedit_date='$time',
4235
                            lastedit_user_id = $user_id,
4236
                            visibility = $visibility $set_type
4237
                        WHERE $filter";
4238
                $result = Database::query($sql);
4239
            }
4240
            break;
4241
        case 'invisible': // Change item to invisible.
4242
            $visibility = '0';
4243
            if (!empty($session_id)) {
4244
                // Check whether session id already exist into item_properties for updating visibility or add it
4245
                $sql = "SELECT session_id FROM $tableItemProperty
4246
                        WHERE
4247
                            c_id = $course_id AND
4248
                            tool = '$tool' AND
4249
                            ref = $item_id AND
4250
                            session_id = $session_id";
4251
                $rs = Database::query($sql);
4252
                if (Database::num_rows($rs) > 0) {
4253
                    $sql = "UPDATE $tableItemProperty
4254
                            SET
4255
                                lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
4256
                                lastedit_date = '$time',
4257
                                lastedit_user_id = $user_id,
4258
                                visibility = $visibility,
4259
                                session_id = $session_id $set_type
4260
                            WHERE $filter";
4261
                    $result = Database::query($sql);
4262
                } else {
4263
                    $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)
4264
                            VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
4265
                    $result = Database::query($sql);
4266
                    $id = Database::insert_id();
4267
                    if ($id) {
4268
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
4269
                        Database::query($sql);
4270
                    }
4271
                }
4272
            } else {
4273
                $sql = "UPDATE $tableItemProperty
4274
                        SET
4275
                            lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
4276
                            lastedit_date = '$time',
4277
                            lastedit_user_id = $user_id,
4278
                            visibility = $visibility $set_type
4279
                        WHERE $filter";
4280
                $result = Database::query($sql);
4281
            }
4282
            break;
4283
        default: // The item will be added or updated.
4284
            $set_type = ", lastedit_type = '$last_edit_type' ";
4285
            $visibility = '1';
4286
            //$filter .= $to_filter; already added
4287
            $sql = "UPDATE $tableItemProperty
4288
                    SET
4289
                      lastedit_date = '$time',
4290
                      lastedit_user_id = $user_id $set_type
4291
                    WHERE $filter";
4292
            $result = Database::query($sql);
4293
    }
4294
4295
    // Insert if no entries are found (can only happen in case of $last_edit_type switch is 'default').
4296
    if (false == $result || 0 == Database::affected_rows($result)) {
4297
        $objCourse = $em->find('ChamiloCoreBundle:Course', intval($course_id));
4298
        $objTime = new DateTime('now', new DateTimeZone('UTC'));
4299
        $objUser = api_get_user_entity($user_id);
4300
        if (empty($objUser)) {
4301
            // Use anonymous
4302
            $user_id = api_get_anonymous_id();
4303
            $objUser = api_get_user_entity($user_id);
4304
        }
4305
4306
        $objGroup = null;
4307
        if (!empty($to_group_id)) {
4308
            $objGroup = $em->find('ChamiloCourseBundle:CGroupInfo', $to_group_id);
4309
        }
4310
4311
        $objToUser = api_get_user_entity($to_user_id);
4312
        $objSession = $em->find('ChamiloCoreBundle:Session', intval($session_id));
4313
4314
        $startVisibleDate = !empty($start_visible) ? new DateTime($start_visible, new DateTimeZone('UTC')) : null;
4315
        $endVisibleDate = !empty($endVisibleDate) ? new DateTime($endVisibleDate, new DateTimeZone('UTC')) : null;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $endVisibleDate seems to never exist and therefore empty should always be true.
Loading history...
4316
4317
        $cItemProperty = new CItemProperty($objCourse);
4318
        $cItemProperty
4319
            ->setTool($tool)
4320
            ->setRef($item_id)
4321
            ->setInsertDate($objTime)
4322
            ->setInsertUser($objUser)
4323
            ->setLasteditDate($objTime)
4324
            ->setLasteditType($last_edit_type)
4325
            ->setGroup($objGroup)
4326
            ->setToUser($objToUser)
4327
            ->setVisibility($visibility)
4328
            ->setStartVisible($startVisibleDate)
4329
            ->setEndVisible($endVisibleDate)
4330
            ->setSession($objSession);
4331
4332
        $em->persist($cItemProperty);
4333
        $em->flush();
4334
4335
        $id = $cItemProperty->getIid();
4336
4337
        if ($id) {
4338
            $cItemProperty->setId($id);
4339
            $em->merge($cItemProperty);
4340
            $em->flush();
4341
4342
            return false;
4343
        }
4344
    }
4345
4346
    return true;
4347
}
4348
4349
/**
4350
 * Gets item property by tool.
4351
 *
4352
 * @param string    course code
4353
 * @param string    tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
4354
 * @param int       id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
4355
 * @param int    $session_id
4356
 * @param string $tool
4357
 * @param string $course_code
4358
 *
4359
 * @return array All fields from c_item_property (all rows found) or empty array
4360
 */
4361
function api_get_item_property_by_tool($tool, $course_code, $session_id = null)
4362
{
4363
    $course_info = api_get_course_info($course_code);
4364
    $tool = Database::escape_string($tool);
4365
4366
    // Definition of tables.
4367
    $item_property_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
4368
    $session_id = (int) $session_id;
4369
    $session_condition = ' AND session_id = '.$session_id;
4370
    if (empty($session_id)) {
4371
        $session_condition = " AND (session_id = 0 OR session_id IS NULL) ";
4372
    }
4373
    $course_id = $course_info['real_id'];
4374
4375
    $sql = "SELECT * FROM $item_property_table
4376
            WHERE
4377
                c_id = $course_id AND
4378
                tool = '$tool'
4379
                $session_condition ";
4380
    $rs = Database::query($sql);
4381
    $list = [];
4382
    if (Database::num_rows($rs) > 0) {
4383
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
4384
            $list[] = $row;
4385
        }
4386
    }
4387
4388
    return $list;
4389
}
4390
4391
/**
4392
 * Gets item property by tool and user.
4393
 *
4394
 * @param int $userId
4395
 * @param int $tool
4396
 * @param int $courseId
4397
 * @param int $session_id
4398
 *
4399
 * @return array
4400
 */
4401
function api_get_item_property_list_by_tool_by_user(
4402
    $userId,
4403
    $tool,
4404
    $courseId,
4405
    $session_id = 0
4406
) {
4407
    $userId = intval($userId);
4408
    $tool = Database::escape_string($tool);
4409
    $session_id = intval($session_id);
4410
    $courseId = intval($courseId);
4411
4412
    // Definition of tables.
4413
    $item_property_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
4414
    $session_condition = ' AND session_id = '.$session_id;
4415
    if (empty($session_id)) {
4416
        $session_condition = " AND (session_id = 0 OR session_id IS NULL) ";
4417
    }
4418
    $sql = "SELECT * FROM $item_property_table
4419
            WHERE
4420
                insert_user_id = $userId AND
4421
                c_id = $courseId AND
4422
                tool = '$tool'
4423
                $session_condition ";
4424
4425
    $rs = Database::query($sql);
4426
    $list = [];
4427
    if (Database::num_rows($rs) > 0) {
4428
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
4429
            $list[] = $row;
4430
        }
4431
    }
4432
4433
    return $list;
4434
}
4435
4436
/**
4437
 * Gets item property id from tool of a course.
4438
 *
4439
 * @param string $course_code course code
4440
 * @param string $tool        tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
4441
 * @param int    $ref         id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
4442
 * @param int    $sessionId   Session ID (optional)
4443
 *
4444
 * @return int
4445
 */
4446
function api_get_item_property_id($course_code, $tool, $ref, $sessionId = 0)
4447
{
4448
    $course_info = api_get_course_info($course_code);
4449
    $tool = Database::escape_string($tool);
4450
    $ref = (int) $ref;
4451
4452
    // Definition of tables.
4453
    $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
4454
    $course_id = $course_info['real_id'];
4455
    $sessionId = (int) $sessionId;
4456
    $sessionCondition = " AND session_id = $sessionId ";
4457
    if (empty($sessionId)) {
4458
        $sessionCondition = ' AND (session_id = 0 OR session_id IS NULL) ';
4459
    }
4460
    $sql = "SELECT id FROM $tableItemProperty
4461
            WHERE
4462
                c_id = $course_id AND
4463
                tool = '$tool' AND
4464
                ref = $ref
4465
                $sessionCondition";
4466
    $rs = Database::query($sql);
4467
    $item_property_id = '';
4468
    if (Database::num_rows($rs) > 0) {
4469
        $row = Database::fetch_array($rs);
4470
        $item_property_id = $row['id'];
4471
    }
4472
4473
    return $item_property_id;
4474
}
4475
4476
/**
4477
 * Inserts a record in the track_e_item_property table (No update).
4478
 *
4479
 * @param string $tool
4480
 * @param int    $ref
4481
 * @param string $title
4482
 * @param string $content
4483
 * @param int    $progress
4484
 *
4485
 * @return bool|int
4486
 */
4487
function api_track_item_property_update($tool, $ref, $title, $content, $progress)
4488
{
4489
    $tbl_stats_item_property = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY);
4490
    $course_id = api_get_course_int_id(); //numeric
4491
    $course_code = api_get_course_id(); //alphanumeric
4492
    $item_property_id = api_get_item_property_id($course_code, $tool, $ref);
4493
    if (!empty($item_property_id)) {
4494
        $sql = "INSERT IGNORE INTO $tbl_stats_item_property SET
4495
                course_id           = '$course_id',
4496
                item_property_id    = '$item_property_id',
4497
                title               = '".Database::escape_string($title)."',
4498
                content             = '".Database::escape_string($content)."',
4499
                progress            = '".intval($progress)."',
4500
                lastedit_date       = '".api_get_utc_datetime()."',
4501
                lastedit_user_id    = '".api_get_user_id()."',
4502
                session_id          = '".api_get_session_id()."'";
4503
        $result = Database::query($sql);
4504
        $affected_rows = Database::affected_rows($result);
4505
4506
        return $affected_rows;
4507
    }
4508
4509
    return false;
4510
}
4511
4512
/**
4513
 * @param string $tool
4514
 * @param int    $ref
4515
 *
4516
 * @return array|resource
4517
 */
4518
function api_get_track_item_property_history($tool, $ref)
4519
{
4520
    $tbl_stats_item_property = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY);
4521
    $course_id = api_get_course_int_id(); //numeric
4522
    $course_code = api_get_course_id(); //alphanumeric
4523
    $item_property_id = api_get_item_property_id($course_code, $tool, $ref);
4524
    $sql = "SELECT * FROM $tbl_stats_item_property
4525
            WHERE item_property_id = $item_property_id AND course_id = $course_id
4526
            ORDER BY lastedit_date DESC";
4527
    $result = Database::query($sql);
4528
    if (false === $result or null === $result) {
4529
        $result = [];
4530
    } else {
4531
        $result = Database::store_result($result, 'ASSOC');
4532
    }
4533
4534
    return $result;
4535
}
4536
4537
/**
4538
 * Gets item property data from tool of a course id.
4539
 *
4540
 * @param int    $course_id
4541
 * @param string $tool       tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
4542
 * @param int    $ref        id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
4543
 * @param int    $session_id
4544
 * @param int    $groupId
4545
 *
4546
 * @return array with all fields from c_item_property, empty array if not found or false if course could not be found
4547
 */
4548
function api_get_item_property_info($course_id, $tool, $ref, $session_id = 0, $groupId = 0)
4549
{
4550
    $courseInfo = api_get_course_info_by_id($course_id);
4551
4552
    if (empty($courseInfo)) {
4553
        return false;
4554
    }
4555
4556
    $tool = Database::escape_string($tool);
4557
    $course_id = $courseInfo['real_id'];
4558
    $ref = (int) $ref;
4559
    $session_id = (int) $session_id;
4560
4561
    $sessionCondition = " session_id = $session_id";
4562
    if (empty($session_id)) {
4563
        $sessionCondition = ' (session_id = 0 OR session_id IS NULL) ';
4564
    }
4565
4566
    // Definition of tables.
4567
    $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
4568
4569
    $sql = "SELECT * FROM $table
4570
            WHERE
4571
                c_id = $course_id AND
4572
                tool = '$tool' AND
4573
                ref = $ref AND
4574
                $sessionCondition ";
4575
4576
    if (!empty($groupId)) {
4577
        $groupId = (int) $groupId;
4578
        $sql .= " AND to_group_id = $groupId ";
4579
    }
4580
4581
    $rs = Database::query($sql);
4582
    $row = [];
4583
    if (Database::num_rows($rs) > 0) {
4584
        $row = Database::fetch_array($rs, 'ASSOC');
4585
    }
4586
4587
    return $row;
4588
}
4589
4590
/**
4591
 * Displays a combo box so the user can select his/her preferred language.
4592
 *
4593
 * @param string The desired name= value for the select
4594
 * @param bool Whether we use the JQuery Chozen library or not
4595
 * (in some cases, like the indexing language picker, it can alter the presentation)
4596
 *
4597
 * @deprecated
4598
 *
4599
 * @return string
4600
 */
4601
function api_get_languages_combo($name = 'language')
4602
{
4603
    $ret = '';
4604
    $platformLanguage = api_get_setting('platformLanguage');
4605
4606
    // Retrieve a complete list of all the languages.
4607
    $language_list = api_get_languages();
4608
4609
    if (count($language_list) < 2) {
4610
        return $ret;
4611
    }
4612
4613
    // The the current language of the user so that his/her language occurs as selected in the dropdown menu.
4614
    if (isset($_SESSION['user_language_choice'])) {
4615
        $default = $_SESSION['user_language_choice'];
4616
    } else {
4617
        $default = $platformLanguage;
4618
    }
4619
4620
    $ret .= '<select name="'.$name.'" id="language_chosen" class="selectpicker show-tick form-control">';
4621
    foreach ($language_list as $key => $value) {
4622
        if ($key == $default) {
4623
            $selected = ' selected="selected"';
4624
        } else {
4625
            $selected = '';
4626
        }
4627
        $ret .= sprintf('<option value=%s" %s>%s</option>', $key, $selected, $value);
4628
    }
4629
    $ret .= '</select>';
4630
4631
    return $ret;
4632
}
4633
4634
/**
4635
 * Displays a form (drop down menu) so the user can select his/her preferred language.
4636
 * The form works with or without javascript.
4637
 *
4638
 * @param  bool Hide form if only one language available (defaults to false = show the box anyway)
4639
 * @param bool $showAsButton
4640
 *
4641
 * @return string|null Display the box directly
4642
 */
4643
function api_display_language_form($hide_if_no_choice = false, $showAsButton = false)
4644
{
4645
    // Retrieve a complete list of all the languages.
4646
    $language_list = api_get_languages();
4647
    if (count($language_list['name']) <= 1 && $hide_if_no_choice) {
4648
        return; //don't show any form
4649
    }
4650
4651
    // The the current language of the user so that his/her language occurs as selected in the dropdown menu.
4652
    if (isset($_SESSION['user_language_choice'])) {
4653
        $user_selected_language = $_SESSION['user_language_choice'];
4654
    }
4655
    if (empty($user_selected_language)) {
4656
        $user_selected_language = api_get_setting('platformLanguage');
4657
    }
4658
4659
    $currentLanguageId = api_get_language_id($user_selected_language);
4660
    $currentLanguageInfo = api_get_language_info($currentLanguageId);
4661
    $countryCode = languageToCountryIsoCode($currentLanguageInfo['isocode']);
4662
    $url = api_get_self();
4663
    if ($showAsButton) {
4664
        $html = '<div class="btn-group">
4665
              <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
4666
                <span class="flag-icon flag-icon-'.$countryCode.'"></span>
4667
                '.$currentLanguageInfo['original_name'].'
4668
                <span class="caret">
4669
                </span>
4670
              </button>';
4671
    } else {
4672
        $html = '
4673
            <a href="'.$url.'" class="dropdown-toggle" data-toggle="dropdown" role="button">
4674
                <span class="flag-icon flag-icon-'.$countryCode.'"></span>
4675
                '.$currentLanguageInfo['original_name'].'
4676
                <span class="caret"></span>
4677
            </a>
4678
            ';
4679
    }
4680
4681
    $html .= '<ul class="dropdown-menu" role="menu">';
4682
    foreach ($language_list['all'] as $key => $data) {
4683
        $urlLink = $url.'?language='.$data['english_name'];
4684
        $html .= '<li><a href="'.$urlLink.'"><span class="flag-icon flag-icon-'.languageToCountryIsoCode($data['isocode']).'"></span> '.$data['original_name'].'</a></li>';
4685
    }
4686
    $html .= '</ul>';
4687
4688
    if ($showAsButton) {
4689
        $html .= '</div>';
4690
    }
4691
4692
    return $html;
4693
}
4694
4695
/**
4696
 * @param string $languageIsoCode
4697
 *
4698
 * @return string
4699
 */
4700
function languageToCountryIsoCode($languageIsoCode)
4701
{
4702
    $allow = api_get_configuration_value('language_flags_by_country');
4703
4704
    // @todo save in DB
4705
    switch ($languageIsoCode) {
4706
        case 'ko':
4707
            $country = 'kr';
4708
            break;
4709
        case 'ja':
4710
            $country = 'jp';
4711
            break;
4712
        case 'ca':
4713
            $country = 'es';
4714
            if ($allow) {
4715
                $country = 'catalan';
4716
            }
4717
            break;
4718
        case 'gl': // galego
4719
            $country = 'es';
4720
            if ($allow) {
4721
                $country = 'galician';
4722
            }
4723
            break;
4724
        case 'ka':
4725
            $country = 'ge';
4726
            break;
4727
        case 'sl':
4728
            $country = 'si';
4729
            break;
4730
        case 'eu': // Euskera
4731
            $country = 'es';
4732
            if ($allow) {
4733
                $country = 'basque';
4734
            }
4735
            break;
4736
        case 'cs':
4737
            $country = 'cz';
4738
            break;
4739
        case 'el':
4740
            $country = 'ae';
4741
            break;
4742
        case 'ar':
4743
            $country = 'ae';
4744
            break;
4745
        case 'en_US':
4746
        case 'en':
4747
            $country = 'gb';
4748
            break;
4749
        case 'he':
4750
            $country = 'il';
4751
            break;
4752
        case 'uk': // Ukraine
4753
            $country = 'ua';
4754
            break;
4755
        case 'da':
4756
            $country = 'dk';
4757
            break;
4758
        case 'pt-BR':
4759
            $country = 'br';
4760
            break;
4761
        case 'qu':
4762
            $country = 'pe';
4763
            break;
4764
        case 'sv':
4765
            $country = 'se';
4766
            break;
4767
        case 'zh-TW':
4768
        case 'zh':
4769
            $country = 'cn';
4770
            break;
4771
        default:
4772
            $country = $languageIsoCode;
4773
            break;
4774
    }
4775
    $country = strtolower($country);
4776
4777
    return $country;
4778
}
4779
4780
/**
4781
 * Returns a list of all the languages that are made available by the admin.
4782
 *
4783
 * @return array An array with all languages. Structure of the array is
4784
 *               array['name'] = An array with the name of every language
4785
 *               array['folder'] = An array with the corresponding names of the language-folders in the filesystem
4786
 */
4787
function api_get_languages()
4788
{
4789
    $table = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4790
    $sql = "SELECT * FROM $table WHERE available='1'
4791
            ORDER BY original_name ASC";
4792
    $result = Database::query($sql);
4793
    $languages = [];
4794
    while ($row = Database::fetch_array($result, 'ASSOC')) {
4795
        $languages[$row['isocode']] = $row['original_name'];
4796
    }
4797
4798
    return $languages;
4799
}
4800
4801
/**
4802
 * Returns a list of all the languages that are made available by the admin.
4803
 *
4804
 * @return array
4805
 */
4806
function api_get_languages_to_array()
4807
{
4808
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4809
    $sql = "SELECT * FROM $tbl_language WHERE available='1' ORDER BY original_name ASC";
4810
    $result = Database::query($sql);
4811
    $languages = [];
4812
    while ($row = Database::fetch_array($result)) {
4813
        $languages[$row['dokeos_folder']] = $row['original_name'];
4814
    }
4815
4816
    return $languages;
4817
}
4818
4819
/**
4820
 * Returns the id (the database id) of a language.
4821
 *
4822
 * @param   string  language name (the corresponding name of the language-folder in the filesystem)
4823
 *
4824
 * @return int id of the language
4825
 */
4826
function api_get_language_id($language)
4827
{
4828
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4829
    if (empty($language)) {
4830
        return null;
4831
    }
4832
    $language = Database::escape_string($language);
4833
    $sql = "SELECT id FROM $tbl_language
4834
            WHERE dokeos_folder = '$language' LIMIT 1";
4835
    $result = Database::query($sql);
4836
    $row = Database::fetch_array($result);
4837
4838
    return $row['id'];
4839
}
4840
4841
/**
4842
 * Get the language information by its id.
4843
 *
4844
 * @param int $languageId
4845
 *
4846
 * @throws Exception
4847
 *
4848
 * @return array
4849
 */
4850
function api_get_language_info($languageId)
4851
{
4852
    if (empty($languageId)) {
4853
        return [];
4854
    }
4855
4856
    $language = Database::getManager()
4857
        ->find('ChamiloCoreBundle:Language', $languageId);
4858
4859
    if (!$language) {
4860
        return [];
4861
    }
4862
4863
    return [
4864
        'id' => $language->getId(),
4865
        'original_name' => $language->getOriginalName(),
4866
        'english_name' => $language->getEnglishName(),
4867
        'isocode' => $language->getIsocode(),
4868
        'dokeos_folder' => $language->getDokeosFolder(),
4869
        'available' => $language->getAvailable(),
4870
        'parent_id' => $language->getParent() ? $language->getParent()->getId() : null,
4871
    ];
4872
}
4873
4874
/**
4875
 * @param string $code
4876
 *
4877
 * @return \Chamilo\CoreBundle\Entity\Language
4878
 */
4879
function api_get_language_from_iso($code)
4880
{
4881
    $em = Database::getManager();
4882
4883
    return $em->getRepository('ChamiloCoreBundle:Language')->findOneBy(['isocode' => $code]);
4884
}
4885
4886
/**
4887
 * Returns the name of the visual (CSS) theme to be applied on the current page.
4888
 * The returned name depends on the platform, course or user -wide settings.
4889
 *
4890
 * @return string The visual theme's name, it is the name of a folder inside web/css/themes
4891
 */
4892
function api_get_visual_theme()
4893
{
4894
    static $visual_theme;
4895
    if (!isset($visual_theme)) {
4896
        // Get style directly from DB
4897
        /*$styleFromDatabase = api_get_settings_params_simple(
4898
            [
4899
                'variable = ? AND access_url = ?' => [
4900
                    'stylesheets',
4901
                    api_get_current_access_url_id(),
4902
                ],
4903
            ]
4904
        );
4905
4906
        if ($styleFromDatabase) {
4907
            $platform_theme = $styleFromDatabase['selected_value'];
4908
        } else {
4909
            $platform_theme = api_get_setting('stylesheets');
4910
        }*/
4911
        $platform_theme = api_get_setting('stylesheets');
4912
4913
        // Platform's theme.
4914
        $visual_theme = $platform_theme;
4915
        if ('true' == api_get_setting('user_selected_theme')) {
4916
            $user_info = api_get_user_info();
4917
            if (isset($user_info['theme'])) {
4918
                $user_theme = $user_info['theme'];
4919
4920
                if (!empty($user_theme)) {
4921
                    $visual_theme = $user_theme;
4922
                    // User's theme.
4923
                }
4924
            }
4925
        }
4926
4927
        $course_id = api_get_course_id();
4928
        if (!empty($course_id)) {
4929
            if ('true' == api_get_setting('allow_course_theme')) {
4930
                $course_theme = api_get_course_setting('course_theme', $course_id);
4931
4932
                if (!empty($course_theme) && -1 != $course_theme) {
4933
                    if (!empty($course_theme)) {
4934
                        // Course's theme.
4935
                        $visual_theme = $course_theme;
4936
                    }
4937
                }
4938
4939
                $allow_lp_theme = api_get_course_setting('allow_learning_path_theme');
4940
                if (1 == $allow_lp_theme) {
4941
                    global $lp_theme_css, $lp_theme_config;
4942
                    // These variables come from the file lp_controller.php.
4943
                    if (!$lp_theme_config) {
4944
                        if (!empty($lp_theme_css)) {
4945
                            // LP's theme.
4946
                            $visual_theme = $lp_theme_css;
4947
                        }
4948
                    }
4949
                }
4950
            }
4951
        }
4952
4953
        if (empty($visual_theme)) {
4954
            $visual_theme = 'chamilo';
4955
        }
4956
4957
        global $lp_theme_log;
4958
        if ($lp_theme_log) {
4959
            $visual_theme = $platform_theme;
4960
        }
4961
    }
4962
4963
    return $visual_theme;
4964
}
4965
4966
/**
4967
 * Returns a list of CSS themes currently available in the CSS folder
4968
 * The folder must have a default.css file.
4969
 *
4970
 * @param bool $getOnlyThemeFromVirtualInstance Used by the vchamilo plugin
4971
 *
4972
 * @return array list of themes directories from the css folder
4973
 *               Note: Directory names (names of themes) in the file system should contain ASCII-characters only
4974
 */
4975
function api_get_themes($getOnlyThemeFromVirtualInstance = false)
4976
{
4977
    // This configuration value is set by the vchamilo plugin
4978
    $virtualTheme = api_get_configuration_value('virtual_css_theme_folder');
4979
4980
    $readCssFolder = function ($dir) use ($virtualTheme) {
4981
        $finder = new Finder();
4982
        $themes = $finder->directories()->in($dir)->depth(0)->sortByName();
4983
        $list = [];
4984
        /** @var Symfony\Component\Finder\SplFileInfo $theme */
4985
        foreach ($themes as $theme) {
4986
            $folder = $theme->getFilename();
4987
            // A theme folder is consider if there's a default.css file
4988
            if (!file_exists($theme->getPathname().'/default.css')) {
4989
                continue;
4990
            }
4991
            $name = ucwords(str_replace('_', ' ', $folder));
4992
            if ($folder == $virtualTheme) {
4993
                continue;
4994
            }
4995
            $list[$folder] = $name;
4996
        }
4997
4998
        return $list;
4999
    };
5000
5001
    $dir = api_get_path(SYS_CSS_PATH).'themes/';
5002
    $list = $readCssFolder($dir);
5003
5004
    if (!empty($virtualTheme)) {
5005
        $newList = $readCssFolder($dir.'/'.$virtualTheme);
5006
        if ($getOnlyThemeFromVirtualInstance) {
5007
            return $newList;
5008
        }
5009
        $list = $list + $newList;
5010
        asort($list);
5011
    }
5012
5013
    return $list;
5014
}
5015
5016
/**
5017
 * Find the largest sort value in a given user_course_category
5018
 * This function is used when we are moving a course to a different category
5019
 * and also when a user subscribes to courses (the new course is added at the end of the main category.
5020
 *
5021
 * @author Patrick Cool <[email protected]>, Ghent University
5022
 *
5023
 * @param int $user_course_category the id of the user_course_category
5024
 * @param int $user_id
5025
 *
5026
 * @return int the value of the highest sort of the user_course_category
5027
 */
5028
function api_max_sort_value($user_course_category, $user_id)
5029
{
5030
    $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5031
    $sql = "SELECT max(sort) as max_sort FROM $tbl_course_user
5032
            WHERE
5033
                user_id='".intval($user_id)."' AND
5034
                relation_type<>".COURSE_RELATION_TYPE_RRHH." AND
5035
                user_course_cat='".intval($user_course_category)."'";
5036
    $result_max = Database::query($sql);
5037
    if (1 == Database::num_rows($result_max)) {
5038
        $row_max = Database::fetch_array($result_max);
5039
5040
        return $row_max['max_sort'];
5041
    }
5042
5043
    return 0;
5044
}
5045
5046
/**
5047
 * Transforms a number of seconds in hh:mm:ss format.
5048
 *
5049
 * @author Julian Prud'homme
5050
 *
5051
 * @param int    $seconds      number of seconds
5052
 * @param string $space
5053
 * @param bool   $showSeconds
5054
 * @param bool   $roundMinutes
5055
 *
5056
 * @return string the formatted time
5057
 */
5058
function api_time_to_hms($seconds, $space = ':', $showSeconds = true, $roundMinutes = false)
5059
{
5060
    // $seconds = -1 means that we have wrong data in the db.
5061
    if (-1 == $seconds) {
5062
        return
5063
            get_lang('Unknown').
5064
            Display::return_icon(
5065
                'info2.gif',
5066
                get_lang('The datas about this user were registered when the calculation of time spent on the platform wasn\'t possible.'),
5067
                ['align' => 'absmiddle', 'hspace' => '3px']
5068
            );
5069
    }
5070
5071
    // How many hours ?
5072
    $hours = floor($seconds / 3600);
5073
5074
    // How many minutes ?
5075
    $min = floor(($seconds - ($hours * 3600)) / 60);
5076
5077
    if ($roundMinutes) {
5078
        if ($min >= 45) {
5079
            $min = 45;
5080
        }
5081
5082
        if ($min >= 30 && $min <= 44) {
5083
            $min = 30;
5084
        }
5085
5086
        if ($min >= 15 && $min <= 29) {
5087
            $min = 15;
5088
        }
5089
5090
        if ($min >= 0 && $min <= 14) {
5091
            $min = 0;
5092
        }
5093
    }
5094
5095
    // How many seconds
5096
    $sec = floor($seconds - ($hours * 3600) - ($min * 60));
5097
5098
    if ($hours < 10) {
5099
        $hours = "0$hours";
5100
    }
5101
5102
    if ($sec < 10) {
5103
        $sec = "0$sec";
5104
    }
5105
5106
    if ($min < 10) {
5107
        $min = "0$min";
5108
    }
5109
5110
    $seconds = '';
5111
    if ($showSeconds) {
5112
        $seconds = $space.$sec;
5113
    }
5114
5115
    return $hours.$space.$min.$seconds;
5116
}
5117
5118
/* FILE SYSTEM RELATED FUNCTIONS */
5119
5120
/**
5121
 * Returns the permissions to be assigned to every newly created directory by the web-server.
5122
 * The return value is based on the platform administrator's setting
5123
 * "Administration > Configuration settings > Security > Permissions for new directories".
5124
 *
5125
 * @return int returns the permissions in the format "Owner-Group-Others, Read-Write-Execute", as an integer value
5126
 */
5127
function api_get_permissions_for_new_directories()
5128
{
5129
    static $permissions;
5130
    if (!isset($permissions)) {
5131
        $permissions = trim(api_get_setting('permissions_for_new_directories'));
5132
        // The default value 0777 is according to that in the platform administration panel after fresh system installation.
5133
        $permissions = octdec(!empty($permissions) ? $permissions : '0777');
5134
    }
5135
5136
    return $permissions;
5137
}
5138
5139
/**
5140
 * Returns the permissions to be assigned to every newly created directory by the web-server.
5141
 * The return value is based on the platform administrator's setting
5142
 * "Administration > Configuration settings > Security > Permissions for new files".
5143
 *
5144
 * @return int returns the permissions in the format
5145
 *             "Owner-Group-Others, Read-Write-Execute", as an integer value
5146
 */
5147
function api_get_permissions_for_new_files()
5148
{
5149
    static $permissions;
5150
    if (!isset($permissions)) {
5151
        $permissions = trim(api_get_setting('permissions_for_new_files'));
5152
        // The default value 0666 is according to that in the platform
5153
        // administration panel after fresh system installation.
5154
        $permissions = octdec(!empty($permissions) ? $permissions : '0666');
5155
    }
5156
5157
    return $permissions;
5158
}
5159
5160
/**
5161
 * Deletes a file, or a folder and its contents.
5162
 *
5163
 * @author      Aidan Lister <[email protected]>
5164
 *
5165
 * @version     1.0.3
5166
 *
5167
 * @param string $dirname Directory to delete
5168
 * @param       bool     Deletes only the content or not
5169
 * @param bool $strict if one folder/file fails stop the loop
5170
 *
5171
 * @return bool Returns TRUE on success, FALSE on failure
5172
 *
5173
 * @see http://aidanlister.com/2004/04/recursively-deleting-a-folder-in-php/
5174
 *
5175
 * @author      Yannick Warnier, adaptation for the Chamilo LMS, April, 2008
5176
 * @author      Ivan Tcholakov, a sanity check about Directory class creation has been added, September, 2009
5177
 */
5178
function rmdirr($dirname, $delete_only_content_in_folder = false, $strict = false)
5179
{
5180
    $res = true;
5181
    // A sanity check.
5182
    if (!file_exists($dirname)) {
5183
        return false;
5184
    }
5185
    $php_errormsg = '';
5186
    // Simple delete for a file.
5187
    if (is_file($dirname) || is_link($dirname)) {
5188
        $res = unlink($dirname);
5189
        if (false === $res) {
5190
            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);
5191
        }
5192
5193
        return $res;
5194
    }
5195
5196
    // Loop through the folder.
5197
    $dir = dir($dirname);
5198
    // A sanity check.
5199
    $is_object_dir = is_object($dir);
5200
    if ($is_object_dir) {
5201
        while (false !== $entry = $dir->read()) {
5202
            // Skip pointers.
5203
            if ('.' == $entry || '..' == $entry) {
5204
                continue;
5205
            }
5206
5207
            // Recurse.
5208
            if ($strict) {
5209
                $result = rmdirr("$dirname/$entry");
5210
                if (false == $result) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
5211
                    $res = false;
5212
                    break;
5213
                }
5214
            } else {
5215
                rmdirr("$dirname/$entry");
5216
            }
5217
        }
5218
    }
5219
5220
    // Clean up.
5221
    if ($is_object_dir) {
5222
        $dir->close();
5223
    }
5224
5225
    if (false == $delete_only_content_in_folder) {
5226
        $res = rmdir($dirname);
5227
        if (false === $res) {
5228
            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);
5229
        }
5230
    }
5231
5232
    return $res;
5233
}
5234
5235
// TODO: This function is to be simplified. File access modes to be implemented.
5236
/**
5237
 * function adapted from a php.net comment
5238
 * copy recursively a folder.
5239
 *
5240
 * @param the source folder
5241
 * @param the dest folder
5242
 * @param an array of excluded file_name (without extension)
5243
 * @param copied_files the returned array of copied files
5244
 * @param string $source
5245
 * @param string $dest
5246
 */
5247
function copyr($source, $dest, $exclude = [], $copied_files = [])
5248
{
5249
    if (empty($dest)) {
5250
        return false;
5251
    }
5252
    // Simple copy for a file
5253
    if (is_file($source)) {
5254
        $path_info = pathinfo($source);
5255
        if (!in_array($path_info['filename'], $exclude)) {
5256
            copy($source, $dest);
5257
        }
5258
5259
        return true;
5260
    } elseif (!is_dir($source)) {
5261
        //then source is not a dir nor a file, return
5262
        return false;
5263
    }
5264
5265
    // Make destination directory.
5266
    if (!is_dir($dest)) {
5267
        mkdir($dest, api_get_permissions_for_new_directories());
5268
    }
5269
5270
    // Loop through the folder.
5271
    $dir = dir($source);
5272
    while (false !== $entry = $dir->read()) {
5273
        // Skip pointers
5274
        if ('.' == $entry || '..' == $entry) {
5275
            continue;
5276
        }
5277
5278
        // Deep copy directories.
5279
        if ($dest !== "$source/$entry") {
5280
            $files = copyr("$source/$entry", "$dest/$entry", $exclude, $copied_files);
5281
        }
5282
    }
5283
    // Clean up.
5284
    $dir->close();
5285
5286
    return true;
5287
}
5288
5289
/**
5290
 * @todo: Using DIRECTORY_SEPARATOR is not recommended, this is an obsolete approach.
5291
 * Documentation header to be added here.
5292
 *
5293
 * @param string $pathname
5294
 * @param string $base_path_document
5295
 * @param int    $session_id
5296
 *
5297
 * @return mixed True if directory already exists, false if a file already exists at
5298
 *               the destination and null if everything goes according to plan
5299
 */
5300
function copy_folder_course_session(
5301
    $pathname,
5302
    $base_path_document,
5303
    $session_id,
5304
    $course_info,
5305
    $document,
5306
    $source_course_id
5307
) {
5308
    $table = Database::get_course_table(TABLE_DOCUMENT);
5309
    $session_id = intval($session_id);
5310
    $source_course_id = intval($source_course_id);
5311
5312
    // Check whether directory already exists.
5313
    if (is_dir($pathname) || empty($pathname)) {
5314
        return true;
5315
    }
5316
5317
    // Ensure that a file with the same name does not already exist.
5318
    if (is_file($pathname)) {
5319
        trigger_error('copy_folder_course_session(): File exists', E_USER_WARNING);
5320
5321
        return false;
5322
    }
5323
5324
    $course_id = $course_info['real_id'];
5325
    $folders = explode(DIRECTORY_SEPARATOR, str_replace($base_path_document.DIRECTORY_SEPARATOR, '', $pathname));
5326
    $new_pathname = $base_path_document;
5327
    $path = '';
5328
5329
    foreach ($folders as $folder) {
5330
        $new_pathname .= DIRECTORY_SEPARATOR.$folder;
5331
        $path .= DIRECTORY_SEPARATOR.$folder;
5332
5333
        if (!file_exists($new_pathname)) {
5334
            $path = Database::escape_string($path);
5335
5336
            $sql = "SELECT * FROM $table
5337
                    WHERE
5338
                        c_id = $source_course_id AND
5339
                        path = '$path' AND
5340
                        filetype = 'folder' AND
5341
                        session_id = '$session_id'";
5342
            $rs1 = Database::query($sql);
5343
            $num_rows = Database::num_rows($rs1);
5344
5345
            if (0 == $num_rows) {
5346
                mkdir($new_pathname, api_get_permissions_for_new_directories());
5347
5348
                // Insert new folder with destination session_id.
5349
                $params = [
5350
                    'c_id' => $course_id,
5351
                    'path' => $path,
5352
                    'comment' => $document->comment,
5353
                    'title' => basename($new_pathname),
5354
                    'filetype' => 'folder',
5355
                    'size' => '0',
5356
                    'session_id' => $session_id,
5357
                ];
5358
                $document_id = Database::insert($table, $params);
5359
                if ($document_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $document_id of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
5360
                    $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
5361
                    Database::query($sql);
5362
5363
                    api_item_property_update(
5364
                        $course_info,
5365
                        TOOL_DOCUMENT,
5366
                        $document_id,
5367
                        'FolderCreated',
5368
                        api_get_user_id(),
5369
                        0,
5370
                        0,
5371
                        null,
5372
                        null,
5373
                        $session_id
5374
                    );
5375
                }
5376
            }
5377
        }
5378
    } // en foreach
5379
}
5380
5381
// TODO: chmodr() is a better name. Some corrections are needed. Documentation header to be added here.
5382
/**
5383
 * @param string $path
5384
 */
5385
function api_chmod_R($path, $filemode)
5386
{
5387
    if (!is_dir($path)) {
5388
        return chmod($path, $filemode);
5389
    }
5390
5391
    $handler = opendir($path);
5392
    while ($file = readdir($handler)) {
5393
        if ('.' != $file && '..' != $file) {
5394
            $fullpath = "$path/$file";
5395
            if (!is_dir($fullpath)) {
5396
                if (!chmod($fullpath, $filemode)) {
5397
                    return false;
5398
                }
5399
            } else {
5400
                if (!api_chmod_R($fullpath, $filemode)) {
5401
                    return false;
5402
                }
5403
            }
5404
        }
5405
    }
5406
5407
    closedir($handler);
5408
5409
    return chmod($path, $filemode);
5410
}
5411
5412
// TODO: Where the following function has been copy/pased from? There is no information about author and license. Style, coding conventions...
5413
/**
5414
 * Parse info file format. (e.g: file.info).
5415
 *
5416
 * Files should use an ini-like format to specify values.
5417
 * White-space generally doesn't matter, except inside values.
5418
 * e.g.
5419
 *
5420
 * @verbatim
5421
 *   key = value
5422
 *   key = "value"
5423
 *   key = 'value'
5424
 *   key = "multi-line
5425
 *
5426
 *   value"
5427
 *   key = 'multi-line
5428
 *
5429
 *   value'
5430
 *   key
5431
 *   =
5432
 *   'value'
5433
 * @endverbatim
5434
 *
5435
 * Arrays are created using a GET-like syntax:
5436
 *
5437
 * @verbatim
5438
 *   key[] = "numeric array"
5439
 *   key[index] = "associative array"
5440
 *   key[index][] = "nested numeric array"
5441
 *   key[index][index] = "nested associative array"
5442
 * @endverbatim
5443
 *
5444
 * PHP constants are substituted in, but only when used as the entire value:
5445
 *
5446
 * Comments should start with a semi-colon at the beginning of a line.
5447
 *
5448
 * This function is NOT for placing arbitrary module-specific settings. Use
5449
 * variable_get() and variable_set() for that.
5450
 *
5451
 * Information stored in the module.info file:
5452
 * - name: The real name of the module for display purposes.
5453
 * - description: A brief description of the module.
5454
 * - dependencies: An array of shortnames of other modules this module depends on.
5455
 * - package: The name of the package of modules this module belongs to.
5456
 *
5457
 * Example of .info file:
5458
 * <code>
5459
 * @verbatim
5460
 *   name = Forum
5461
 *   description = Enables threaded discussions about general topics.
5462
 *   dependencies[] = taxonomy
5463
 *   dependencies[] = comment
5464
 *   package = Core - optional
5465
 *   version = VERSION
5466
 * @endverbatim
5467
 * </code>
5468
 *
5469
 * @param string $filename
5470
 *                         The file we are parsing. Accepts file with relative or absolute path.
5471
 *
5472
 * @return
5473
 *   The info array
5474
 */
5475
function api_parse_info_file($filename)
5476
{
5477
    $info = [];
5478
5479
    if (!file_exists($filename)) {
5480
        return $info;
5481
    }
5482
5483
    $data = file_get_contents($filename);
5484
    if (preg_match_all('
5485
        @^\s*                           # Start at the beginning of a line, ignoring leading whitespace
5486
        ((?:
5487
          [^=;\[\]]|                    # Key names cannot contain equal signs, semi-colons or square brackets,
5488
          \[[^\[\]]*\]                  # unless they are balanced and not nested
5489
        )+?)
5490
        \s*=\s*                         # Key/value pairs are separated by equal signs (ignoring white-space)
5491
        (?:
5492
          ("(?:[^"]|(?<=\\\\)")*")|     # Double-quoted string, which may contain slash-escaped quotes/slashes
5493
          (\'(?:[^\']|(?<=\\\\)\')*\')| # Single-quoted string, which may contain slash-escaped quotes/slashes
5494
          ([^\r\n]*?)                   # Non-quoted string
5495
        )\s*$                           # Stop at the next end of a line, ignoring trailing whitespace
5496
        @msx', $data, $matches, PREG_SET_ORDER)) {
5497
        $key = $value1 = $value2 = $value3 = '';
5498
        foreach ($matches as $match) {
5499
            // Fetch the key and value string.
5500
            $i = 0;
5501
            foreach (['key', 'value1', 'value2', 'value3'] as $var) {
5502
                $$var = isset($match[++$i]) ? $match[$i] : '';
5503
            }
5504
            $value = stripslashes(substr($value1, 1, -1)).stripslashes(substr($value2, 1, -1)).$value3;
5505
5506
            // Parse array syntax.
5507
            $keys = preg_split('/\]?\[/', rtrim($key, ']'));
5508
            $last = array_pop($keys);
5509
            $parent = &$info;
5510
5511
            // Create nested arrays.
5512
            foreach ($keys as $key) {
5513
                if ('' == $key) {
5514
                    $key = count($parent);
5515
                }
5516
                if (!isset($parent[$key]) || !is_array($parent[$key])) {
5517
                    $parent[$key] = [];
5518
                }
5519
                $parent = &$parent[$key];
5520
            }
5521
5522
            // Handle PHP constants.
5523
            if (defined($value)) {
5524
                $value = constant($value);
5525
            }
5526
5527
            // Insert actual value.
5528
            if ('' == $last) {
5529
                $last = count($parent);
5530
            }
5531
            $parent[$last] = $value;
5532
        }
5533
    }
5534
5535
    return $info;
5536
}
5537
5538
/**
5539
 * Gets Chamilo version from the configuration files.
5540
 *
5541
 * @return string A string of type "1.8.4", or an empty string if the version could not be found
5542
 */
5543
function api_get_version()
5544
{
5545
    return (string) api_get_configuration_value('system_version');
5546
}
5547
5548
/**
5549
 * Gets the software name (the name/brand of the Chamilo-based customized system).
5550
 *
5551
 * @return string
5552
 */
5553
function api_get_software_name()
5554
{
5555
    $name = api_get_configuration_value('software_name');
5556
    if (!empty($name)) {
5557
        return $name;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $name also could return the type boolean which is incompatible with the documented return type string.
Loading history...
5558
    } else {
5559
        return 'Chamilo';
5560
    }
5561
}
5562
5563
function api_get_status_list()
5564
{
5565
    $list = [];
5566
    // Table of status
5567
    $list[COURSEMANAGER] = 'teacher'; // 1
5568
    $list[SESSIONADMIN] = 'session_admin'; // 3
5569
    $list[DRH] = 'drh'; // 4
5570
    $list[STUDENT] = 'user'; // 5
5571
    $list[ANONYMOUS] = 'anonymous'; // 6
5572
    $list[INVITEE] = 'invited'; // 20
5573
5574
    return $list;
5575
}
5576
5577
/**
5578
 * Checks whether status given in parameter exists in the platform.
5579
 *
5580
 * @param mixed the status (can be either int either string)
5581
 *
5582
 * @return bool if the status exists, else returns false
5583
 */
5584
function api_status_exists($status_asked)
5585
{
5586
    $list = api_get_status_list();
5587
5588
    return in_array($status_asked, $list) ? true : isset($list[$status_asked]);
5589
}
5590
5591
/**
5592
 * Checks whether status given in parameter exists in the platform. The function
5593
 * returns the status ID or false if it does not exist, but given the fact there
5594
 * is no "0" status, the return value can be checked against
5595
 * if(api_status_key()) to know if it exists.
5596
 *
5597
 * @param   mixed   The status (can be either int or string)
5598
 *
5599
 * @return mixed Status ID if exists, false otherwise
5600
 */
5601
function api_status_key($status)
5602
{
5603
    $list = api_get_status_list();
5604
5605
    return isset($list[$status]) ? $status : array_search($status, $list);
5606
}
5607
5608
/**
5609
 * Gets the status langvars list.
5610
 *
5611
 * @return string[] the list of status with their translations
5612
 */
5613
function api_get_status_langvars()
5614
{
5615
    return [
5616
        COURSEMANAGER => get_lang('Teacher'),
5617
        SESSIONADMIN => get_lang('SessionsAdmin'),
5618
        DRH => get_lang('Human Resources Manager'),
5619
        STUDENT => get_lang('Learner'),
5620
        ANONYMOUS => get_lang('Anonymous'),
5621
        STUDENT_BOSS => get_lang('RoleStudentBoss'),
5622
        INVITEE => get_lang('Invited'),
5623
    ];
5624
}
5625
5626
/**
5627
 * The function that retrieves all the possible settings for a certain config setting.
5628
 *
5629
 * @author Patrick Cool <[email protected]>, Ghent University
5630
 */
5631
function api_get_settings_options($var)
5632
{
5633
    $table_settings_options = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
5634
    $var = Database::escape_string($var);
5635
    $sql = "SELECT * FROM $table_settings_options
5636
            WHERE variable = '$var'
5637
            ORDER BY id";
5638
    $result = Database::query($sql);
5639
    $settings_options_array = [];
5640
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5641
        $settings_options_array[] = $row;
5642
    }
5643
5644
    return $settings_options_array;
5645
}
5646
5647
/**
5648
 * @param array $params
5649
 */
5650
function api_set_setting_option($params)
5651
{
5652
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
5653
    if (empty($params['id'])) {
5654
        Database::insert($table, $params);
5655
    } else {
5656
        Database::update($table, $params, ['id = ? ' => $params['id']]);
5657
    }
5658
}
5659
5660
/**
5661
 * @param array $params
5662
 */
5663
function api_set_setting_simple($params)
5664
{
5665
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5666
    $url_id = api_get_current_access_url_id();
5667
5668
    if (empty($params['id'])) {
5669
        $params['access_url'] = $url_id;
5670
        Database::insert($table, $params);
5671
    } else {
5672
        Database::update($table, $params, ['id = ? ' => [$params['id']]]);
5673
    }
5674
}
5675
5676
/**
5677
 * @param int $id
5678
 */
5679
function api_delete_setting_option($id)
5680
{
5681
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
5682
    if (!empty($id)) {
5683
        Database::delete($table, ['id = ? ' => $id]);
5684
    }
5685
}
5686
5687
/**
5688
 * Sets a platform configuration setting to a given value.
5689
 *
5690
 * @param string    The variable we want to update
5691
 * @param string    The value we want to record
5692
 * @param string    The sub-variable if any (in most cases, this will remain null)
5693
 * @param string    The category if any (in most cases, this will remain null)
5694
 * @param int       The access_url for which this parameter is valid
5695
 * @param string $cat
5696
 *
5697
 * @return bool|null
5698
 */
5699
function api_set_setting($var, $value, $subvar = null, $cat = null, $access_url = 1)
5700
{
5701
    if (empty($var)) {
5702
        return false;
5703
    }
5704
    $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5705
    $var = Database::escape_string($var);
5706
    $value = Database::escape_string($value);
5707
    $access_url = (int) $access_url;
5708
    if (empty($access_url)) {
5709
        $access_url = 1;
5710
    }
5711
    $select = "SELECT id FROM $t_settings WHERE variable = '$var' ";
5712
    if (!empty($subvar)) {
5713
        $subvar = Database::escape_string($subvar);
5714
        $select .= " AND subkey = '$subvar'";
5715
    }
5716
    if (!empty($cat)) {
5717
        $cat = Database::escape_string($cat);
5718
        $select .= " AND category = '$cat'";
5719
    }
5720
    if ($access_url > 1) {
5721
        $select .= " AND access_url = $access_url";
5722
    } else {
5723
        $select .= " AND access_url = 1 ";
5724
    }
5725
5726
    $res = Database::query($select);
5727
    if (Database::num_rows($res) > 0) {
5728
        // Found item for this access_url.
5729
        $row = Database::fetch_array($res);
5730
        $sql = "UPDATE $t_settings SET selected_value = '$value'
5731
                WHERE id = ".$row['id'];
5732
        Database::query($sql);
5733
    } else {
5734
        // Item not found for this access_url, we have to check if it exist with access_url = 1
5735
        $select = "SELECT * FROM $t_settings
5736
                   WHERE variable = '$var' AND access_url = 1 ";
5737
        // Just in case
5738
        if (1 == $access_url) {
5739
            if (!empty($subvar)) {
5740
                $select .= " AND subkey = '$subvar'";
5741
            }
5742
            if (!empty($cat)) {
5743
                $select .= " AND category = '$cat'";
5744
            }
5745
            $res = Database::query($select);
5746
            if (Database::num_rows($res) > 0) {
5747
                // We have a setting for access_url 1, but none for the current one, so create one.
5748
                $row = Database::fetch_array($res);
5749
                $insert = "INSERT INTO $t_settings (variable, subkey, type,category, selected_value, title, comment, scope, subkeytext, access_url)
5750
                        VALUES
5751
                        ('".$row['variable']."',".(!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL").",".
5752
                    "'".$row['type']."','".$row['category']."',".
5753
                    "'$value','".$row['title']."',".
5754
                    "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".(!empty($row['scope']) ? "'".$row['scope']."'" : "NULL").",".
5755
                    "".(!empty($row['subkeytext']) ? "'".$row['subkeytext']."'" : "NULL").",$access_url)";
5756
                Database::query($insert);
5757
            } else {
5758
                // Such a setting does not exist.
5759
                //error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all', 0);
5760
            }
5761
        } else {
5762
            // Other access url.
5763
            if (!empty($subvar)) {
5764
                $select .= " AND subkey = '$subvar'";
5765
            }
5766
            if (!empty($cat)) {
5767
                $select .= " AND category = '$cat'";
5768
            }
5769
            $res = Database::query($select);
5770
5771
            if (Database::num_rows($res) > 0) {
5772
                // We have a setting for access_url 1, but none for the current one, so create one.
5773
                $row = Database::fetch_array($res);
5774
                if (1 == $row['access_url_changeable']) {
5775
                    $insert = "INSERT INTO $t_settings (variable,subkey, type,category, selected_value,title, comment,scope, subkeytext,access_url, access_url_changeable) VALUES
5776
                            ('".$row['variable']."',".
5777
                        (!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL").",".
5778
                        "'".$row['type']."','".$row['category']."',".
5779
                        "'$value','".$row['title']."',".
5780
                        "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".
5781
                        (!empty($row['scope']) ? "'".$row['scope']."'" : "NULL").",".
5782
                        "".(!empty($row['subkeytext']) ? "'".$row['subkeytext']."'" : "NULL").",$access_url,".$row['access_url_changeable'].")";
5783
                    Database::query($insert);
5784
                }
5785
            } else { // Such a setting does not exist.
5786
                //error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all. The access_url is: '.$access_url.' ',0);
5787
            }
5788
        }
5789
    }
5790
}
5791
5792
/**
5793
 * Sets a whole category of settings to one specific value.
5794
 *
5795
 * @param string    Category
5796
 * @param string    Value
5797
 * @param int       Access URL. Optional. Defaults to 1
5798
 * @param array     Optional array of filters on field type
5799
 * @param string $category
5800
 * @param string $value
5801
 *
5802
 * @return bool
5803
 */
5804
function api_set_settings_category($category, $value = null, $access_url = 1, $fieldtype = [])
5805
{
5806
    if (empty($category)) {
5807
        return false;
5808
    }
5809
    $category = Database::escape_string($category);
5810
    $t_s = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5811
    $access_url = (int) $access_url;
5812
    if (empty($access_url)) {
5813
        $access_url = 1;
5814
    }
5815
    if (isset($value)) {
5816
        $value = Database::escape_string($value);
5817
        $sql = "UPDATE $t_s SET selected_value = '$value'
5818
                WHERE category = '$category' AND access_url = $access_url";
5819
        if (is_array($fieldtype) && count($fieldtype) > 0) {
5820
            $sql .= " AND ( ";
5821
            $i = 0;
5822
            foreach ($fieldtype as $type) {
5823
                if ($i > 0) {
5824
                    $sql .= ' OR ';
5825
                }
5826
                $type = Database::escape_string($type);
5827
                $sql .= " type='".$type."' ";
5828
                $i++;
5829
            }
5830
            $sql .= ")";
5831
        }
5832
        $res = Database::query($sql);
5833
5834
        return false !== $res;
5835
    } else {
5836
        $sql = "UPDATE $t_s SET selected_value = NULL
5837
                WHERE category = '$category' AND access_url = $access_url";
5838
        if (is_array($fieldtype) && count($fieldtype) > 0) {
5839
            $sql .= " AND ( ";
5840
            $i = 0;
5841
            foreach ($fieldtype as $type) {
5842
                if ($i > 0) {
5843
                    $sql .= ' OR ';
5844
                }
5845
                $type = Database::escape_string($type);
5846
                $sql .= " type='".$type."' ";
5847
                $i++;
5848
            }
5849
            $sql .= ")";
5850
        }
5851
        $res = Database::query($sql);
5852
5853
        return false !== $res;
5854
    }
5855
}
5856
5857
/**
5858
 * Gets all available access urls in an array (as in the database).
5859
 *
5860
 * @return array An array of database records
5861
 */
5862
function api_get_access_urls($from = 0, $to = 1000000, $order = 'url', $direction = 'ASC')
5863
{
5864
    $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5865
    $from = (int) $from;
5866
    $to = (int) $to;
5867
    $order = Database::escape_string($order, null, false);
5868
    $direction = Database::escape_string($direction, null, false);
5869
    $sql = "SELECT id, url, description, active, created_by, tms
5870
            FROM $table
5871
            ORDER BY $order $direction
5872
            LIMIT $to OFFSET $from";
5873
    $res = Database::query($sql);
5874
5875
    return Database::store_result($res);
5876
}
5877
5878
/**
5879
 * Gets the access url info in an array.
5880
 *
5881
 * @param int  $id            Id of the access url
5882
 * @param bool $returnDefault Set to false if you want the real URL if URL 1 is still 'http://localhost/'
5883
 *
5884
 * @return array All the info (url, description, active, created_by, tms)
5885
 *               from the access_url table
5886
 *
5887
 * @author Julio Montoya
5888
 */
5889
function api_get_access_url($id, $returnDefault = true)
5890
{
5891
    static $staticResult;
5892
    $id = (int) $id;
5893
5894
    if (isset($staticResult[$id])) {
5895
        $result = $staticResult[$id];
5896
    } else {
5897
        // Calling the Database:: library dont work this is handmade.
5898
        $table_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5899
        $sql = "SELECT url, description, active, created_by, tms
5900
                FROM $table_access_url WHERE id = '$id' ";
5901
        $res = Database::query($sql);
5902
        $result = @Database::fetch_array($res);
5903
        $staticResult[$id] = $result;
5904
    }
5905
5906
    // If the result url is 'http://localhost/' (the default) and the root_web
5907
    // (=current url) is different, and the $id is = 1 (which might mean
5908
    // api_get_current_access_url_id() returned 1 by default), then return the
5909
    // root_web setting instead of the current URL
5910
    // This is provided as an option to avoid breaking the storage of URL-specific
5911
    // homepages in home/localhost/
5912
    if (1 === $id && false === $returnDefault) {
5913
        $currentUrl = api_get_current_access_url_id();
5914
        // only do this if we are on the main URL (=1), otherwise we could get
5915
        // information on another URL instead of the one asked as parameter
5916
        if (1 === $currentUrl) {
5917
            $rootWeb = api_get_path(WEB_PATH);
5918
            $default = 'http://localhost/';
5919
            if ($result['url'] === $default && $rootWeb != $default) {
5920
                $result['url'] = $rootWeb;
5921
            }
5922
        }
5923
    }
5924
5925
    return $result;
5926
}
5927
5928
/**
5929
 * Gets all the current settings for a specific access url.
5930
 *
5931
 * @param string    The category, if any, that we want to get
5932
 * @param string    Whether we want a simple list (display a category) or
5933
 * a grouped list (group by variable as in settings.php default). Values: 'list' or 'group'
5934
 * @param int       Access URL's ID. Optional. Uses 1 by default, which is the unique URL
5935
 *
5936
 * @return array Array of database results for the current settings of the current access URL
5937
 */
5938
function &api_get_settings($cat = null, $ordering = 'list', $access_url = 1, $url_changeable = 0)
5939
{
5940
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5941
    $access_url = (int) $access_url;
5942
    $where_condition = '';
5943
    if (1 == $url_changeable) {
5944
        $where_condition = " AND access_url_changeable= '1' ";
5945
    }
5946
    if (empty($access_url) || -1 == $access_url) {
5947
        $access_url = 1;
5948
    }
5949
    $sql = "SELECT * FROM $table
5950
            WHERE access_url = $access_url  $where_condition ";
5951
5952
    if (!empty($cat)) {
5953
        $cat = Database::escape_string($cat);
5954
        $sql .= " AND category='$cat' ";
5955
    }
5956
    if ('group' == $ordering) {
5957
        $sql .= " ORDER BY id ASC";
5958
    } else {
5959
        $sql .= " ORDER BY 1,2 ASC";
5960
    }
5961
    $result = Database::query($sql);
5962
    if (null === $result) {
5963
        return [];
5964
    }
5965
    $result = Database::store_result($result, 'ASSOC');
5966
5967
    return $result;
5968
}
5969
5970
/**
5971
 * @param string $value       The value we want to record
5972
 * @param string $variable    The variable name we want to insert
5973
 * @param string $subKey      The subkey for the variable we want to insert
5974
 * @param string $type        The type for the variable we want to insert
5975
 * @param string $category    The category for the variable we want to insert
5976
 * @param string $title       The title
5977
 * @param string $comment     The comment
5978
 * @param string $scope       The scope
5979
 * @param string $subKeyText  The subkey text
5980
 * @param int    $accessUrlId The access_url for which this parameter is valid
5981
 * @param int    $visibility  The changeability of this setting for non-master urls
5982
 *
5983
 * @return int The setting ID
5984
 */
5985
function api_add_setting(
5986
    $value,
5987
    $variable,
5988
    $subKey = '',
5989
    $type = 'textfield',
5990
    $category = '',
5991
    $title = '',
5992
    $comment = '',
5993
    $scope = '',
5994
    $subKeyText = '',
5995
    $accessUrlId = 1,
5996
    $visibility = 0
5997
) {
5998
    $em = Database::getManager();
5999
    $settingRepo = $em->getRepository('ChamiloCoreBundle:SettingsCurrent');
6000
    $accessUrlId = (int) $accessUrlId ?: 1;
6001
6002
    if (is_array($value)) {
6003
        $value = serialize($value);
6004
    } else {
6005
        $value = trim($value);
6006
    }
6007
6008
    $criteria = ['variable' => $variable, 'url' => $accessUrlId];
6009
6010
    if (!empty($subKey)) {
6011
        $criteria['subkey'] = $subKey;
6012
    }
6013
6014
    // Check if this variable doesn't exist already
6015
    /** @var SettingsCurrent $setting */
6016
    $setting = $settingRepo->findOneBy($criteria);
6017
6018
    if ($setting) {
0 ignored issues
show
introduced by
$setting is of type Chamilo\CoreBundle\Entity\SettingsCurrent, thus it always evaluated to true.
Loading history...
6019
        $setting->setSelectedValue($value);
6020
6021
        $em->persist($setting);
6022
        $em->flush();
6023
6024
        return $setting->getId();
6025
    }
6026
6027
    // Item not found for this access_url, we have to check if the whole thing is missing
6028
    // (in which case we ignore the insert) or if there *is* a record but just for access_url = 1
6029
    $setting = new SettingsCurrent();
6030
    $url = api_get_url_entity();
6031
6032
    $setting
6033
        ->setVariable($variable)
6034
        ->setSelectedValue($value)
6035
        ->setType($type)
6036
        ->setCategory($category)
6037
        ->setSubkey($subKey)
6038
        ->setTitle($title)
6039
        ->setComment($comment)
6040
        ->setScope($scope)
6041
        ->setSubkeytext($subKeyText)
6042
        ->setUrl(api_get_url_entity())
6043
        ->setAccessUrlChangeable($visibility);
6044
6045
    $em->persist($setting);
6046
    $em->flush();
6047
6048
    return $setting->getId();
6049
}
6050
6051
/**
6052
 * Checks wether a user can or can't view the contents of a course.
6053
 *
6054
 * @deprecated use CourseManager::is_user_subscribed_in_course
6055
 *
6056
 * @param int $userid User id or NULL to get it from $_SESSION
6057
 * @param int $cid    course id to check whether the user is allowed
6058
 *
6059
 * @return bool
6060
 */
6061
function api_is_course_visible_for_user($userid = null, $cid = null)
6062
{
6063
    if (null === $userid) {
6064
        $userid = api_get_user_id();
6065
    }
6066
    if (empty($userid) || strval(intval($userid)) != $userid) {
6067
        if (api_is_anonymous()) {
6068
            $userid = api_get_anonymous_id();
6069
        } else {
6070
            return false;
6071
        }
6072
    }
6073
    $cid = Database::escape_string($cid);
6074
6075
    $courseInfo = api_get_course_info($cid);
6076
    $courseId = $courseInfo['real_id'];
6077
    $is_platformAdmin = api_is_platform_admin();
6078
6079
    $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
6080
    $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
6081
6082
    $sql = "SELECT
6083
                $course_cat_table.code AS category_code,
6084
                $course_table.visibility,
6085
                $course_table.code,
6086
                $course_cat_table.code
6087
            FROM $course_table
6088
            LEFT JOIN $course_cat_table
6089
                ON $course_table.category_id = $course_cat_table.id
6090
            WHERE
6091
                $course_table.code = '$cid'
6092
            LIMIT 1";
6093
6094
    $result = Database::query($sql);
6095
6096
    if (Database::num_rows($result) > 0) {
6097
        $visibility = Database::fetch_array($result);
6098
        $visibility = $visibility['visibility'];
6099
    } else {
6100
        $visibility = 0;
6101
    }
6102
    // Shortcut permissions in case the visibility is "open to the world".
6103
    if (COURSE_VISIBILITY_OPEN_WORLD === $visibility) {
6104
        return true;
6105
    }
6106
6107
    $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
6108
6109
    $sql = "SELECT
6110
                is_tutor, status
6111
            FROM $tbl_course_user
6112
            WHERE
6113
                user_id  = '$userid' AND
6114
                relation_type <> '".COURSE_RELATION_TYPE_RRHH."' AND
6115
                c_id = $courseId
6116
            LIMIT 1";
6117
6118
    $result = Database::query($sql);
6119
6120
    if (Database::num_rows($result) > 0) {
6121
        // This user has got a recorded state for this course.
6122
        $cuData = Database::fetch_array($result);
6123
        $is_courseMember = true;
6124
        $is_courseAdmin = (1 == $cuData['status']);
6125
    }
6126
6127
    if (!$is_courseAdmin) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $is_courseAdmin does not seem to be defined for all execution paths leading up to this point.
Loading history...
6128
        // This user has no status related to this course.
6129
        // Is it the session coach or the session admin?
6130
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
6131
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
6132
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
6133
6134
        $sql = "SELECT
6135
                    session.id_coach, session_admin_id, session.id
6136
                FROM
6137
                    $tbl_session as session
6138
                INNER JOIN $tbl_session_course
6139
                    ON session_rel_course.session_id = session.id
6140
                    AND session_rel_course.c_id = '$courseId'
6141
                LIMIT 1";
6142
6143
        $result = Database::query($sql);
6144
        $row = Database::store_result($result);
6145
6146
        if ($row[0]['id_coach'] == $userid) {
6147
            $is_courseMember = true;
6148
            $is_courseAdmin = false;
6149
        } elseif ($row[0]['session_admin_id'] == $userid) {
6150
            $is_courseMember = false;
6151
            $is_courseAdmin = false;
6152
        } else {
6153
            // Check if the current user is the course coach.
6154
            $sql = "SELECT 1
6155
                    FROM $tbl_session_course
6156
                    WHERE session_rel_course.c_id = '$courseId'
6157
                    AND session_rel_course.id_coach = '$userid'
6158
                    LIMIT 1";
6159
6160
            $result = Database::query($sql);
6161
6162
            //if ($row = Database::fetch_array($result)) {
6163
            if (Database::num_rows($result) > 0) {
6164
                $is_courseMember = true;
6165
                $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
6166
6167
                $sql = "SELECT status FROM $tbl_user
6168
                        WHERE user_id = $userid
6169
                        LIMIT 1";
6170
6171
                $result = Database::query($sql);
6172
6173
                if (1 == Database::result($result, 0, 0)) {
6174
                    $is_courseAdmin = true;
6175
                } else {
6176
                    $is_courseAdmin = false;
6177
                }
6178
            } else {
6179
                // Check if the user is a student is this session.
6180
                $sql = "SELECT  id
6181
                        FROM $tbl_session_course_user
6182
                        WHERE
6183
                            user_id  = '$userid' AND
6184
                            c_id = '$courseId'
6185
                        LIMIT 1";
6186
6187
                if (Database::num_rows($result) > 0) {
6188
                    // This user haa got a recorded state for this course.
6189
                    while ($row = Database::fetch_array($result)) {
6190
                        $is_courseMember = true;
6191
                        $is_courseAdmin = false;
6192
                    }
6193
                }
6194
            }
6195
        }
6196
    }
6197
6198
    switch ($visibility) {
6199
        case COURSE_VISIBILITY_OPEN_WORLD:
6200
            return true;
6201
        case COURSE_VISIBILITY_OPEN_PLATFORM:
6202
            return isset($userid);
6203
        case COURSE_VISIBILITY_REGISTERED:
6204
        case COURSE_VISIBILITY_CLOSED:
6205
            return $is_platformAdmin || $is_courseMember || $is_courseAdmin;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $is_courseMember does not seem to be defined for all execution paths leading up to this point.
Loading history...
6206
        case COURSE_VISIBILITY_HIDDEN:
6207
            return $is_platformAdmin;
6208
    }
6209
6210
    return false;
6211
}
6212
6213
/**
6214
 * Returns whether an element (forum, message, survey ...) belongs to a session or not.
6215
 *
6216
 * @param string the tool of the element
6217
 * @param int the element id in database
6218
 * @param int the session_id to compare with element session id
6219
 *
6220
 * @return bool true if the element is in the session, false else
6221
 */
6222
function api_is_element_in_the_session($tool, $element_id, $session_id = null)
6223
{
6224
    if (is_null($session_id)) {
6225
        $session_id = api_get_session_id();
6226
    }
6227
6228
    $element_id = (int) $element_id;
6229
6230
    if (empty($element_id)) {
6231
        return false;
6232
    }
6233
6234
    // Get information to build query depending of the tool.
6235
    switch ($tool) {
6236
        case TOOL_SURVEY:
6237
            $table_tool = Database::get_course_table(TABLE_SURVEY);
6238
            $key_field = 'survey_id';
6239
            break;
6240
        case TOOL_ANNOUNCEMENT:
6241
            $table_tool = Database::get_course_table(TABLE_ANNOUNCEMENT);
6242
            $key_field = 'id';
6243
            break;
6244
        case TOOL_AGENDA:
6245
            $table_tool = Database::get_course_table(TABLE_AGENDA);
6246
            $key_field = 'id';
6247
            break;
6248
        case TOOL_GROUP:
6249
            $table_tool = Database::get_course_table(TABLE_GROUP);
6250
            $key_field = 'id';
6251
            break;
6252
        default:
6253
            return false;
6254
    }
6255
    $course_id = api_get_course_int_id();
6256
6257
    $sql = "SELECT session_id FROM $table_tool
6258
            WHERE c_id = $course_id AND $key_field =  ".$element_id;
6259
    $rs = Database::query($sql);
6260
    if ($element_session_id = Database::result($rs, 0, 0)) {
6261
        if ($element_session_id == intval($session_id)) {
6262
            // The element belongs to the session.
6263
            return true;
6264
        }
6265
    }
6266
6267
    return false;
6268
}
6269
6270
/**
6271
 * Replaces "forbidden" characters in a filename string.
6272
 *
6273
 * @param string $filename
6274
 * @param bool   $treat_spaces_as_hyphens
6275
 *
6276
 * @return string
6277
 */
6278
function api_replace_dangerous_char($filename, $treat_spaces_as_hyphens = true)
6279
{
6280
    // Some non-properly encoded file names can cause the whole file to be
6281
    // skipped when uploaded. Avoid this by detecting the encoding and
6282
    // converting to UTF-8, setting the source as ASCII (a reasonably
6283
    // limited characters set) if nothing could be found (BT#
6284
    $encoding = api_detect_encoding($filename);
6285
    if (empty($encoding)) {
6286
        $encoding = 'ASCII';
6287
        if (!api_is_valid_ascii($filename)) {
6288
            // try iconv and try non standard ASCII a.k.a CP437
6289
            // see BT#15022
6290
            if (function_exists('iconv')) {
6291
                $result = iconv('CP437', 'UTF-8', $filename);
6292
                if (api_is_valid_utf8($result)) {
6293
                    $filename = $result;
6294
                    $encoding = 'UTF-8';
6295
                }
6296
            }
6297
        }
6298
    }
6299
6300
    $filename = api_to_system_encoding($filename, $encoding);
6301
6302
    $url = URLify::filter(
6303
        $filename,
6304
        250,
6305
        '',
6306
        true,
6307
        false,
6308
        false,
6309
        false
6310
    );
6311
6312
    return $url;
6313
}
6314
6315
/**
6316
 * Fixes the $_SERVER['REQUEST_URI'] that is empty in IIS6.
6317
 *
6318
 * @author Ivan Tcholakov, 28-JUN-2006.
6319
 */
6320
function api_request_uri()
6321
{
6322
    if (!empty($_SERVER['REQUEST_URI'])) {
6323
        return $_SERVER['REQUEST_URI'];
6324
    }
6325
    $uri = $_SERVER['SCRIPT_NAME'];
6326
    if (!empty($_SERVER['QUERY_STRING'])) {
6327
        $uri .= '?'.$_SERVER['QUERY_STRING'];
6328
    }
6329
    $_SERVER['REQUEST_URI'] = $uri;
6330
6331
    return $uri;
6332
}
6333
6334
/** Gets the current access_url id of the Chamilo Platform.
6335
 * @author Julio Montoya <[email protected]>
6336
 *
6337
 * @return int access_url_id of the current Chamilo Installation
6338
 */
6339
function api_get_current_access_url_id()
6340
{
6341
    if (false === api_get_multiple_access_url()) {
6342
        return 1;
6343
    }
6344
6345
    static $id;
6346
    if (!empty($id)) {
6347
        return $id;
6348
    }
6349
6350
    $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
6351
    $path = Database::escape_string(api_get_path(WEB_PATH));
6352
    $sql = "SELECT id FROM $table WHERE url = '".$path."'";
6353
    $result = Database::query($sql);
6354
    if (Database::num_rows($result) > 0) {
6355
        $id = Database::result($result, 0, 0);
6356
        if (false === $id) {
6357
            return -1;
6358
        }
6359
6360
        return (int) $id;
6361
    }
6362
6363
    $id = 1;
6364
6365
    //if the url in WEB_PATH was not found, it can only mean that there is
6366
    // either a configuration problem or the first URL has not been defined yet
6367
    // (by default it is http://localhost/). Thus the more sensible thing we can
6368
    // do is return 1 (the main URL) as the user cannot hack this value anyway
6369
    return 1;
6370
}
6371
6372
/**
6373
 * Gets the registered urls from a given user id.
6374
 *
6375
 * @author Julio Montoya <[email protected]>
6376
 *
6377
 * @param int $user_id
6378
 *
6379
 * @return array
6380
 */
6381
function api_get_access_url_from_user($user_id)
6382
{
6383
    $user_id = (int) $user_id;
6384
    $table_url_rel_user = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
6385
    $table_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
6386
    $sql = "SELECT access_url_id
6387
            FROM $table_url_rel_user url_rel_user
6388
            INNER JOIN $table_url u
6389
            ON (url_rel_user.access_url_id = u.id)
6390
            WHERE user_id = ".$user_id;
6391
    $result = Database::query($sql);
6392
    $list = [];
6393
    while ($row = Database::fetch_array($result, 'ASSOC')) {
6394
        $list[] = $row['access_url_id'];
6395
    }
6396
6397
    return $list;
6398
}
6399
6400
/**
6401
 * Checks whether the curent user is in a group or not.
6402
 *
6403
 * @param string        The group id - optional (takes it from session if not given)
6404
 * @param string        The course code - optional (no additional check by course if course code is not given)
6405
 *
6406
 * @return bool
6407
 *
6408
 * @author Ivan Tcholakov
6409
 */
6410
function api_is_in_group($groupIdParam = null, $courseCodeParam = null)
6411
{
6412
    if (!empty($courseCodeParam)) {
6413
        $courseCode = api_get_course_id();
6414
        if (!empty($courseCode)) {
6415
            if ($courseCodeParam != $courseCode) {
6416
                return false;
6417
            }
6418
        } else {
6419
            return false;
6420
        }
6421
    }
6422
6423
    $groupId = api_get_group_id();
6424
6425
    if (isset($groupId) && '' != $groupId) {
6426
        if (!empty($groupIdParam)) {
6427
            return $groupIdParam == $groupId;
6428
        } else {
6429
            return true;
6430
        }
6431
    }
6432
6433
    return false;
6434
}
6435
6436
/**
6437
 * Checks whether a secret key is valid.
6438
 *
6439
 * @param string $original_key_secret - secret key from (webservice) client
6440
 * @param string $security_key        - security key from Chamilo
6441
 *
6442
 * @return bool - true if secret key is valid, false otherwise
6443
 */
6444
function api_is_valid_secret_key($original_key_secret, $security_key)
6445
{
6446
    return $original_key_secret == sha1($security_key);
6447
}
6448
6449
/**
6450
 * Checks whether a user is into course.
6451
 *
6452
 * @param int $course_id - the course id
6453
 * @param int $user_id   - the user id
6454
 *
6455
 * @return bool
6456
 */
6457
function api_is_user_of_course($course_id, $user_id)
6458
{
6459
    $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
6460
    $sql = 'SELECT user_id FROM '.$tbl_course_rel_user.'
6461
            WHERE
6462
                c_id ="'.intval($course_id).'" AND
6463
                user_id = "'.intval($user_id).'" AND
6464
                relation_type <> '.COURSE_RELATION_TYPE_RRHH.' ';
6465
    $result = Database::query($sql);
6466
6467
    return 1 == Database::num_rows($result);
6468
}
6469
6470
/**
6471
 * Checks whether the server's operating system is Windows (TM).
6472
 *
6473
 * @return bool - true if the operating system is Windows, false otherwise
6474
 */
6475
function api_is_windows_os()
6476
{
6477
    if (function_exists('php_uname')) {
6478
        // php_uname() exists as of PHP 4.0.2, according to the documentation.
6479
        // We expect that this function will always work for Chamilo 1.8.x.
6480
        $os = php_uname();
6481
    }
6482
    // The following methods are not needed, but let them stay, just in case.
6483
    elseif (isset($_ENV['OS'])) {
6484
        // Sometimes $_ENV['OS'] may not be present (bugs?)
6485
        $os = $_ENV['OS'];
6486
    } elseif (defined('PHP_OS')) {
6487
        // PHP_OS means on which OS PHP was compiled, this is why
6488
        // using PHP_OS is the last choice for detection.
6489
        $os = PHP_OS;
6490
    } else {
6491
        return false;
6492
    }
6493
6494
    return 'win' == strtolower(substr((string) $os, 0, 3));
6495
}
6496
6497
/**
6498
 * This function informs whether the sent request is XMLHttpRequest.
6499
 */
6500
function api_is_xml_http_request()
6501
{
6502
    return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && 'xmlhttprequest' == strtolower($_SERVER['HTTP_X_REQUESTED_WITH']);
6503
}
6504
6505
/**
6506
 * This wrapper function has been implemented for avoiding some known problems about the function getimagesize().
6507
 *
6508
 * @see http://php.net/manual/en/function.getimagesize.php
6509
 * @see http://www.dokeos.com/forum/viewtopic.php?t=12345
6510
 * @see http://www.dokeos.com/forum/viewtopic.php?t=16355
6511
 *
6512
 * @return int
6513
 */
6514
function api_getimagesize($path)
6515
{
6516
    $image = new Image($path);
6517
6518
    return $image->get_image_size();
6519
}
6520
6521
/**
6522
 * This function resizes an image, with preserving its proportions (or aspect ratio).
6523
 *
6524
 * @author Ivan Tcholakov, MAY-2009.
6525
 *
6526
 * @param int $image         System path or URL of the image
6527
 * @param int $target_width  Targeted width
6528
 * @param int $target_height Targeted height
6529
 *
6530
 * @return array Calculated new width and height
6531
 */
6532
function api_resize_image($image, $target_width, $target_height)
6533
{
6534
    $image_properties = api_getimagesize($image);
6535
6536
    return api_calculate_image_size(
6537
        $image_properties['width'],
6538
        $image_properties['height'],
6539
        $target_width,
6540
        $target_height
6541
    );
6542
}
6543
6544
/**
6545
 * This function calculates new image size, with preserving image's proportions (or aspect ratio).
6546
 *
6547
 * @author Ivan Tcholakov, MAY-2009.
6548
 * @author The initial idea has been taken from code by Patrick Cool, MAY-2004.
6549
 *
6550
 * @param int $image_width   Initial width
6551
 * @param int $image_height  Initial height
6552
 * @param int $target_width  Targeted width
6553
 * @param int $target_height Targeted height
6554
 *
6555
 * @return array Calculated new width and height
6556
 */
6557
function api_calculate_image_size(
6558
    $image_width,
6559
    $image_height,
6560
    $target_width,
6561
    $target_height
6562
) {
6563
    // Only maths is here.
6564
    $result = ['width' => $image_width, 'height' => $image_height];
6565
    if ($image_width <= 0 || $image_height <= 0) {
6566
        return $result;
6567
    }
6568
    $resize_factor_width = $target_width / $image_width;
6569
    $resize_factor_height = $target_height / $image_height;
6570
    $delta_width = $target_width - $image_width * $resize_factor_height;
6571
    $delta_height = $target_height - $image_height * $resize_factor_width;
6572
    if ($delta_width > $delta_height) {
6573
        $result['width'] = ceil($image_width * $resize_factor_height);
6574
        $result['height'] = ceil($image_height * $resize_factor_height);
6575
    } elseif ($delta_width < $delta_height) {
6576
        $result['width'] = ceil($image_width * $resize_factor_width);
6577
        $result['height'] = ceil($image_height * $resize_factor_width);
6578
    } else {
6579
        $result['width'] = ceil($target_width);
6580
        $result['height'] = ceil($target_height);
6581
    }
6582
6583
    return $result;
6584
}
6585
6586
/**
6587
 * Returns a list of Chamilo's tools or
6588
 * checks whether a given identificator is a valid Chamilo's tool.
6589
 *
6590
 * @author Isaac flores paz
6591
 *
6592
 * @param string The tool name to filter
6593
 *
6594
 * @return mixed Filtered string or array
6595
 */
6596
function api_get_tools_lists($my_tool = null)
6597
{
6598
    $tools_list = [
6599
        TOOL_DOCUMENT,
6600
        TOOL_THUMBNAIL,
6601
        TOOL_HOTPOTATOES,
6602
        TOOL_CALENDAR_EVENT,
6603
        TOOL_LINK,
6604
        TOOL_COURSE_DESCRIPTION,
6605
        TOOL_SEARCH,
6606
        TOOL_LEARNPATH,
6607
        TOOL_ANNOUNCEMENT,
6608
        TOOL_FORUM,
6609
        TOOL_THREAD,
6610
        TOOL_POST,
6611
        TOOL_DROPBOX,
6612
        TOOL_QUIZ,
6613
        TOOL_USER,
6614
        TOOL_GROUP,
6615
        TOOL_BLOGS,
6616
        TOOL_CHAT,
6617
        TOOL_STUDENTPUBLICATION,
6618
        TOOL_TRACKING,
6619
        TOOL_HOMEPAGE_LINK,
6620
        TOOL_COURSE_SETTING,
6621
        TOOL_BACKUP,
6622
        TOOL_COPY_COURSE_CONTENT,
6623
        TOOL_RECYCLE_COURSE,
6624
        TOOL_COURSE_HOMEPAGE,
6625
        TOOL_COURSE_RIGHTS_OVERVIEW,
6626
        TOOL_UPLOAD,
6627
        TOOL_COURSE_MAINTENANCE,
6628
        TOOL_SURVEY,
6629
        TOOL_WIKI,
6630
        TOOL_GLOSSARY,
6631
        TOOL_GRADEBOOK,
6632
        TOOL_NOTEBOOK,
6633
        TOOL_ATTENDANCE,
6634
        TOOL_COURSE_PROGRESS,
6635
    ];
6636
    if (empty($my_tool)) {
6637
        return $tools_list;
6638
    }
6639
6640
    return in_array($my_tool, $tools_list) ? $my_tool : '';
6641
}
6642
6643
/**
6644
 * Checks whether we already approved the last version term and condition.
6645
 *
6646
 * @param int user id
6647
 *
6648
 * @return bool true if we pass false otherwise
6649
 */
6650
function api_check_term_condition($userId)
6651
{
6652
    if ('true' === api_get_setting('allow_terms_conditions')) {
6653
        // Check if exists terms and conditions
6654
        if (0 == LegalManager::count()) {
6655
            return true;
6656
        }
6657
6658
        $extraFieldValue = new ExtraFieldValue('user');
6659
        $data = $extraFieldValue->get_values_by_handler_and_field_variable(
6660
            $userId,
6661
            'legal_accept'
6662
        );
6663
6664
        if (!empty($data) && isset($data['value']) && !empty($data['value'])) {
6665
            $result = $data['value'];
6666
            $user_conditions = explode(':', $result);
6667
            $version = $user_conditions[0];
6668
            $langId = $user_conditions[1];
6669
            $realVersion = LegalManager::get_last_version($langId);
6670
6671
            return $version >= $realVersion;
6672
        }
6673
6674
        return false;
6675
    }
6676
6677
    return false;
6678
}
6679
6680
/**
6681
 * Gets all information of a tool into course.
6682
 *
6683
 * @param int The tool id
6684
 *
6685
 * @return array
6686
 */
6687
function api_get_tool_information_by_name($name)
6688
{
6689
    $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
6690
    $course_id = api_get_course_int_id();
6691
6692
    $sql = "SELECT id FROM tool
6693
            WHERE name = '".Database::escape_string($name)."' ";
6694
    $rs = Database::query($sql);
6695
    $data = Database::fetch_array($rs);
6696
    $tool = $data['id'];
6697
6698
    $sql = "SELECT * FROM $t_tool
6699
            WHERE c_id = $course_id  AND tool_id = '".$tool."' ";
6700
    $rs = Database::query($sql);
6701
6702
    return Database::fetch_array($rs, 'ASSOC');
6703
}
6704
6705
/**
6706
 * Function used to protect a "global" admin script.
6707
 * The function blocks access when the user has no global platform admin rights.
6708
 * Global admins are the admins that are registered in the main.admin table
6709
 * AND the users who have access to the "principal" portal.
6710
 * That means that there is a record in the main.access_url_rel_user table
6711
 * with his user id and the access_url_id=1.
6712
 *
6713
 * @author Julio Montoya
6714
 *
6715
 * @param int $user_id
6716
 *
6717
 * @return bool
6718
 */
6719
function api_is_global_platform_admin($user_id = null)
6720
{
6721
    $user_id = (int) $user_id;
6722
    if (empty($user_id)) {
6723
        $user_id = api_get_user_id();
6724
    }
6725
    if (api_is_platform_admin_by_id($user_id)) {
6726
        $urlList = api_get_access_url_from_user($user_id);
6727
        // The admin is registered in the first "main" site with access_url_id = 1
6728
        if (in_array(1, $urlList)) {
6729
            return true;
6730
        } else {
6731
            return false;
6732
        }
6733
    }
6734
6735
    return false;
6736
}
6737
6738
/**
6739
 * @param int  $admin_id_to_check
6740
 * @param int  $my_user_id
6741
 * @param bool $allow_session_admin
6742
 *
6743
 * @return bool
6744
 */
6745
function api_global_admin_can_edit_admin(
6746
    $admin_id_to_check,
6747
    $my_user_id = null,
6748
    $allow_session_admin = false
6749
) {
6750
    if (empty($my_user_id)) {
6751
        $my_user_id = api_get_user_id();
6752
    }
6753
6754
    $iam_a_global_admin = api_is_global_platform_admin($my_user_id);
6755
    $user_is_global_admin = api_is_global_platform_admin($admin_id_to_check);
6756
6757
    if ($iam_a_global_admin) {
6758
        // Global admin can edit everything
6759
        return true;
6760
    } else {
6761
        // If i'm a simple admin
6762
        $is_platform_admin = api_is_platform_admin_by_id($my_user_id);
6763
6764
        if ($allow_session_admin) {
6765
            $is_platform_admin = api_is_platform_admin_by_id($my_user_id) || (SESSIONADMIN == api_get_user_status($my_user_id));
6766
        }
6767
6768
        if ($is_platform_admin) {
6769
            if ($user_is_global_admin) {
6770
                return false;
6771
            } else {
6772
                return true;
6773
            }
6774
        } else {
6775
            return false;
6776
        }
6777
    }
6778
}
6779
6780
/**
6781
 * @param int  $admin_id_to_check
6782
 * @param int  $my_user_id
6783
 * @param bool $allow_session_admin
6784
 *
6785
 * @return bool|null
6786
 */
6787
function api_protect_super_admin($admin_id_to_check, $my_user_id = null, $allow_session_admin = false)
6788
{
6789
    if (api_global_admin_can_edit_admin($admin_id_to_check, $my_user_id, $allow_session_admin)) {
6790
        return true;
6791
    } else {
6792
        api_not_allowed();
6793
    }
6794
}
6795
6796
/**
6797
 * Function used to protect a global admin script.
6798
 * The function blocks access when the user has no global platform admin rights.
6799
 * See also the api_is_global_platform_admin() function wich defines who's a "global" admin.
6800
 *
6801
 * @author Julio Montoya
6802
 */
6803
function api_protect_global_admin_script()
6804
{
6805
    if (!api_is_global_platform_admin()) {
6806
        api_not_allowed();
6807
6808
        return false;
6809
    }
6810
6811
    return true;
6812
}
6813
6814
/**
6815
 * Check browser support for specific file types or features
6816
 * This function checks if the user's browser supports a file format or given
6817
 * feature, or returns the current browser and major version when
6818
 * $format=check_browser. Only a limited number of formats and features are
6819
 * checked by this method. Make sure you check its definition first.
6820
 *
6821
 * @param string $format Can be a file format (extension like svg, webm, ...) or a feature (like autocapitalize, ...)
6822
 *
6823
 * @deprecated
6824
 *
6825
 * @return bool or return text array if $format=check_browser
6826
 *
6827
 * @author Juan Carlos Raña Trabado
6828
 */
6829
function api_browser_support($format = '')
6830
{
6831
    return true;
6832
6833
    $browser = new Browser();
0 ignored issues
show
Unused Code introduced by
$browser = new Browser() is not 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...
6834
    $current_browser = $browser->getBrowser();
6835
    $a_versiontemp = explode('.', $browser->getVersion());
6836
    $current_majorver = $a_versiontemp[0];
6837
6838
    static $result;
6839
6840
    if (isset($result[$format])) {
6841
        return $result[$format];
6842
    }
6843
6844
    // Native svg support
6845
    if ('svg' == $format) {
6846
        if (('Internet Explorer' == $current_browser && $current_majorver >= 9) ||
6847
            ('Firefox' == $current_browser && $current_majorver > 1) ||
6848
            ('Safari' == $current_browser && $current_majorver >= 4) ||
6849
            ('Chrome' == $current_browser && $current_majorver >= 1) ||
6850
            ('Opera' == $current_browser && $current_majorver >= 9)
6851
        ) {
6852
            $result[$format] = true;
6853
6854
            return true;
6855
        } else {
6856
            $result[$format] = false;
6857
6858
            return false;
6859
        }
6860
    } elseif ('pdf' == $format) {
6861
        // native pdf support
6862
        if ('Chrome' == $current_browser && $current_majorver >= 6) {
6863
            $result[$format] = true;
6864
6865
            return true;
6866
        } else {
6867
            $result[$format] = false;
6868
6869
            return false;
6870
        }
6871
    } elseif ('tif' == $format || 'tiff' == $format) {
6872
        //native tif support
6873
        if ('Safari' == $current_browser && $current_majorver >= 5) {
6874
            $result[$format] = true;
6875
6876
            return true;
6877
        } else {
6878
            $result[$format] = false;
6879
6880
            return false;
6881
        }
6882
    } elseif ('ogg' == $format || 'ogx' == $format || 'ogv' == $format || 'oga' == $format) {
6883
        //native ogg, ogv,oga support
6884
        if (('Firefox' == $current_browser && $current_majorver >= 3) ||
6885
            ('Chrome' == $current_browser && $current_majorver >= 3) ||
6886
            ('Opera' == $current_browser && $current_majorver >= 9)) {
6887
            $result[$format] = true;
6888
6889
            return true;
6890
        } else {
6891
            $result[$format] = false;
6892
6893
            return false;
6894
        }
6895
    } elseif ('mpg' == $format || 'mpeg' == $format) {
6896
        //native mpg support
6897
        if (('Safari' == $current_browser && $current_majorver >= 5)) {
6898
            $result[$format] = true;
6899
6900
            return true;
6901
        } else {
6902
            $result[$format] = false;
6903
6904
            return false;
6905
        }
6906
    } elseif ('mp4' == $format) {
6907
        //native mp4 support (TODO: Android, iPhone)
6908
        if ('Android' == $current_browser || 'iPhone' == $current_browser) {
6909
            $result[$format] = true;
6910
6911
            return true;
6912
        } else {
6913
            $result[$format] = false;
6914
6915
            return false;
6916
        }
6917
    } elseif ('mov' == $format) {
6918
        //native mov support( TODO:check iPhone)
6919
        if ('Safari' == $current_browser && $current_majorver >= 5 || 'iPhone' == $current_browser) {
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: ('Safari' == $current_br...ne' == $current_browser, Probably Intended Meaning: 'Safari' == $current_bro...e' == $current_browser)
Loading history...
6920
            $result[$format] = true;
6921
6922
            return true;
6923
        } else {
6924
            $result[$format] = false;
6925
6926
            return false;
6927
        }
6928
    } elseif ('avi' == $format) {
6929
        //native avi support
6930
        if ('Safari' == $current_browser && $current_majorver >= 5) {
6931
            $result[$format] = true;
6932
6933
            return true;
6934
        } else {
6935
            $result[$format] = false;
6936
6937
            return false;
6938
        }
6939
    } elseif ('wmv' == $format) {
6940
        //native wmv support
6941
        if ('Firefox' == $current_browser && $current_majorver >= 4) {
6942
            $result[$format] = true;
6943
6944
            return true;
6945
        } else {
6946
            $result[$format] = false;
6947
6948
            return false;
6949
        }
6950
    } elseif ('webm' == $format) {
6951
        //native webm support (TODO:check IE9, Chrome9, Android)
6952
        if (('Firefox' == $current_browser && $current_majorver >= 4) ||
6953
            ('Opera' == $current_browser && $current_majorver >= 9) ||
6954
            ('Internet Explorer' == $current_browser && $current_majorver >= 9) ||
6955
            ('Chrome' == $current_browser && $current_majorver >= 9) ||
6956
            'Android' == $current_browser
6957
        ) {
6958
            $result[$format] = true;
6959
6960
            return true;
6961
        } else {
6962
            $result[$format] = false;
6963
6964
            return false;
6965
        }
6966
    } elseif ('wav' == $format) {
6967
        //native wav support (only some codecs !)
6968
        if (('Firefox' == $current_browser && $current_majorver >= 4) ||
6969
            ('Safari' == $current_browser && $current_majorver >= 5) ||
6970
            ('Opera' == $current_browser && $current_majorver >= 9) ||
6971
            ('Internet Explorer' == $current_browser && $current_majorver >= 9) ||
6972
            ('Chrome' == $current_browser && $current_majorver > 9) ||
6973
            'Android' == $current_browser ||
6974
            'iPhone' == $current_browser
6975
        ) {
6976
            $result[$format] = true;
6977
6978
            return true;
6979
        } else {
6980
            $result[$format] = false;
6981
6982
            return false;
6983
        }
6984
    } elseif ('mid' == $format || 'kar' == $format) {
6985
        //native midi support (TODO:check Android)
6986
        if ('Opera' == $current_browser && $current_majorver >= 9 || 'Android' == $current_browser) {
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: ('Opera' == $current_bro...id' == $current_browser, Probably Intended Meaning: 'Opera' == $current_brow...d' == $current_browser)
Loading history...
6987
            $result[$format] = true;
6988
6989
            return true;
6990
        } else {
6991
            $result[$format] = false;
6992
6993
            return false;
6994
        }
6995
    } elseif ('wma' == $format) {
6996
        //native wma support
6997
        if ('Firefox' == $current_browser && $current_majorver >= 4) {
6998
            $result[$format] = true;
6999
7000
            return true;
7001
        } else {
7002
            $result[$format] = false;
7003
7004
            return false;
7005
        }
7006
    } elseif ('au' == $format) {
7007
        //native au support
7008
        if ('Safari' == $current_browser && $current_majorver >= 5) {
7009
            $result[$format] = true;
7010
7011
            return true;
7012
        } else {
7013
            $result[$format] = false;
7014
7015
            return false;
7016
        }
7017
    } elseif ('mp3' == $format) {
7018
        //native mp3 support (TODO:check Android, iPhone)
7019
        if (('Safari' == $current_browser && $current_majorver >= 5) ||
7020
            ('Chrome' == $current_browser && $current_majorver >= 6) ||
7021
            ('Internet Explorer' == $current_browser && $current_majorver >= 9) ||
7022
            'Android' == $current_browser ||
7023
            'iPhone' == $current_browser ||
7024
            'Firefox' == $current_browser
7025
        ) {
7026
            $result[$format] = true;
7027
7028
            return true;
7029
        } else {
7030
            $result[$format] = false;
7031
7032
            return false;
7033
        }
7034
    } elseif ('autocapitalize' == $format) {
7035
        // Help avoiding showing the autocapitalize option if the browser doesn't
7036
        // support it: this attribute is against the HTML5 standard
7037
        if ('Safari' == $current_browser || 'iPhone' == $current_browser) {
7038
            return true;
7039
        } else {
7040
            return false;
7041
        }
7042
    } elseif ("check_browser" == $format) {
7043
        $array_check_browser = [$current_browser, $current_majorver];
7044
7045
        return $array_check_browser;
7046
    } else {
7047
        $result[$format] = false;
7048
7049
        return false;
7050
    }
7051
}
7052
7053
/**
7054
 * This function checks if exist path and file browscap.ini
7055
 * In order for this to work, your browscap configuration setting in php.ini
7056
 * must point to the correct location of the browscap.ini file on your system
7057
 * http://php.net/manual/en/function.get-browser.php.
7058
 *
7059
 * @return bool
7060
 *
7061
 * @author Juan Carlos Raña Trabado
7062
 */
7063
function api_check_browscap()
7064
{
7065
    $setting = ini_get('browscap');
7066
    if ($setting) {
7067
        $browser = get_browser($_SERVER['HTTP_USER_AGENT'], true);
7068
        if (strpos($setting, 'browscap.ini') && !empty($browser)) {
7069
            return true;
7070
        }
7071
    }
7072
7073
    return false;
7074
}
7075
7076
/**
7077
 * Returns the <script> HTML tag.
7078
 */
7079
function api_get_js($file)
7080
{
7081
    return '<script type="text/javascript" src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/'.$file.'"></script>'."\n";
7082
}
7083
7084
function api_get_build_js($file)
7085
{
7086
    return '<script type="text/javascript" src="'.api_get_path(WEB_PUBLIC_PATH).'build/'.$file.'"></script>'."\n";
7087
}
7088
7089
/**
7090
 * Returns the <script> HTML tag.
7091
 *
7092
 * @return string
7093
 */
7094
function api_get_asset($file)
7095
{
7096
    return '<script type="text/javascript" src="'.api_get_path(WEB_PUBLIC_PATH).'build/libs/'.$file.'"></script>'."\n";
7097
}
7098
7099
/**
7100
 * Returns the <script> HTML tag.
7101
 *
7102
 * @param string $file
7103
 * @param string $media
7104
 *
7105
 * @return string
7106
 */
7107
function api_get_css_asset($file, $media = 'screen')
7108
{
7109
    return '<link href="'.api_get_path(WEB_PUBLIC_PATH).'libs/'.$file.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
7110
}
7111
7112
/**
7113
 * Returns the <link> HTML tag.
7114
 *
7115
 * @param string $file
7116
 * @param string $media
7117
 */
7118
function api_get_css($file, $media = 'screen')
7119
{
7120
    return '<link href="'.$file.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
7121
}
7122
7123
function api_get_bootstrap_and_font_awesome($returnOnlyPath = false)
7124
{
7125
    $url = api_get_path(WEB_PUBLIC_PATH).'build/css/bootstrap.css';
7126
    if ($returnOnlyPath) {
7127
        return $url;
7128
    }
7129
7130
    return '<link href="'.$url.'" rel="stylesheet" type="text/css" />'."\n";
7131
}
7132
7133
/**
7134
 * Returns the js header to include the jquery library.
7135
 */
7136
function api_get_jquery_js()
7137
{
7138
    return api_get_asset('jquery/jquery.min.js');
7139
}
7140
7141
/**
7142
 * Returns the jquery path.
7143
 *
7144
 * @return string
7145
 */
7146
function api_get_jquery_web_path()
7147
{
7148
    return api_get_path(WEB_PUBLIC_PATH).'assets/jquery/jquery.min.js';
7149
}
7150
7151
/**
7152
 * @return string
7153
 */
7154
function api_get_jquery_ui_js_web_path()
7155
{
7156
    return api_get_path(WEB_PUBLIC_PATH).'assets/jquery-ui/jquery-ui.min.js';
7157
}
7158
7159
/**
7160
 * @return string
7161
 */
7162
function api_get_jquery_ui_css_web_path()
7163
{
7164
    return api_get_path(WEB_PUBLIC_PATH).'assets/jquery-ui/themes/smoothness/jquery-ui.min.css';
7165
}
7166
7167
/**
7168
 * Returns the jquery-ui library js headers.
7169
 *
7170
 * @return string html tags
7171
 */
7172
function api_get_jquery_ui_js()
7173
{
7174
    $libraries = [];
7175
7176
    return api_get_jquery_libraries_js($libraries);
7177
}
7178
7179
function api_get_jqgrid_js()
7180
{
7181
    $routePublic = Container::getRouter()->generate('home');
7182
7183
    return api_get_css($routePublic.'build/free-jqgrid.css').PHP_EOL
7184
        .api_get_js_simple($routePublic.'build/free-jqgrid.js');
7185
}
7186
7187
/**
7188
 * Returns the jquery library js and css headers.
7189
 *
7190
 * @param   array   list of jquery libraries supported jquery-ui
7191
 * @param   bool    add the jquery library
7192
 *
7193
 * @return string html tags
7194
 */
7195
function api_get_jquery_libraries_js($libraries)
7196
{
7197
    $js = '';
7198
7199
    //Document multiple upload funcionality
7200
    if (in_array('jquery-uploadzs', $libraries)) {
7201
        $js .= api_get_asset('blueimp-load-image/js/load-image.all.min.js');
7202
        $js .= api_get_asset('blueimp-canvas-to-blob/js/canvas-to-blob.min.js');
7203
        $js .= api_get_asset('jquery-file-upload/js/jquery.iframe-transport.js');
7204
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload.js');
7205
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-process.js');
7206
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-image.js');
7207
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-audio.js');
7208
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-video.js');
7209
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-validate.js');
7210
7211
        $js .= api_get_css(api_get_path(WEB_PUBLIC_PATH).'assets/jquery-file-upload/css/jquery.fileupload.css');
7212
        $js .= api_get_css(api_get_path(WEB_PUBLIC_PATH).'assets/jquery-file-upload/css/jquery.fileupload-ui.css');
7213
    }
7214
7215
    // jquery datepicker
7216
    if (in_array('datepicker', $libraries)) {
7217
        $languaje = 'en-GB';
7218
        $platform_isocode = strtolower(api_get_language_isocode());
7219
7220
        $datapicker_langs = [
7221
            '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',
7222
        ];
7223
        if (in_array($platform_isocode, $datapicker_langs)) {
7224
            $languaje = $platform_isocode;
7225
        }
7226
7227
        $js .= api_get_js('jquery-ui/jquery-ui-i18n.min.js');
7228
        $script = '<script>
7229
        $(function(){
7230
            $.datepicker.setDefaults($.datepicker.regional["'.$languaje.'"]);
7231
            $.datepicker.regional["local"] = $.datepicker.regional["'.$languaje.'"];
7232
        });
7233
        </script>
7234
        ';
7235
        $js .= $script;
7236
    }
7237
7238
    return $js;
7239
}
7240
7241
/**
7242
 * Returns the URL to the course or session, removing the complexity of the URL
7243
 * building piece by piece.
7244
 *
7245
 * This function relies on api_get_course_info()
7246
 *
7247
 * @param string $courseCode The course code - optional (takes it from context if not given)
7248
 * @param int    $sessionId  The session ID  - optional (takes it from context if not given)
7249
 * @param int    $groupId    The group ID - optional (takes it from context if not given)
7250
 *
7251
 * @return string The URL to a course, a session, or empty string if nothing works e.g. https://localhost/courses/ABC/index.php?session_id=3&gidReq=1
7252
 *
7253
 * @author  Julio Montoya <[email protected]>
7254
 */
7255
function api_get_course_url($courseCode = null, $sessionId = null, $groupId = null)
7256
{
7257
    $courseDirectory = '';
7258
    $url = '';
7259
    // If courseCode not set, get context or []
7260
    if (empty($courseCode)) {
7261
        $courseInfo = api_get_course_info();
7262
    } else {
7263
        $courseInfo = api_get_course_info($courseCode);
7264
    }
7265
7266
    // If course defined, get directory, otherwise keep empty string
7267
    if (!empty($courseInfo['directory'])) {
7268
        $courseDirectory = $courseInfo['directory'];
7269
    }
7270
7271
    // If sessionId not set, get context or 0
7272
    if (empty($sessionId)) {
7273
        $sessionId = api_get_session_id();
7274
    }
7275
7276
    // If groupId not set, get context or 0
7277
    if (empty($groupId)) {
7278
        $groupId = api_get_group_id();
7279
    }
7280
7281
    // Build the URL
7282
    if (!empty($courseDirectory)) {
7283
        // directory not empty, so we do have a course
7284
        $url = api_get_path(WEB_COURSE_PATH).$courseDirectory.'/index.php?id_session='.$sessionId.'&gidReq='.$groupId;
7285
    } elseif (!empty($sessionId) &&
7286
        'true' !== api_get_setting('session.remove_session_url')
7287
    ) {
7288
        // if the course was unset and the session was set, send directly to the session
7289
        $url = api_get_path(WEB_CODE_PATH).'session/index.php?session_id='.$sessionId;
7290
    }
7291
7292
    // if not valid combination was found, return an empty string
7293
    return $url;
7294
}
7295
7296
/**
7297
 * Check if the current portal has the $_configuration['multiple_access_urls'] parameter on.
7298
 *
7299
 * @return bool true if multi site is enabled
7300
 */
7301
function api_get_multiple_access_url()
7302
{
7303
    global $_configuration;
7304
    if (isset($_configuration['multiple_access_urls']) && $_configuration['multiple_access_urls']) {
7305
        return true;
7306
    }
7307
7308
    return false;
7309
}
7310
7311
/**
7312
 * @return bool
7313
 */
7314
function api_is_multiple_url_enabled()
7315
{
7316
    return api_get_multiple_access_url();
7317
}
7318
7319
/**
7320
 * Returns a md5 unique id.
7321
 *
7322
 * @todo add more parameters
7323
 */
7324
function api_get_unique_id()
7325
{
7326
    $id = md5(time().uniqid().api_get_user_id().api_get_course_id().api_get_session_id());
7327
7328
    return $id;
7329
}
7330
7331
/**
7332
 * @param int Course id
7333
 * @param int tool id: TOOL_QUIZ, TOOL_FORUM, TOOL_STUDENTPUBLICATION, TOOL_LEARNPATH
7334
 * @param int the item id (tool id, exercise id, lp id)
7335
 *
7336
 * @return bool
7337
 */
7338
function api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code = null)
7339
{
7340
    if (api_is_platform_admin()) {
7341
        return false;
7342
    }
7343
    if ('true' == api_get_setting('gradebook_locking_enabled')) {
7344
        if (empty($course_code)) {
7345
            $course_code = api_get_course_id();
7346
        }
7347
        $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
7348
        $item_id = (int) $item_id;
7349
        $link_type = (int) $link_type;
7350
        $course_code = Database::escape_string($course_code);
7351
        $sql = "SELECT locked FROM $table
7352
                WHERE locked = 1 AND ref_id = $item_id AND type = $link_type AND course_code = '$course_code' ";
7353
        $result = Database::query($sql);
7354
        if (Database::num_rows($result)) {
7355
            return true;
7356
        }
7357
    }
7358
7359
    return false;
7360
}
7361
7362
/**
7363
 * Blocks a page if the item was added in a gradebook.
7364
 *
7365
 * @param int       exercise id, work id, thread id,
7366
 * @param int       LINK_EXERCISE, LINK_STUDENTPUBLICATION, LINK_LEARNPATH LINK_FORUM_THREAD, LINK_ATTENDANCE
7367
 * see gradebook/lib/be/linkfactory
7368
 * @param string    course code
7369
 *
7370
 * @return false|null
7371
 */
7372
function api_block_course_item_locked_by_gradebook($item_id, $link_type, $course_code = null)
7373
{
7374
    if (api_is_platform_admin()) {
7375
        return false;
7376
    }
7377
7378
    if (api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code)) {
7379
        $message = Display::return_message(get_lang('This option is not available because this activity is contained by an assessment, which is currently locked. To unlock the assessment, ask your platform administrator.'), 'warning');
7380
        api_not_allowed(true, $message);
7381
    }
7382
}
7383
7384
/**
7385
 * Checks the PHP version installed is enough to run Chamilo.
7386
 *
7387
 * @param string Include path (used to load the error page)
7388
 */
7389
function api_check_php_version()
7390
{
7391
    if (!function_exists('version_compare') ||
7392
        version_compare(phpversion(), REQUIRED_PHP_VERSION, '<')
7393
    ) {
7394
        throw new Exception('Wrong PHP version');
7395
    }
7396
}
7397
7398
/**
7399
 * Checks whether the Archive directory is present and writeable. If not,
7400
 * prints a warning message.
7401
 */
7402
function api_check_archive_dir()
7403
{
7404
    if (is_dir(api_get_path(SYS_ARCHIVE_PATH)) && !is_writable(api_get_path(SYS_ARCHIVE_PATH))) {
7405
        $message = Display::return_message(get_lang('The app/cache/ directory, used by this tool, is not writeable. Please contact your platform administrator.'), 'warning');
7406
        api_not_allowed(true, $message);
7407
    }
7408
}
7409
7410
/**
7411
 * Returns an array of global configuration settings which should be ignored
7412
 * when printing the configuration settings screens.
7413
 *
7414
 * @return array Array of strings, each identifying one of the excluded settings
7415
 */
7416
function api_get_locked_settings()
7417
{
7418
    return [
7419
        'permanently_remove_deleted_files',
7420
        'account_valid_duration',
7421
        'service_ppt2lp',
7422
        'wcag_anysurfer_public_pages',
7423
        'upload_extensions_list_type',
7424
        'upload_extensions_blacklist',
7425
        'upload_extensions_whitelist',
7426
        'upload_extensions_skip',
7427
        'upload_extensions_replace_by',
7428
        'hide_dltt_markup',
7429
        'split_users_upload_directory',
7430
        'permissions_for_new_directories',
7431
        'permissions_for_new_files',
7432
        'platform_charset',
7433
        'ldap_description',
7434
        'cas_activate',
7435
        'cas_server',
7436
        'cas_server_uri',
7437
        'cas_port',
7438
        'cas_protocol',
7439
        'cas_add_user_activate',
7440
        'update_user_info_cas_with_ldap',
7441
        'languagePriority1',
7442
        'languagePriority2',
7443
        'languagePriority3',
7444
        'languagePriority4',
7445
        'login_is_email',
7446
        'chamilo_database_version',
7447
    ];
7448
}
7449
7450
/**
7451
 * Checks if the user is corrently logged in. Returns the user ID if he is, or
7452
 * false if he isn't. If the user ID is given and is an integer, then the same
7453
 * ID is simply returned.
7454
 *
7455
 * @param  int User ID
7456
 *
7457
 * @return bool Integer User ID is logged in, or false otherwise
7458
 */
7459
function api_user_is_login($user_id = null)
7460
{
7461
    return Container::getAuthorizationChecker()->isGranted('IS_AUTHENTICATED_FULLY');
7462
}
7463
7464
/**
7465
 * Guess the real ip for register in the database, even in reverse proxy cases.
7466
 * To be recognized, the IP has to be found in either $_SERVER['REMOTE_ADDR'] or
7467
 * in $_SERVER['HTTP_X_FORWARDED_FOR'], which is in common use with rproxies.
7468
 * Note: the result of this function is not SQL-safe. Please escape it before
7469
 * inserting in a database.
7470
 *
7471
 * @return string the user's real ip (unsafe - escape it before inserting to db)
7472
 *
7473
 * @author Jorge Frisancho Jibaja <[email protected]>, USIL - Some changes to allow the use of real IP using reverse proxy
7474
 *
7475
 * @version CEV CHANGE 24APR2012
7476
 */
7477
function api_get_real_ip()
7478
{
7479
    $ip = trim($_SERVER['REMOTE_ADDR']);
7480
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
7481
        if (preg_match('/,/', $_SERVER['HTTP_X_FORWARDED_FOR'])) {
7482
            @list($ip1, $ip2) = @explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
7483
        } else {
7484
            $ip1 = $_SERVER['HTTP_X_FORWARDED_FOR'];
7485
        }
7486
        $ip = trim($ip1);
7487
    }
7488
7489
    return $ip;
7490
}
7491
7492
/**
7493
 * Checks whether an IP is included inside an IP range.
7494
 *
7495
 * @param string IP address
7496
 * @param string IP range
7497
 * @param string $ip
7498
 *
7499
 * @return bool True if IP is in the range, false otherwise
7500
 *
7501
 * @author claudiu at cnixs dot com  on http://www.php.net/manual/fr/ref.network.php#55230
7502
 * @author Yannick Warnier for improvements and managment of multiple ranges
7503
 *
7504
 * @todo check for IPv6 support
7505
 */
7506
function api_check_ip_in_range($ip, $range)
7507
{
7508
    if (empty($ip) or empty($range)) {
7509
        return false;
7510
    }
7511
    $ip_ip = ip2long($ip);
7512
    // divide range param into array of elements
7513
    if (false !== strpos($range, ',')) {
7514
        $ranges = explode(',', $range);
7515
    } else {
7516
        $ranges = [$range];
7517
    }
7518
    foreach ($ranges as $range) {
0 ignored issues
show
introduced by
$range is overwriting one of the parameters of this function.
Loading history...
7519
        $range = trim($range);
7520
        if (empty($range)) {
7521
            continue;
7522
        }
7523
        if (false === strpos($range, '/')) {
7524
            if (0 === strcmp($ip, $range)) {
7525
                return true; // there is a direct IP match, return OK
7526
            }
7527
            continue; //otherwise, get to the next range
7528
        }
7529
        // the range contains a "/", so analyse completely
7530
        list($net, $mask) = explode("/", $range);
7531
7532
        $ip_net = ip2long($net);
7533
        // mask binary magic
7534
        $ip_mask = ~((1 << (32 - $mask)) - 1);
7535
7536
        $ip_ip_net = $ip_ip & $ip_mask;
7537
        if ($ip_ip_net == $ip_net) {
7538
            return true;
7539
        }
7540
    }
7541
7542
    return false;
7543
}
7544
7545
function api_check_user_access_to_legal($course_visibility)
7546
{
7547
    $course_visibility_list = [COURSE_VISIBILITY_OPEN_WORLD, COURSE_VISIBILITY_OPEN_PLATFORM];
7548
7549
    return in_array($course_visibility, $course_visibility_list) || api_is_drh();
7550
}
7551
7552
/**
7553
 * Checks if the global chat is enabled or not.
7554
 *
7555
 * @return bool
7556
 */
7557
function api_is_global_chat_enabled()
7558
{
7559
    return
7560
        !api_is_anonymous() &&
7561
        'true' === api_get_setting('allow_global_chat') &&
7562
        'true' === api_get_setting('allow_social_tool');
7563
}
7564
7565
/**
7566
 * @todo Fix tool_visible_by_default_at_creation labels
7567
 * @todo Add sessionId parameter to avoid using context
7568
 *
7569
 * @param int   $item_id
7570
 * @param int   $tool_id
7571
 * @param int   $group_id   id
7572
 * @param array $courseInfo
7573
 * @param int   $sessionId
7574
 * @param int   $userId
7575
 */
7576
function api_set_default_visibility(
7577
    $item_id,
7578
    $tool_id,
7579
    $group_id = 0,
7580
    $courseInfo = [],
7581
    $sessionId = 0,
7582
    $userId = 0
7583
) {
7584
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
7585
    $courseId = $courseInfo['real_id'];
7586
    $courseCode = $courseInfo['code'];
7587
    $sessionId = empty($sessionId) ? api_get_session_id() : $sessionId;
7588
    $userId = empty($userId) ? api_get_user_id() : $userId;
7589
7590
    // if group is null force group_id = 0, this force is needed to create a LP folder with group = 0
7591
    if (is_null($group_id)) {
7592
        $group_id = 0;
7593
    } else {
7594
        $group_id = empty($group_id) ? api_get_group_id() : $group_id;
7595
    }
7596
7597
    $groupInfo = [];
7598
    if (!empty($group_id)) {
7599
        $groupInfo = GroupManager::get_group_properties($group_id);
7600
    }
7601
    $original_tool_id = $tool_id;
7602
7603
    switch ($tool_id) {
7604
        case TOOL_LINK:
7605
        case TOOL_LINK_CATEGORY:
7606
            $tool_id = 'links';
7607
            break;
7608
        case TOOL_DOCUMENT:
7609
            $tool_id = 'documents';
7610
            break;
7611
        case TOOL_LEARNPATH:
7612
            $tool_id = 'learning';
7613
            break;
7614
        case TOOL_ANNOUNCEMENT:
7615
            $tool_id = 'announcements';
7616
            break;
7617
        case TOOL_FORUM:
7618
        case TOOL_FORUM_CATEGORY:
7619
        case TOOL_FORUM_THREAD:
7620
            $tool_id = 'forums';
7621
            break;
7622
        case TOOL_QUIZ:
7623
            $tool_id = 'quiz';
7624
            break;
7625
    }
7626
    $setting = api_get_setting('tool_visible_by_default_at_creation');
7627
7628
    if (isset($setting[$tool_id])) {
7629
        $visibility = 'invisible';
7630
        if ('true' == $setting[$tool_id]) {
7631
            $visibility = 'visible';
7632
        }
7633
7634
        // Read the portal and course default visibility
7635
        if ('documents' === $tool_id) {
7636
            $visibility = DocumentManager::getDocumentDefaultVisibility($courseInfo);
7637
        }
7638
7639
        api_item_property_update(
7640
            $courseInfo,
7641
            $original_tool_id,
7642
            $item_id,
7643
            $visibility,
7644
            $userId,
7645
            $groupInfo,
7646
            null,
7647
            null,
7648
            null,
7649
            $sessionId
7650
        );
7651
7652
        // Fixes default visibility for tests
7653
        switch ($original_tool_id) {
7654
            case TOOL_QUIZ:
7655
                if (empty($sessionId)) {
7656
                    $objExerciseTmp = new Exercise($courseId);
7657
                    $objExerciseTmp->read($item_id);
7658
                    if ('visible' == $visibility) {
7659
                        $objExerciseTmp->enable();
7660
                        $objExerciseTmp->save();
7661
                    } else {
7662
                        $objExerciseTmp->disable();
7663
                        $objExerciseTmp->save();
7664
                    }
7665
                }
7666
                break;
7667
        }
7668
    }
7669
}
7670
7671
/**
7672
 * @return string
7673
 */
7674
function api_get_security_key()
7675
{
7676
    return api_get_configuration_value('security_key');
0 ignored issues
show
Bug Best Practice introduced by
The expression return api_get_configura...n_value('security_key') also could return the type boolean which is incompatible with the documented return type string.
Loading history...
7677
}
7678
7679
/**
7680
 * @param int $user_id
7681
 * @param int $courseId
7682
 * @param int $session_id
7683
 *
7684
 * @return array
7685
 */
7686
function api_detect_user_roles($user_id, $courseId, $session_id = 0)
7687
{
7688
    $user_roles = [];
7689
    $courseInfo = api_get_course_info_by_id($courseId);
7690
    $course_code = $courseInfo['code'];
7691
7692
    $url_id = api_get_current_access_url_id();
7693
    if (api_is_platform_admin_by_id($user_id, $url_id)) {
7694
        $user_roles[] = PLATFORM_ADMIN;
7695
    }
7696
7697
    /*if (api_is_drh()) {
7698
        $user_roles[] = DRH;
7699
    }*/
7700
7701
    if (!empty($session_id)) {
7702
        if (SessionManager::user_is_general_coach($user_id, $session_id)) {
7703
            $user_roles[] = SESSION_GENERAL_COACH;
7704
        }
7705
    }
7706
7707
    if (!empty($course_code)) {
7708
        if (empty($session_id)) {
7709
            if (CourseManager::is_course_teacher($user_id, $course_code)) {
7710
                $user_roles[] = COURSEMANAGER;
7711
            }
7712
            if (CourseManager::get_tutor_in_course_status($user_id, $courseInfo['real_id'])) {
7713
                $user_roles[] = COURSE_TUTOR;
7714
            }
7715
7716
            if (CourseManager::is_user_subscribed_in_course($user_id, $course_code)) {
7717
                $user_roles[] = COURSE_STUDENT;
7718
            }
7719
        } else {
7720
            $user_status_in_session = SessionManager::get_user_status_in_course_session(
7721
                $user_id,
7722
                $courseId,
7723
                $session_id
7724
            );
7725
7726
            if (!empty($user_status_in_session)) {
7727
                if (0 == $user_status_in_session) {
7728
                    $user_roles[] = SESSION_STUDENT;
7729
                }
7730
                if (2 == $user_status_in_session) {
7731
                    $user_roles[] = SESSION_COURSE_COACH;
7732
                }
7733
            }
7734
7735
            /*if (api_is_course_session_coach($user_id, $course_code, $session_id)) {
7736
               $user_roles[] = SESSION_COURSE_COACH;
7737
            }*/
7738
        }
7739
    }
7740
7741
    return $user_roles;
7742
}
7743
7744
/**
7745
 * @param int $courseId
7746
 * @param int $session_id
7747
 *
7748
 * @return bool
7749
 */
7750
function api_coach_can_edit_view_results($courseId = null, $session_id = null)
7751
{
7752
    if (api_is_platform_admin()) {
7753
        return true;
7754
    }
7755
7756
    $user_id = api_get_user_id();
7757
7758
    if (empty($courseId)) {
7759
        $courseId = api_get_course_int_id();
7760
    }
7761
7762
    if (empty($session_id)) {
7763
        $session_id = api_get_session_id();
7764
    }
7765
7766
    $roles = api_detect_user_roles($user_id, $courseId, $session_id);
7767
7768
    if (in_array(SESSION_COURSE_COACH, $roles)) {
7769
        //return api_get_setting('session_tutor_reports_visibility') == 'true';
7770
        return true;
7771
    } else {
7772
        if (in_array(COURSEMANAGER, $roles)) {
7773
            return true;
7774
        }
7775
7776
        return false;
7777
    }
7778
}
7779
7780
/**
7781
 * @param string $file
7782
 *
7783
 * @return string
7784
 */
7785
function api_get_js_simple($file)
7786
{
7787
    return '<script type="text/javascript" src="'.$file.'"></script>'."\n";
7788
}
7789
7790
/**
7791
 * Modify default memory_limit and max_execution_time limits
7792
 * Needed when processing long tasks.
7793
 */
7794
function api_set_more_memory_and_time_limits()
7795
{
7796
    if (function_exists('ini_set')) {
7797
        api_set_memory_limit('256M');
7798
        ini_set('max_execution_time', 1800);
7799
    }
7800
}
7801
7802
/**
7803
 * Tries to set memory limit, if authorized and new limit is higher than current.
7804
 *
7805
 * @param string $mem New memory limit
7806
 *
7807
 * @return bool True on success, false on failure or current is higher than suggested
7808
 * @assert (null) === false
7809
 * @assert (-1) === false
7810
 * @assert (0) === true
7811
 * @assert ('1G') === true
7812
 */
7813
function api_set_memory_limit($mem)
7814
{
7815
    //if ini_set() not available, this function is useless
7816
    if (!function_exists('ini_set') || is_null($mem) || -1 == $mem) {
7817
        return false;
7818
    }
7819
7820
    $memory_limit = ini_get('memory_limit');
7821
    if (api_get_bytes_memory_limit($mem) > api_get_bytes_memory_limit($memory_limit)) {
7822
        ini_set('memory_limit', $mem);
7823
7824
        return true;
7825
    }
7826
7827
    return false;
7828
}
7829
7830
/**
7831
 * Gets memory limit in bytes.
7832
 *
7833
 * @param string The memory size (128M, 1G, 1000K, etc)
7834
 *
7835
 * @return int
7836
 * @assert (null) === false
7837
 * @assert ('1t')  === 1099511627776
7838
 * @assert ('1g')  === 1073741824
7839
 * @assert ('1m')  === 1048576
7840
 * @assert ('100k') === 102400
7841
 */
7842
function api_get_bytes_memory_limit($mem)
7843
{
7844
    $size = strtolower(substr($mem, -1));
7845
7846
    switch ($size) {
7847
        case 't':
7848
            $mem = intval(substr($mem, -1)) * 1024 * 1024 * 1024 * 1024;
7849
            break;
7850
        case 'g':
7851
            $mem = intval(substr($mem, 0, -1)) * 1024 * 1024 * 1024;
7852
            break;
7853
        case 'm':
7854
            $mem = intval(substr($mem, 0, -1)) * 1024 * 1024;
7855
            break;
7856
        case 'k':
7857
            $mem = intval(substr($mem, 0, -1)) * 1024;
7858
            break;
7859
        default:
7860
            // we assume it's integer only
7861
            $mem = intval($mem);
7862
            break;
7863
    }
7864
7865
    return $mem;
7866
}
7867
7868
/**
7869
 * Finds all the information about a user from username instead of user id.
7870
 *
7871
 * @param string $officialCode
7872
 *
7873
 * @return array $user_info user_id, lastname, firstname, username, email, ...
7874
 *
7875
 * @author Yannick Warnier <[email protected]>
7876
 */
7877
function api_get_user_info_from_official_code($officialCode)
7878
{
7879
    if (empty($officialCode)) {
7880
        return false;
7881
    }
7882
    $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_USER)."
7883
            WHERE official_code ='".Database::escape_string($officialCode)."'";
7884
    $result = Database::query($sql);
7885
    if (Database::num_rows($result) > 0) {
7886
        $result_array = Database::fetch_array($result);
7887
7888
        return _api_format_user($result_array);
7889
    }
7890
7891
    return false;
7892
}
7893
7894
/**
7895
 * @param string $usernameInputId
7896
 * @param string $passwordInputId
7897
 *
7898
 * @return string|null
7899
 */
7900
function api_get_password_checker_js($usernameInputId, $passwordInputId)
7901
{
7902
    $checkPass = api_get_setting('allow_strength_pass_checker');
7903
    $useStrengthPassChecker = 'true' === $checkPass;
7904
7905
    if (false === $useStrengthPassChecker) {
7906
        return null;
7907
    }
7908
7909
    $translations = [
7910
        'wordLength' => get_lang('The password is too short'),
7911
        'wordNotEmail' => get_lang('Your password cannot be the same as your email'),
7912
        'wordSimilarToUsername' => get_lang('Your password cannot contain your username'),
7913
        'wordTwoCharacterClasses' => get_lang('Use different character classes'),
7914
        'wordRepetitions' => get_lang('Too many repetitions'),
7915
        'wordSequences' => get_lang('Your password contains sequences'),
7916
        'errorList' => get_lang('errors found'),
7917
        'veryWeak' => get_lang('Very weak'),
7918
        'weak' => get_lang('Weak'),
7919
        'normal' => get_lang('Normal'),
7920
        'medium' => get_lang('Medium'),
7921
        'strong' => get_lang('Strong'),
7922
        'veryStrong' => get_lang('Very strong'),
7923
    ];
7924
7925
    $js = api_get_asset('pwstrength-bootstrap/dist/pwstrength-bootstrap.min.js');
7926
    $js .= "<script>
7927
    var errorMessages = {
7928
        password_to_short : \"".get_lang('The password is too short')."\",
7929
        same_as_username : \"".get_lang('Your password cannot be the same as your username')."\"
7930
    };
7931
7932
    $(function() {
7933
        var lang = ".json_encode($translations).";
7934
        var options = {
7935
            onLoad : function () {
7936
                //$('#messages').text('Start typing password');
7937
            },
7938
            onKeyUp: function (evt) {
7939
                $(evt.target).pwstrength('outputErrorList');
7940
            },
7941
            errorMessages : errorMessages,
7942
            viewports: {
7943
                progress: '#password_progress',
7944
                verdict: '#password-verdict',
7945
                errors: '#password-errors'
7946
            },
7947
            usernameField: '$usernameInputId'
7948
        };
7949
        options.i18n = {
7950
            t: function (key) {
7951
                var result = lang[key];
7952
                return result === key ? '' : result; // This assumes you return the
7953
            }
7954
        };
7955
        $('".$passwordInputId."').pwstrength(options);
7956
    });
7957
    </script>";
7958
7959
    return $js;
7960
}
7961
7962
/**
7963
 * create an user extra field called 'captcha_blocked_until_date'.
7964
 *
7965
 * @param string $username
7966
 *
7967
 * @return bool
7968
 */
7969
function api_block_account_captcha($username)
7970
{
7971
    $userInfo = api_get_user_info_from_username($username);
7972
    if (empty($userInfo)) {
7973
        return false;
7974
    }
7975
    $minutesToBlock = api_get_setting('captcha_time_to_block');
7976
    $time = time() + $minutesToBlock * 60;
7977
    UserManager::update_extra_field_value(
7978
        $userInfo['user_id'],
7979
        'captcha_blocked_until_date',
7980
        api_get_utc_datetime($time)
7981
    );
7982
7983
    return true;
7984
}
7985
7986
/**
7987
 * @param string $username
7988
 *
7989
 * @return bool
7990
 */
7991
function api_clean_account_captcha($username)
7992
{
7993
    $userInfo = api_get_user_info_from_username($username);
7994
    if (empty($userInfo)) {
7995
        return false;
7996
    }
7997
    Session::erase('loginFailedCount');
7998
    UserManager::update_extra_field_value(
7999
        $userInfo['user_id'],
8000
        'captcha_blocked_until_date',
8001
        null
8002
    );
8003
8004
    return true;
8005
}
8006
8007
/**
8008
 * @param string $username
8009
 *
8010
 * @return bool
8011
 */
8012
function api_get_user_blocked_by_captcha($username)
8013
{
8014
    $userInfo = api_get_user_info_from_username($username);
8015
    if (empty($userInfo)) {
8016
        return false;
8017
    }
8018
    $data = UserManager::get_extra_user_data_by_field(
8019
        $userInfo['user_id'],
8020
        'captcha_blocked_until_date'
8021
    );
8022
    if (isset($data) && isset($data['captcha_blocked_until_date'])) {
8023
        return $data['captcha_blocked_until_date'];
8024
    }
8025
8026
    return false;
8027
}
8028
8029
/**
8030
 * Remove tags from HTML anf return the $in_number_char first non-HTML char
8031
 * Postfix the text with "..." if it has been truncated.
8032
 *
8033
 * @param string $text
8034
 * @param int    $number
8035
 *
8036
 * @return string
8037
 *
8038
 * @author hubert borderiou
8039
 */
8040
function api_get_short_text_from_html($text, $number)
8041
{
8042
    // Delete script and style tags
8043
    $text = preg_replace('/(<(script|style)\b[^>]*>).*?(<\/\2>)/is', "$1$3", $text);
8044
    $text = api_html_entity_decode($text);
8045
    $out_res = api_remove_tags_with_space($text, false);
8046
    $postfix = "...";
8047
    if (strlen($out_res) > $number) {
8048
        $out_res = substr($out_res, 0, $number).$postfix;
8049
    }
8050
8051
    return $out_res;
8052
}
8053
8054
/**
8055
 * Replace tags with a space in a text.
8056
 * If $in_double_quote_replace, replace " with '' (for HTML attribute purpose, for exemple).
8057
 *
8058
 * @return string
8059
 *
8060
 * @author hubert borderiou
8061
 */
8062
function api_remove_tags_with_space($in_html, $in_double_quote_replace = true)
8063
{
8064
    $out_res = $in_html;
8065
    if ($in_double_quote_replace) {
8066
        $out_res = str_replace('"', "''", $out_res);
8067
    }
8068
    // avoid text stuck together when tags are removed, adding a space after >
8069
    $out_res = str_replace(">", "> ", $out_res);
8070
    $out_res = strip_tags($out_res);
8071
8072
    return $out_res;
8073
}
8074
8075
/**
8076
 * If true, the drh can access all content (courses, users) inside a session.
8077
 *
8078
 * @return bool
8079
 */
8080
function api_drh_can_access_all_session_content()
8081
{
8082
    $value = api_get_setting('drh_can_access_all_session_content');
8083
8084
    return 'true' === $value;
8085
}
8086
8087
/**
8088
 * @param string $tool
8089
 * @param string $setting
8090
 * @param int    $defaultValue
8091
 *
8092
 * @return string
8093
 */
8094
function api_get_default_tool_setting($tool, $setting, $defaultValue)
8095
{
8096
    global $_configuration;
8097
    if (isset($_configuration[$tool]) &&
8098
        isset($_configuration[$tool]['default_settings']) &&
8099
        isset($_configuration[$tool]['default_settings'][$setting])
8100
    ) {
8101
        return $_configuration[$tool]['default_settings'][$setting];
8102
    }
8103
8104
    return $defaultValue;
8105
}
8106
8107
/**
8108
 * Checks if user can login as another user.
8109
 *
8110
 * @param int $loginAsUserId the user id to log in
8111
 * @param int $userId        my user id
8112
 *
8113
 * @return bool
8114
 */
8115
function api_can_login_as($loginAsUserId, $userId = null)
8116
{
8117
    if (empty($userId)) {
8118
        $userId = api_get_user_id();
8119
    }
8120
    if ($loginAsUserId == $userId) {
8121
        return false;
8122
    }
8123
8124
    if (empty($loginAsUserId)) {
8125
        return false;
8126
    }
8127
8128
    if ($loginAsUserId != strval(intval($loginAsUserId))) {
8129
        return false;
8130
    }
8131
8132
    // Check if the user to login is an admin
8133
    if (api_is_platform_admin_by_id($loginAsUserId)) {
8134
        // Only super admins can login to admin accounts
8135
        if (!api_global_admin_can_edit_admin($loginAsUserId)) {
8136
            return false;
8137
        }
8138
    }
8139
8140
    $userInfo = api_get_user_info($loginAsUserId);
8141
    $isDrh = function () use ($loginAsUserId) {
8142
        if (api_is_drh()) {
8143
            if (api_drh_can_access_all_session_content()) {
8144
                $users = SessionManager::getAllUsersFromCoursesFromAllSessionFromStatus(
8145
                    'drh_all',
8146
                    api_get_user_id()
8147
                );
8148
                $userList = [];
8149
                if (is_array($users)) {
8150
                    foreach ($users as $user) {
8151
                        $userList[] = $user['user_id'];
8152
                    }
8153
                }
8154
                if (in_array($loginAsUserId, $userList)) {
8155
                    return true;
8156
                }
8157
            } else {
8158
                if (api_is_drh() &&
8159
                    UserManager::is_user_followed_by_drh($loginAsUserId, api_get_user_id())
8160
                ) {
8161
                    return true;
8162
                }
8163
            }
8164
        }
8165
8166
        return false;
8167
    };
8168
8169
    $loginAsStatusForSessionAdmins = [STUDENT];
8170
8171
    if (api_get_setting('session.allow_session_admin_login_as_teacher')) {
8172
        $loginAsStatusForSessionAdmins[] = COURSEMANAGER;
8173
    }
8174
8175
    return api_is_platform_admin() ||
8176
        (api_is_session_admin() && in_array($userInfo['status'], $loginAsStatusForSessionAdmins)) ||
8177
        $isDrh();
8178
}
8179
8180
/**
8181
 * @return bool
8182
 */
8183
function api_is_allowed_in_course()
8184
{
8185
    if (api_is_platform_admin()) {
8186
        return true;
8187
    }
8188
8189
    $user = api_get_current_user();
8190
    if ($user instanceof User) {
8191
        if ($user->hasRole('ROLE_CURRENT_SESSION_COURSE_STUDENT') ||
8192
            $user->hasRole('ROLE_CURRENT_SESSION_COURSE_TEACHER') ||
8193
            $user->hasRole('ROLE_CURRENT_COURSE_STUDENT') ||
8194
            $user->hasRole('ROLE_CURRENT_COURSE_TEACHER')
8195
        ) {
8196
            return true;
8197
        }
8198
    }
8199
8200
    return false;
8201
}
8202
8203
/**
8204
 * Set the cookie to go directly to the course code $in_firstpage
8205
 * after login.
8206
 *
8207
 * @param string $value is the course code of the course to go
8208
 */
8209
function api_set_firstpage_parameter($value)
8210
{
8211
    setcookie('GotoCourse', $value);
8212
}
8213
8214
/**
8215
 * Delete the cookie to go directly to the course code $in_firstpage
8216
 * after login.
8217
 */
8218
function api_delete_firstpage_parameter()
8219
{
8220
    setcookie('GotoCourse', '', time() - 3600);
8221
}
8222
8223
/**
8224
 * @return bool if course_code for direct course access after login is set
8225
 */
8226
function exist_firstpage_parameter()
8227
{
8228
    return isset($_COOKIE['GotoCourse']) && '' != $_COOKIE['GotoCourse'];
8229
}
8230
8231
/**
8232
 * @return return the course_code of the course where user login
8233
 */
8234
function api_get_firstpage_parameter()
8235
{
8236
    return $_COOKIE['GotoCourse'];
8237
}
8238
8239
/**
8240
 * Return true on https install.
8241
 *
8242
 * @return bool
8243
 */
8244
function api_is_https()
8245
{
8246
    if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: (! empty($_SERVER['HTTP_...ttps_forwarded_proto']), Probably Intended Meaning: ! empty($_SERVER['HTTP_X...tps_forwarded_proto']))
Loading history...
8247
        'https' == $_SERVER['HTTP_X_FORWARDED_PROTO'] || !empty($_configuration['force_https_forwarded_proto'])
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $_configuration seems to never exist and therefore empty should always be true.
Loading history...
8248
    ) {
8249
        $isSecured = true;
8250
    } else {
8251
        if (!empty($_SERVER['HTTPS']) && 'off' != $_SERVER['HTTPS']) {
8252
            $isSecured = true;
8253
        } else {
8254
            $isSecured = false;
8255
            // last chance
8256
            if (!empty($_SERVER['SERVER_PORT']) && 443 == $_SERVER['SERVER_PORT']) {
8257
                $isSecured = true;
8258
            }
8259
        }
8260
    }
8261
8262
    return $isSecured;
8263
}
8264
8265
/**
8266
 * Return protocol (http or https).
8267
 *
8268
 * @return string
8269
 */
8270
function api_get_protocol()
8271
{
8272
    return api_is_https() ? 'https' : 'http';
8273
}
8274
8275
/**
8276
 * Return a string where " are replaced with 2 '
8277
 * It is useful when you pass a PHP variable in a Javascript browser dialog
8278
 * e.g. : alert("<?php get_lang('Message') ?>");
8279
 * and message contains character ".
8280
 *
8281
 * @param string $in_text
8282
 *
8283
 * @return string
8284
 */
8285
function convert_double_quote_to_single($in_text)
8286
{
8287
    return api_preg_replace('/"/', "''", $in_text);
8288
}
8289
8290
/**
8291
 * Get origin.
8292
 *
8293
 * @param string
8294
 *
8295
 * @return string
8296
 */
8297
function api_get_origin()
8298
{
8299
    $origin = isset($_REQUEST['origin']) ? Security::remove_XSS($_REQUEST['origin']) : '';
8300
8301
    return $origin;
8302
}
8303
8304
/**
8305
 * Warns an user that the portal reach certain limit.
8306
 *
8307
 * @param string $limitName
8308
 */
8309
function api_warn_hosting_contact($limitName)
8310
{
8311
    $hostingParams = api_get_configuration_value(1);
8312
    $email = null;
8313
8314
    if (!empty($hostingParams)) {
8315
        if (isset($hostingParams['hosting_contact_mail'])) {
8316
            $email = $hostingParams['hosting_contact_mail'];
8317
        }
8318
    }
8319
8320
    if (!empty($email)) {
8321
        $subject = get_lang('Hosting warning reached');
8322
        $body = get_lang('Portal name').': '.api_get_path(WEB_PATH)." \n ";
8323
        $body .= get_lang('Portal\'s limit type').': '.$limitName." \n ";
8324
        if (isset($hostingParams[$limitName])) {
8325
            $body .= get_lang('Value').': '.$hostingParams[$limitName];
8326
        }
8327
        api_mail_html(null, $email, $subject, $body);
8328
    }
8329
}
8330
8331
/**
8332
 * Gets value of a variable from config/configuration.php
8333
 * Variables that are not set in the configuration.php file but set elsewhere:
8334
 * - virtual_css_theme_folder (vchamilo plugin)
8335
 * - access_url (global.inc.php)
8336
 * - apc/apc_prefix (global.inc.php).
8337
 *
8338
 * @param string $variable
8339
 *
8340
 * @return bool|mixed
8341
 */
8342
function api_get_configuration_value($variable)
8343
{
8344
    global $_configuration;
8345
    // Check the current url id, id = 1 by default
8346
    $urlId = isset($_configuration['access_url']) ? (int) $_configuration['access_url'] : 1;
8347
8348
    $variable = trim($variable);
8349
8350
    // Check if variable exists
8351
    if (isset($_configuration[$variable])) {
8352
        if (is_array($_configuration[$variable])) {
8353
            // Check if it exists for the sub portal
8354
            if (array_key_exists($urlId, $_configuration[$variable])) {
8355
                return $_configuration[$variable][$urlId];
8356
            } else {
8357
                // Try to found element with id = 1 (master portal)
8358
                if (array_key_exists(1, $_configuration[$variable])) {
8359
                    return $_configuration[$variable][1];
8360
                }
8361
            }
8362
        }
8363
8364
        return $_configuration[$variable];
8365
    }
8366
8367
    return false;
8368
}
8369
8370
/**
8371
 * Retreives and returns a value in a hierarchical configuration array
8372
 * api_get_configuration_sub_value('a/b/c') returns api_get_configuration_value('a')['b']['c'].
8373
 *
8374
 * @param string $path      the successive array keys, separated by the separator
8375
 * @param mixed  $default   value to be returned if not found, null by default
8376
 * @param string $separator '/' by default
8377
 * @param array  $array     the active configuration array by default
8378
 *
8379
 * @return mixed the found value or $default
8380
 */
8381
function api_get_configuration_sub_value($path, $default = null, $separator = '/', $array = null)
8382
{
8383
    $pos = strpos($path, $separator);
8384
    if (false === $pos) {
8385
        if (is_null($array)) {
8386
            return api_get_configuration_value($path);
8387
        }
8388
        if (is_array($array) && array_key_exists($path, $array)) {
8389
            return $array[$path];
8390
        }
8391
8392
        return $default;
8393
    }
8394
    $key = substr($path, 0, $pos);
8395
    if (is_null($array)) {
8396
        $newArray = api_get_configuration_value($key);
8397
    } elseif (is_array($array) && array_key_exists($key, $array)) {
8398
        $newArray = $array[$key];
8399
    } else {
8400
        return $default;
8401
    }
8402
    if (is_array($newArray)) {
8403
        $newPath = substr($path, $pos + 1);
8404
8405
        return api_get_configuration_sub_value($newPath, $default, $separator, $newArray);
8406
    }
8407
8408
    return $default;
8409
}
8410
8411
/**
8412
 * Retrieves and returns a value in a hierarchical configuration array
8413
 * api_array_sub_value($array, 'a/b/c') returns $array['a']['b']['c'].
8414
 *
8415
 * @param array  $array     the recursive array that contains the value to be returned (or not)
8416
 * @param string $path      the successive array keys, separated by the separator
8417
 * @param mixed  $default   the value to be returned if not found
8418
 * @param string $separator the separator substring
8419
 *
8420
 * @return mixed the found value or $default
8421
 */
8422
function api_array_sub_value($array, $path, $default = null, $separator = '/')
8423
{
8424
    $pos = strpos($path, $separator);
8425
    if (false === $pos) {
8426
        if (is_array($array) && array_key_exists($path, $array)) {
8427
            return $array[$path];
8428
        }
8429
8430
        return $default;
8431
    }
8432
    $key = substr($path, 0, $pos);
8433
    if (is_array($array) && array_key_exists($key, $array)) {
8434
        $newArray = $array[$key];
8435
    } else {
8436
        return $default;
8437
    }
8438
    if (is_array($newArray)) {
8439
        $newPath = substr($path, $pos + 1);
8440
8441
        return api_array_sub_value($newArray, $newPath, $default);
8442
    }
8443
8444
    return $default;
8445
}
8446
8447
/**
8448
 * Returns supported image extensions in the portal.
8449
 *
8450
 * @param bool $supportVectors Whether vector images should also be accepted or not
8451
 *
8452
 * @return array Supported image extensions in the portal
8453
 */
8454
function api_get_supported_image_extensions($supportVectors = true)
8455
{
8456
    // jpg can also be called jpeg, jpe, jfif and jif. See https://en.wikipedia.org/wiki/JPEG#JPEG_filename_extensions
8457
    $supportedImageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'jpe', 'jfif', 'jif'];
8458
    if ($supportVectors) {
8459
        array_push($supportedImageExtensions, 'svg');
8460
    }
8461
    if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
8462
        array_push($supportedImageExtensions, 'webp');
8463
    }
8464
8465
    return $supportedImageExtensions;
8466
}
8467
8468
/**
8469
 * This setting changes the registration status for the campus.
8470
 *
8471
 * @author Patrick Cool <[email protected]>, Ghent University
8472
 *
8473
 * @version August 2006
8474
 *
8475
 * @param bool $listCampus Whether we authorize
8476
 *
8477
 * @todo the $_settings should be reloaded here. => write api function for this and use this in global.inc.php also.
8478
 */
8479
function api_register_campus($listCampus = true)
8480
{
8481
    $tbl_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
8482
8483
    $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='registered'";
8484
    Database::query($sql);
8485
8486
    if (!$listCampus) {
8487
        $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='donotlistcampus'";
8488
        Database::query($sql);
8489
    }
8490
}
8491
8492
/**
8493
 * Checks whether current user is a student boss.
8494
 *
8495
 * @global array $_user
8496
 *
8497
 * @return bool
8498
 */
8499
function api_is_student_boss()
8500
{
8501
    $_user = api_get_user_info();
8502
8503
    return isset($_user['status']) && STUDENT_BOSS == $_user['status'];
8504
}
8505
8506
/**
8507
 * Check whether the user type should be exclude.
8508
 * Such as invited or anonymous users.
8509
 *
8510
 * @param bool $checkDB Optional. Whether check the user status
8511
 * @param int  $userId  Options. The user id
8512
 *
8513
 * @return bool
8514
 */
8515
function api_is_excluded_user_type($checkDB = false, $userId = 0)
8516
{
8517
    if ($checkDB) {
8518
        $userId = empty($userId) ? api_get_user_id() : (int) $userId;
8519
8520
        if (0 == $userId) {
8521
            return true;
8522
        }
8523
8524
        $userInfo = api_get_user_info($userId);
8525
8526
        switch ($userInfo['status']) {
8527
            case INVITEE:
8528
            case ANONYMOUS:
8529
                return true;
8530
            default:
8531
                return false;
8532
        }
8533
    }
8534
8535
    $isInvited = api_is_invitee();
8536
    $isAnonymous = api_is_anonymous();
8537
8538
    if ($isInvited || $isAnonymous) {
8539
        return true;
8540
    }
8541
8542
    return false;
8543
}
8544
8545
/**
8546
 * Get the user status to ignore in reports.
8547
 *
8548
 * @param string $format Optional. The result type (array or string)
8549
 *
8550
 * @return array|string
8551
 */
8552
function api_get_users_status_ignored_in_reports($format = 'array')
8553
{
8554
    $excludedTypes = [
8555
        INVITEE,
8556
        ANONYMOUS,
8557
    ];
8558
8559
    if ('string' == $format) {
8560
        return implode(', ', $excludedTypes);
8561
    }
8562
8563
    return $excludedTypes;
8564
}
8565
8566
/**
8567
 * Set the Site Use Cookie Warning for 1 year.
8568
 */
8569
function api_set_site_use_cookie_warning_cookie()
8570
{
8571
    setcookie('ChamiloUsesCookies', 'ok', time() + 31556926);
8572
}
8573
8574
/**
8575
 * Return true if the Site Use Cookie Warning Cookie warning exists.
8576
 *
8577
 * @return bool
8578
 */
8579
function api_site_use_cookie_warning_cookie_exist()
8580
{
8581
    return isset($_COOKIE['ChamiloUsesCookies']);
8582
}
8583
8584
/**
8585
 * Given a number of seconds, format the time to show hours, minutes and seconds.
8586
 *
8587
 * @param int    $time         The time in seconds
8588
 * @param string $originFormat Optional. PHP o JS
8589
 *
8590
 * @return string (00h00'00")
8591
 */
8592
function api_format_time($time, $originFormat = 'php')
8593
{
8594
    $h = get_lang('h');
8595
    $hours = $time / 3600;
8596
    $mins = ($time % 3600) / 60;
8597
    $secs = ($time % 60);
8598
8599
    if ($time < 0) {
8600
        $hours = 0;
8601
        $mins = 0;
8602
        $secs = 0;
8603
    }
8604
8605
    if ('js' == $originFormat) {
8606
        $formattedTime = trim(sprintf("%02d : %02d : %02d", $hours, $mins, $secs));
8607
    } else {
8608
        $formattedTime = trim(sprintf("%02d$h%02d'%02d\"", $hours, $mins, $secs));
8609
    }
8610
8611
    return $formattedTime;
8612
}
8613
8614
/**
8615
 * Create a new empty directory with index.html file.
8616
 *
8617
 * @param string $name            The new directory name
8618
 * @param string $parentDirectory Directory parent directory name
8619
 *
8620
 * @deprecated use Resources
8621
 *
8622
 * @return bool Return true if the directory was create. Otherwise return false
8623
 */
8624
function api_create_protected_dir($name, $parentDirectory)
8625
{
8626
    $isCreated = false;
8627
8628
    if (!is_writable($parentDirectory)) {
8629
        return false;
8630
    }
8631
8632
    $fullPath = $parentDirectory.api_replace_dangerous_char($name);
8633
8634
    if (mkdir($fullPath, api_get_permissions_for_new_directories(), true)) {
8635
        $fp = fopen($fullPath.'/index.html', 'w');
8636
8637
        if ($fp) {
0 ignored issues
show
introduced by
$fp is of type false|resource, thus it always evaluated to false.
Loading history...
8638
            if (fwrite($fp, '<html><head></head><body></body></html>')) {
8639
                $isCreated = true;
8640
            }
8641
        }
8642
8643
        fclose($fp);
8644
    }
8645
8646
    return $isCreated;
8647
}
8648
8649
/**
8650
 * Sends an email
8651
 * Sender name and email can be specified, if not specified
8652
 * name and email of the platform admin are used.
8653
 *
8654
 * @param string    name of recipient
8655
 * @param string    email of recipient
8656
 * @param string    email subject
8657
 * @param string    email body
8658
 * @param string    sender name
8659
 * @param string    sender e-mail
8660
 * @param array     extra headers in form $headers = array($name => $value) to allow parsing
8661
 * @param array     data file (path and filename)
8662
 * @param bool      True for attaching a embedded file inside content html (optional)
8663
 * @param array     Additional parameters
8664
 *
8665
 * @return bool true if mail was sent
8666
 */
8667
function api_mail_html(
8668
    $recipientName,
8669
    $recipientEmail,
8670
    $subject,
8671
    $body,
8672
    $senderName = '',
8673
    $senderEmail = '',
8674
    $extra_headers = [],
8675
    $data_file = [],
8676
    $embeddedImage = false,
8677
    $additionalParameters = []
8678
) {
8679
    if (!api_valid_email($recipientEmail)) {
8680
        return false;
8681
    }
8682
8683
    // Default values
8684
    $notification = new Notification();
8685
    $defaultEmail = $notification->getDefaultPlatformSenderEmail();
8686
    $defaultName = $notification->getDefaultPlatformSenderName();
8687
8688
    // If the parameter is set don't use the admin.
8689
    $senderName = !empty($senderName) ? $senderName : $defaultName;
8690
    $senderEmail = !empty($senderEmail) ? $senderEmail : $defaultEmail;
8691
8692
    // Reply to first
8693
    $replyToName = '';
8694
    $replyToEmail = '';
8695
    if (isset($extra_headers['reply_to'])) {
8696
        $replyToEmail = $extra_headers['reply_to']['mail'];
8697
        $replyToName = $extra_headers['reply_to']['name'];
8698
    }
8699
8700
    try {
8701
        $message = new TemplatedEmail();
8702
        $message->subject($subject);
8703
8704
        $list = api_get_configuration_value('send_all_emails_to');
8705
        if (!empty($list) && isset($list['emails'])) {
8706
            foreach ($list['emails'] as $email) {
8707
                $message->cc($email);
8708
            }
8709
        }
8710
8711
        // Attachment
8712
        if (!empty($data_file)) {
8713
            foreach ($data_file as $file_attach) {
8714
                if (!empty($file_attach['path']) && !empty($file_attach['filename'])) {
8715
                    $message->attachFromPath($file_attach['path'], $file_attach['filename']);
8716
                }
8717
            }
8718
        }
8719
8720
        $noReply = api_get_setting('noreply_email_address');
8721
        $automaticEmailText = '';
8722
        if (!empty($noReply)) {
8723
            $automaticEmailText = '<br />'.get_lang('This is an automatic email message. Please do not reply to it.');
8724
        }
8725
8726
        $params = [
8727
            'mail_header_style' => api_get_configuration_value('mail_header_style'),
8728
            'mail_content_style' => api_get_configuration_value('mail_content_style'),
8729
            'link' => $additionalParameters['link'] ?? '',
8730
            'automatic_email_text' => $automaticEmailText,
8731
            'content' => $body,
8732
            'theme' => api_get_visual_theme(),
8733
        ];
8734
8735
        if (!empty($senderEmail)) {
8736
            $message->from(new Address($senderEmail, $senderName));
8737
        }
8738
8739
        if (!empty($recipientEmail)) {
8740
            $message->to(new Address($recipientEmail, $recipientName));
8741
        }
8742
8743
        if (!empty($replyToEmail)) {
8744
            $message->replyTo(new Address($replyToEmail, $replyToName));
8745
        }
8746
8747
        $message
8748
            ->htmlTemplate('ChamiloCoreBundle:Mailer:Default/default.html.twig')
8749
            ->textTemplate('ChamiloCoreBundle:Mailer:Default/default.text.twig')
8750
        ;
8751
        $message->context($params);
8752
        Container::getMailer()->send($message);
8753
8754
        return true;
8755
    } catch (Exception $e) {
8756
        error_log($e->getMessage());
8757
    }
8758
8759
    if (!empty($additionalParameters)) {
8760
        $plugin = new AppPlugin();
8761
        $smsPlugin = $plugin->getSMSPluginLibrary();
8762
        if ($smsPlugin) {
0 ignored issues
show
introduced by
$smsPlugin is of type SmsPluginLibraryInterface, thus it always evaluated to true.
Loading history...
8763
            $smsPlugin->send($additionalParameters);
8764
        }
8765
    }
8766
8767
    return 1;
8768
}
8769
8770
/**
8771
 * @param string $tool       Possible values: GroupManager::GROUP_TOOL_*
8772
 * @param bool   $showHeader
8773
 */
8774
function api_protect_course_group($tool, $showHeader = true)
8775
{
8776
    $groupId = api_get_group_id();
8777
    if (!empty($groupId)) {
8778
        if (api_is_platform_admin()) {
8779
            return true;
8780
        }
8781
8782
        if (api_is_allowed_to_edit(false, true, true)) {
8783
            return true;
8784
        }
8785
8786
        $userId = api_get_user_id();
8787
        $sessionId = api_get_session_id();
8788
        if (!empty($sessionId)) {
8789
            if (api_is_coach($sessionId, api_get_course_int_id())) {
8790
                return true;
8791
            }
8792
8793
            if (api_is_drh()) {
8794
                if (SessionManager::isUserSubscribedAsHRM($sessionId, $userId)) {
8795
                    return true;
8796
                }
8797
            }
8798
        }
8799
8800
        $groupInfo = GroupManager::get_group_properties($groupId);
8801
8802
        // Group doesn't exists
8803
        if (empty($groupInfo)) {
8804
            api_not_allowed($showHeader);
8805
        }
8806
8807
        // Check group access
8808
        $allow = GroupManager::user_has_access(
8809
            $userId,
8810
            $groupInfo['iid'],
8811
            $tool
8812
        );
8813
8814
        if (!$allow) {
8815
            api_not_allowed($showHeader);
8816
        }
8817
    }
8818
}
8819
8820
/**
8821
 * Check if a date is in a date range.
8822
 *
8823
 * @param datetime $startDate
8824
 * @param datetime $endDate
8825
 * @param datetime $currentDate
8826
 *
8827
 * @return bool true if date is in rage, false otherwise
8828
 */
8829
function api_is_date_in_date_range($startDate, $endDate, $currentDate = null)
8830
{
8831
    $startDate = strtotime(api_get_local_time($startDate));
8832
    $endDate = strtotime(api_get_local_time($endDate));
8833
    $currentDate = strtotime(api_get_local_time($currentDate));
8834
8835
    if ($currentDate >= $startDate && $currentDate <= $endDate) {
8836
        return true;
8837
    }
8838
8839
    return false;
8840
}
8841
8842
/**
8843
 * Eliminate the duplicates of a multidimensional array by sending the key.
8844
 *
8845
 * @param array $array multidimensional array
8846
 * @param int   $key   key to find to compare
8847
 *
8848
 * @return array
8849
 */
8850
function api_unique_multidim_array($array, $key)
8851
{
8852
    $temp_array = [];
8853
    $i = 0;
8854
    $key_array = [];
8855
8856
    foreach ($array as $val) {
8857
        if (!in_array($val[$key], $key_array)) {
8858
            $key_array[$i] = $val[$key];
8859
            $temp_array[$i] = $val;
8860
        }
8861
        $i++;
8862
    }
8863
8864
    return $temp_array;
8865
}
8866
8867
/**
8868
 * Limit the access to Session Admins when the limit_session_admin_role
8869
 * configuration variable is set to true.
8870
 */
8871
function api_protect_limit_for_session_admin()
8872
{
8873
    $limitAdmin = api_get_setting('limit_session_admin_role');
8874
    if (api_is_session_admin() && 'true' === $limitAdmin) {
8875
        api_not_allowed(true);
8876
    }
8877
}
8878
8879
/**
8880
 * Limits that a session admin has access to list users.
8881
 * When limit_session_admin_list_users configuration variable is set to true.
8882
 */
8883
function api_protect_session_admin_list_users()
8884
{
8885
    $limitAdmin = api_get_configuration_value('limit_session_admin_list_users');
8886
8887
    if (api_is_session_admin() && true === $limitAdmin) {
8888
        api_not_allowed(true);
8889
    }
8890
}
8891
8892
/**
8893
 * @return bool
8894
 */
8895
function api_is_student_view_active()
8896
{
8897
    $studentView = Session::read('studentview');
8898
8899
    return 'studentview' === $studentView;
8900
}
8901
8902
/**
8903
 * Adds a file inside the upload/$type/id.
8904
 *
8905
 * @param string $type
8906
 * @param array  $file
8907
 * @param int    $itemId
8908
 * @param string $cropParameters
8909
 *
8910
 * @deprecated use Resources
8911
 *
8912
 * @return array|bool
8913
 */
8914
function api_upload_file($type, $file, $itemId, $cropParameters = '')
8915
{
8916
    $upload = process_uploaded_file($file);
8917
    if ($upload) {
8918
        $name = api_replace_dangerous_char($file['name']);
8919
8920
        // No "dangerous" files
8921
        $name = disable_dangerous_file($name);
8922
8923
        $pathId = '/'.substr((string) $itemId, 0, 1).'/'.$itemId.'/';
8924
        $path = api_get_path(SYS_UPLOAD_PATH).$type.$pathId;
8925
8926
        if (!is_dir($path)) {
8927
            mkdir($path, api_get_permissions_for_new_directories(), true);
8928
        }
8929
8930
        $pathToSave = $path.$name;
8931
        $result = moveUploadedFile($file, $pathToSave);
8932
8933
        if ($result) {
8934
            if (!empty($cropParameters)) {
8935
                $image = new Image($pathToSave);
8936
                $image->crop($cropParameters);
8937
            }
8938
8939
            return ['path_to_save' => $pathId.$name];
8940
        }
8941
8942
        return false;
8943
    }
8944
}
8945
8946
/**
8947
 * @param string $type
8948
 * @param int    $itemId
8949
 * @param string $file
8950
 *
8951
 * @return bool
8952
 */
8953
function api_get_uploaded_web_url($type, $itemId, $file)
8954
{
8955
    return api_get_uploaded_file($type, $itemId, $file, true);
8956
}
8957
8958
/**
8959
 * @param string $type
8960
 * @param int    $itemId
8961
 * @param string $file
8962
 * @param bool   $getUrl
8963
 *
8964
 * @return bool
8965
 */
8966
function api_get_uploaded_file($type, $itemId, $file, $getUrl = false)
8967
{
8968
    $itemId = (int) $itemId;
8969
    $pathId = '/'.substr((string) $itemId, 0, 1).'/'.$itemId.'/';
8970
    $path = api_get_path(SYS_UPLOAD_PATH).$type.$pathId;
8971
    $file = basename($file);
8972
    $file = $path.'/'.$file;
8973
    if (Security::check_abs_path($file, $path) && is_file($file) && file_exists($file)) {
8974
        if ($getUrl) {
8975
            return str_replace(api_get_path(SYS_UPLOAD_PATH), api_get_path(WEB_UPLOAD_PATH), $file);
8976
        }
8977
8978
        return $file;
8979
    }
8980
8981
    return false;
8982
}
8983
8984
/**
8985
 * @param string $type
8986
 * @param int    $itemId
8987
 * @param string $file
8988
 * @param string $title
8989
 */
8990
function api_download_uploaded_file($type, $itemId, $file, $title = '')
8991
{
8992
    $file = api_get_uploaded_file($type, $itemId, $file);
8993
    if ($file) {
8994
        if (Security::check_abs_path($file, api_get_path(SYS_UPLOAD_PATH).$type)) {
8995
            DocumentManager::file_send_for_download($file, true, $title);
8996
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
8997
        }
8998
    }
8999
    api_not_allowed(true);
9000
}
9001
9002
/**
9003
 * @param string $type
9004
 * @param string $file
9005
 */
9006
function api_remove_uploaded_file($type, $file)
9007
{
9008
    $typePath = api_get_path(SYS_UPLOAD_PATH).$type;
9009
    $path = $typePath.'/'.$file;
9010
    if (Security::check_abs_path($path, $typePath) && file_exists($path) && is_file($path)) {
9011
        unlink($path);
9012
    }
9013
}
9014
9015
/**
9016
 * @param string $type
9017
 * @param int    $itemId
9018
 * @param string $file
9019
 *
9020
 * @return bool
9021
 */
9022
function api_remove_uploaded_file_by_id($type, $itemId, $file)
9023
{
9024
    $file = api_get_uploaded_file($type, $itemId, $file, false);
9025
    $typePath = api_get_path(SYS_UPLOAD_PATH).$type;
9026
    if (Security::check_abs_path($file, $typePath) && file_exists($file) && is_file($file)) {
9027
        unlink($file);
9028
9029
        return true;
9030
    }
9031
9032
    return false;
9033
}
9034
9035
/**
9036
 * Converts string value to float value.
9037
 *
9038
 * 3.141516 => 3.141516
9039
 * 3,141516 => 3.141516
9040
 *
9041
 * @todo WIP
9042
 *
9043
 * @param string $number
9044
 *
9045
 * @return float
9046
 */
9047
function api_float_val($number)
9048
{
9049
    $number = (float) str_replace(',', '.', trim($number));
9050
9051
    return $number;
9052
}
9053
9054
/**
9055
 * Converts float values
9056
 * Example if $decimals = 2.
9057
 *
9058
 * 3.141516 => 3.14
9059
 * 3,141516 => 3,14
9060
 *
9061
 * @param string $number            number in iso code
9062
 * @param int    $decimals
9063
 * @param string $decimalSeparator
9064
 * @param string $thousandSeparator
9065
 *
9066
 * @return bool|string
9067
 */
9068
function api_number_format($number, $decimals = 0, $decimalSeparator = '.', $thousandSeparator = ',')
9069
{
9070
    $number = api_float_val($number);
9071
9072
    return number_format($number, $decimals, $decimalSeparator, $thousandSeparator);
9073
}
9074
9075
/**
9076
 * Set location url with a exit break by default.
9077
 *
9078
 * @param $url
9079
 * @param bool $exit
9080
 */
9081
function location($url, $exit = true)
9082
{
9083
    header('Location: '.$url);
9084
9085
    if ($exit) {
9086
        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
9087
    }
9088
}
9089
9090
/**
9091
 * @return string
9092
 */
9093
function api_get_web_url()
9094
{
9095
    if ('test' === api_get_setting('server_type')) {
9096
        return api_get_path(WEB_PATH).'web/app_dev.php/';
9097
    } else {
9098
        return api_get_path(WEB_PATH).'web/';
9099
    }
9100
}
9101
9102
/**
9103
 * @param string $from
9104
 * @param string $to
9105
 *
9106
 * @return string
9107
 */
9108
function api_get_relative_path($from, $to)
9109
{
9110
    // some compatibility fixes for Windows paths
9111
    $from = is_dir($from) ? rtrim($from, '\/').'/' : $from;
9112
    $to = is_dir($to) ? rtrim($to, '\/').'/' : $to;
9113
    $from = str_replace('\\', '/', $from);
9114
    $to = str_replace('\\', '/', $to);
9115
9116
    $from = explode('/', $from);
9117
    $to = explode('/', $to);
9118
    $relPath = $to;
9119
9120
    foreach ($from as $depth => $dir) {
9121
        // find first non-matching dir
9122
        if ($dir === $to[$depth]) {
9123
            // ignore this directory
9124
            array_shift($relPath);
9125
        } else {
9126
            // get number of remaining dirs to $from
9127
            $remaining = count($from) - $depth;
9128
            if ($remaining > 1) {
9129
                // add traversals up to first matching dir
9130
                $padLength = (count($relPath) + $remaining - 1) * -1;
9131
                $relPath = array_pad($relPath, $padLength, '..');
9132
                break;
9133
            } else {
9134
                $relPath[0] = './'.$relPath[0];
9135
            }
9136
        }
9137
    }
9138
9139
    return implode('/', $relPath);
9140
}
9141
9142
/**
9143
 * Unserialize content using Brummann\Polyfill\Unserialize.
9144
 *
9145
 * @param string $type
9146
 * @param string $serialized
9147
 * @param bool   $ignoreErrors. Optional.
9148
 *
9149
 * @return mixed
9150
 */
9151
function api_unserialize_content($type, $serialized, $ignoreErrors = false)
9152
{
9153
    switch ($type) {
9154
        case 'career':
9155
        case 'sequence_graph':
9156
            $allowedClasses = [Graph::class, VerticesMap::class, Vertices::class, Edges::class];
9157
            break;
9158
        case 'lp':
9159
            $allowedClasses = [
9160
                learnpath::class,
9161
                learnpathItem::class,
9162
                aicc::class,
9163
                aiccBlock::class,
9164
                aiccItem::class,
9165
                aiccObjective::class,
9166
                aiccResource::class,
9167
                scorm::class,
9168
                scormItem::class,
9169
                scormMetadata::class,
9170
                scormOrganization::class,
9171
                scormResource::class,
9172
                Link::class,
9173
                LpItem::class,
9174
            ];
9175
            break;
9176
        case 'course':
9177
            $allowedClasses = [
9178
                Course::class,
9179
                Announcement::class,
9180
                Attendance::class,
9181
                CalendarEvent::class,
9182
                CourseCopyLearnpath::class,
9183
                CourseCopyTestCategory::class,
9184
                CourseDescription::class,
9185
                CourseSession::class,
9186
                Document::class,
9187
                Forum::class,
9188
                ForumCategory::class,
9189
                ForumPost::class,
9190
                ForumTopic::class,
9191
                Glossary::class,
9192
                GradeBookBackup::class,
9193
                Link::class,
9194
                LinkCategory::class,
9195
                Quiz::class,
9196
                QuizQuestion::class,
9197
                QuizQuestionOption::class,
9198
                ScormDocument::class,
9199
                Survey::class,
9200
                SurveyInvitation::class,
9201
                SurveyQuestion::class,
9202
                Thematic::class,
9203
                ToolIntro::class,
9204
                Wiki::class,
9205
                Work::class,
9206
                stdClass::class,
9207
            ];
9208
            break;
9209
        case 'not_allowed_classes':
9210
        default:
9211
            $allowedClasses = false;
9212
    }
9213
9214
    if ($ignoreErrors) {
9215
        return @Unserialize::unserialize(
9216
            $serialized,
9217
            ['allowed_classes' => $allowedClasses]
9218
        );
9219
    }
9220
9221
    return Unserialize::unserialize(
9222
        $serialized,
9223
        ['allowed_classes' => $allowedClasses]
9224
    );
9225
}
9226
9227
/**
9228
 * @param string $template
9229
 *
9230
 * @return string
9231
 */
9232
function api_find_template($template)
9233
{
9234
    return Template::findTemplateFilePath($template);
9235
}
9236
9237
/**
9238
 * @return array
9239
 */
9240
function api_get_language_list_for_flag()
9241
{
9242
    $table = Database::get_main_table(TABLE_MAIN_LANGUAGE);
9243
    $sql = "SELECT english_name, isocode FROM $table
9244
            ORDER BY original_name ASC";
9245
    static $languages = [];
9246
    if (empty($languages)) {
9247
        $result = Database::query($sql);
9248
        while ($row = Database::fetch_array($result)) {
9249
            $languages[$row['english_name']] = $row['isocode'];
9250
        }
9251
        $languages['english'] = 'gb';
9252
    }
9253
9254
    return $languages;
9255
}
9256
9257
/**
9258
 * @param string $name
9259
 *
9260
 * @return \ZipStream\ZipStream
9261
 */
9262
function api_create_zip($name)
9263
{
9264
    $zipStreamOptions = new \ZipStream\Option\Archive();
9265
    $zipStreamOptions->setSendHttpHeaders(true);
9266
    $zipStreamOptions->setContentDisposition('attachment');
9267
    $zipStreamOptions->setContentType('application/x-zip');
9268
9269
    $zip = new \ZipStream\ZipStream($name, $zipStreamOptions);
9270
9271
    return $zip;
9272
}
9273
9274
/**
9275
 * @return string
9276
 */
9277
function api_get_language_translate_html()
9278
{
9279
    $translate = api_get_configuration_value('translate_html');
9280
9281
    if (!$translate) {
9282
        return '';
9283
    }
9284
9285
    $languageList = api_get_languages();
9286
    $hideAll = '';
9287
    foreach ($languageList['all'] as $language) {
9288
        $hideAll .= '
9289
        $("span:lang('.$language['isocode'].')").filter(
9290
            function(e, val) {
9291
                // Only find the spans if they have set the lang
9292
                if ($(this).attr("lang") == null) {
9293
                    return false;
9294
                }
9295
9296
                // Ignore ckeditor classes
9297
                return !this.className.match(/cke(.*)/);
9298
        }).hide();'."\n";
9299
    }
9300
9301
    $userInfo = api_get_user_info();
9302
    $languageId = api_get_language_id($userInfo['language']);
9303
    $languageInfo = api_get_language_info($languageId);
9304
    $isoCode = 'en';
9305
9306
    if (!empty($languageInfo)) {
9307
        $isoCode = $languageInfo['isocode'];
9308
    }
9309
9310
    return '
9311
            $(function() {
9312
                '.$hideAll.'
9313
                var defaultLanguageFromUser = "'.$isoCode.'";
9314
9315
                $("span:lang('.$isoCode.')").filter(
9316
                    function() {
9317
                        // Ignore ckeditor classes
9318
                        return !this.className.match(/cke(.*)/);
9319
                }).show();
9320
9321
                var defaultLanguage = "";
9322
                var langFromUserFound = false;
9323
9324
                $(this).find("span").filter(
9325
                    function() {
9326
                        // Ignore ckeditor classes
9327
                        return !this.className.match(/cke(.*)/);
9328
                }).each(function() {
9329
                    defaultLanguage = $(this).attr("lang");
9330
                    if (defaultLanguage) {
9331
                        $(this).before().next("br").remove();
9332
                        if (defaultLanguageFromUser == defaultLanguage) {
9333
                            langFromUserFound = true;
9334
                        }
9335
                    }
9336
                });
9337
9338
                // Show default language
9339
                if (langFromUserFound == false && defaultLanguage) {
9340
                    $("span:lang("+defaultLanguage+")").filter(
9341
                    function() {
9342
                            // Ignore ckeditor classes
9343
                            return !this.className.match(/cke(.*)/);
9344
                    }).show();
9345
                }
9346
            });
9347
    ';
9348
}
9349