Completed
Push — master ( 73cb1f...8d952e )
by Julito
33:13
created

api.lib.php ➔ api_not_allowed()   D

Complexity

Conditions 32
Paths 2

Size

Total Lines 194
Code Lines 128

Duplication

Lines 15
Ratio 7.73 %

Importance

Changes 0
Metric Value
cc 32
eloc 128
nc 2
nop 2
dl 15
loc 194
rs 4.3721
c 0
b 0
f 0

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 ChamiloSession as Session;
5
use Chamilo\CourseBundle\Entity\CItemProperty;
6
use Symfony\Component\Validator\Constraints as Assert;
7
use Chamilo\UserBundle\Entity\User;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, User.

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

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

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

// Bar.php
namespace OtherDir;

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

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

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

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

// Bar.php
namespace OtherDir;

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

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

Let’s take a look at these examples:

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

// More likely intended return: true/false
return 0 === ($foo & 4);
Loading history...
1075
            isset($course_info['registration_code']) &&
1076
            !empty($course_info['registration_code'])
1077
        ) {
1078
            $is_visible = false;
1079
        }
1080
    }
1081
1082
    // Check session visibility
1083
    $session_id = api_get_session_id();
1084
1085
    if (!empty($session_id)) {
1086
        //$is_allowed_in_course was set in local.inc.php
1087
        if (!$is_allowed_in_course) {
1088
            $is_visible = false;
1089
        }
1090
    }
1091
1092
    if (!$is_visible) {
1093
        api_not_allowed($print_headers);
1094
        return false;
1095
    }
1096
    return true;
1097
}
1098
1099
/**
1100
 * Function used to protect an admin script.
1101
 *
1102
 * The function blocks access when the user has no platform admin rights
1103
 * with an error message printed on default output
1104
 * @param bool Whether to allow session admins as well
1105
 * @param bool Whether to allow HR directors as well
1106
 * @param string An optional message (already passed through get_lang)
1107
 * @return bool True if user is allowed, false otherwise.
1108
 * The function also outputs an error message in case not allowed
1109
 * @author Roan Embrechts (original author)
1110
 */
1111
function api_protect_admin_script($allow_sessions_admins = false, $allow_drh = false, $message = null)
1112
{
1113
    if (!api_is_platform_admin($allow_sessions_admins, $allow_drh)) {
1114
        api_not_allowed(true, $message);
1115
        return false;
1116
    }
1117
    return true;
1118
}
1119
1120
/**
1121
 * Function used to protect a teacher script.
1122
 * The function blocks access when the user has no teacher rights.
1123
 *
1124
 * @author Yoselyn Castillo
1125
 */
1126
function api_protect_teacher_script($allow_sessions_admins = false)
1127
{
1128
    if (!api_is_allowed_to_edit()) {
1129
        api_not_allowed(true);
1130
        return false;
1131
    }
1132
    return true;
1133
}
1134
1135
/**
1136
 * Function used to prevent anonymous users from accessing a script.
1137
 * @param bool|true $printHeaders
1138
 * @author Roan Embrechts
1139
 *
1140
 * @return bool
1141
 */
1142
function api_block_anonymous_users($printHeaders = true)
1143
{
1144
    $user = api_get_user_info();
1145 View Code Duplication
    if (!(isset($user['user_id']) && $user['user_id']) || api_is_anonymous($user['user_id'], true)) {
1146
        api_not_allowed($printHeaders);
1147
        return false;
1148
    }
1149
1150
    return true;
1151
}
1152
1153
/**
1154
 * @return array with the navigator name and version
1155
 */
1156
function api_get_navigator() {
1157
    $navigator = 'Unknown';
1158
    $version = 0;
1159
1160
    if (!isset($_SERVER['HTTP_USER_AGENT'])) {
1161
        return array('name' => 'Unknown', 'version' => '0.0.0');
1162
    }
1163
1164
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') !== false) {
1165
        $navigator = 'Opera';
1166
        list (, $version) = explode('Opera', $_SERVER['HTTP_USER_AGENT']);
1167 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {
1168
        $navigator = 'Internet Explorer';
1169
        list (, $version) = explode('MSIE', $_SERVER['HTTP_USER_AGENT']);
1170
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome') !== false) {
1171
        $navigator = 'Chrome';
1172
        list (, $version) = explode('Chrome', $_SERVER['HTTP_USER_AGENT']);
1173 View Code Duplication
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'safari') !== false) {
1174
        $navigator = 'Safari';
1175
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1176
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Gecko') !== false) {
1177
        $navigator = 'Mozilla';
1178
        list (, $version) = explode('; rv:', $_SERVER['HTTP_USER_AGENT']);
1179 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Netscape') !== false) {
1180
        $navigator = 'Netscape';
1181
        list (, $version) = explode('Netscape', $_SERVER['HTTP_USER_AGENT']);
1182
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Konqueror') !== false) {
1183
        $navigator = 'Konqueror';
1184
        list (, $version) = explode('Konqueror', $_SERVER['HTTP_USER_AGENT']);
1185 View Code Duplication
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'applewebkit') !== false) {
1186
        $navigator = 'AppleWebKit';
1187
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1188
    }
1189
    $version = str_replace('/', '', $version);
1190
    if (strpos($version, '.') === false) {
1191
        $version = number_format(doubleval($version), 1);
1192
    }
1193
    $return = array('name' => $navigator, 'version' => $version);
1194
    return $return;
1195
}
1196
1197
/**
1198
 * @return True if user self registration is allowed, false otherwise.
1199
 */
1200
function api_is_self_registration_allowed()
1201
{
1202
    return isset($GLOBALS['allowSelfReg']) ? $GLOBALS['allowSelfReg'] : false;
1203
}
1204
1205
/**
1206
 * This function returns the id of the user which is stored in the $_user array.
1207
 *
1208
 * example: The function can be used to check if a user is logged in
1209
 *          if (api_get_user_id())
1210
 * @return integer the id of the current user, 0 if is empty
1211
 */
1212
function api_get_user_id()
1213
{
1214
    $userInfo = Session::read('_user');
1215
    if ($userInfo && isset($userInfo['user_id'])) {
1216
        return $userInfo['user_id'];
1217
    }
1218
    return 0;
1219
}
1220
1221
/**
1222
 * Gets the list of courses a specific user is subscribed to
1223
 * @param int       User ID
1224
 * @param boolean   $fetch_session Whether to get session courses or not - NOT YET IMPLEMENTED
1225
 * @return array    Array of courses in the form [0]=>('code'=>xxx,'db'=>xxx,'dir'=>xxx,'status'=>d)
1226
 */
1227
function api_get_user_courses($userid, $fetch_session = true)
1228
{
1229
    // Get out if not integer
1230
    if ($userid != strval(intval($userid))) {
1231
        return array();
1232
    }
1233
1234
    $t_course = Database::get_main_table(TABLE_MAIN_COURSE);
1235
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1236
1237
    $sql = "SELECT cc.id as real_id, cc.code code, cc.directory dir, cu.status status
1238
            FROM    $t_course       cc,
1239
                    $t_course_user   cu
1240
            WHERE
1241
                cc.id = cu.c_id AND
1242
                cu.user_id = '".$userid."' AND
1243
                cu.relation_type<>".COURSE_RELATION_TYPE_RRHH." ";
1244
    $result = Database::query($sql);
1245
    if ($result === false) {
1246
        return array();
1247
    }
1248
1249
    $courses = array();
1250
    while ($row = Database::fetch_array($result)) {
1251
        // we only need the database name of the course
1252
        $courses[] = $row;
1253
    }
1254
1255
    return $courses;
1256
}
1257
1258
/**
1259
 * Formats user information into a standard array
1260
 * This function should be only used inside api_get_user_info()
1261
 *
1262
 * @param array Non-standard user array
1263
 * @param bool $add_password
1264
 *
1265
 * @return array Standard user array
1266
 */
1267
function _api_format_user($user, $add_password = false)
1268
{
1269
    $result = array();
1270
1271
    $firstname = null;
1272
    $lastname = null;
1273
    if (isset($user['firstname']) && isset($user['lastname'])) {
1274
        $firstname = $user['firstname'];
1275
        $lastname = $user['lastname'];
1276
    } elseif (isset($user['firstName']) && isset($user['lastName'])) {
1277
        $firstname = isset($user['firstName']) ? $user['firstName'] : null;
1278
        $lastname = isset($user['lastName']) ? $user['lastName'] : null;
1279
    }
1280
1281
    $result['complete_name'] = api_get_person_name($firstname, $lastname);
1282
1283
    $result['complete_name_with_username'] = $result['complete_name'];
1284
1285
    if (!empty($user['username'])) {
1286
        $result['complete_name_with_username'] = $result['complete_name'].' ('.$user['username'].')';
1287
    }
1288
1289
    $result['firstname'] = $firstname;
1290
    $result['lastname'] = $lastname;
1291
1292
    // Kept for historical reasons
1293
    $result['firstName'] = $firstname;
1294
    $result['lastName'] = $lastname;
1295
1296
    $attributes = array(
1297
        'phone',
1298
        'address',
1299
        'picture_uri',
1300
        'official_code',
1301
        'status',
1302
        'active',
1303
        'auth_source',
1304
        'username',
1305
        'theme',
1306
        'language',
1307
        'creator_id',
1308
        'registration_date',
1309
        'hr_dept_id',
1310
        'expiration_date',
1311
        'last_login'
1312
    );
1313
    if (api_get_setting('extended_profile') === 'true') {
1314
        $attributes[] = 'competences';
1315
        $attributes[] = 'diplomas';
1316
        $attributes[] = 'teach';
1317
        $attributes[] = 'openarea';
1318
    }
1319
1320
    foreach ($attributes as $attribute) {
1321
        $result[$attribute] = isset($user[$attribute]) ? $user[$attribute] : null;
1322
    }
1323
1324
    if (isset($user['email'])) {
1325
        $result['mail'] = isset($user['email']) ? $user['email'] : null;
1326
        $result['email'] = isset($user['email'])? $user['email'] : null;
1327
    } else {
1328
        $result['mail'] = isset($user['mail']) ? $user['mail'] : null;
1329
        $result['email'] = isset($user['mail'])? $user['mail'] : null;
1330
    }
1331
    $user_id = intval($user['user_id']);
1332
    // Maintain the user_id index for backwards compatibility
1333
    $result['user_id'] = $result['id'] = $user_id;
1334
    $result['last_login'] = $user['last_login'];
1335
1336
    // Getting user avatar.
1337
    $originalFile = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_ORIGINAL, null, $result);
1338
    $smallFile = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_SMALL, null, $result);
1339
    $mediumFile = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_MEDIUM, null, $result);
1340
1341
    $result['avatar'] = $originalFile;
1342
    $avatarString = explode('?', $originalFile);
1343
    $result['avatar_no_query'] = reset($avatarString);
1344
    $result['avatar_small'] = $smallFile;
1345
    $result['avatar_medium'] = $mediumFile;
1346
1347
    if (isset($user['user_is_online'])) {
1348
        $result['user_is_online'] = $user['user_is_online'] == true ? 1 : 0;
1349
    }
1350
    if (isset($user['user_is_online_in_chat'])) {
1351
        $result['user_is_online_in_chat'] = intval($user['user_is_online_in_chat']);
1352
    }
1353
1354
    if ($add_password) {
1355
        $result['password'] = $user['password'];
1356
    }
1357
1358
    if (isset($result['profile_completed'])) {
1359
        $result['profile_completed'] = $user['profile_completed'];
1360
    }
1361
1362
    $result['profile_url'] = api_get_path(WEB_CODE_PATH).'social/profile.php?u='.$user_id;
1363
1364
    if (isset($user['extra'])) {
1365
        $result['extra'] = $user['extra'];
1366
    }
1367
1368
    return $result;
1369
}
1370
1371
/**
1372
 * Finds all the information about a user.
1373
 * If no parameter is passed you find all the information about the current user.
1374
 * @param int  $user_id
1375
 * @param bool $checkIfUserOnline
1376
 * @param bool $showPassword
1377
 * @param bool $loadExtraData
1378
 * @param bool $loadOnlyVisibleExtraData Get the user extra fields that are visible
1379
 * @return array $user_info user_id, lastname, firstname, username, email, etc
1380
 * @author Patrick Cool <[email protected]>
1381
 * @author Julio Montoya
1382
 * @version 21 September 2004
1383
 */
1384
function api_get_user_info(
1385
    $user_id = 0,
1386
    $checkIfUserOnline = false,
1387
    $showPassword = false,
1388
    $loadExtraData = false,
1389
    $loadOnlyVisibleExtraData = false
1390
) {
1391
    if (empty($user_id)) {
1392
        $userFromSession = Session::read('_user');
1393
        if (isset($userFromSession)) {
1394
            return _api_format_user($userFromSession);
1395
        }
1396
1397
        return false;
1398
    }
1399
1400
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1401
            WHERE id='".intval($user_id)."'";
1402
    $result = Database::query($sql);
1403
    if (Database::num_rows($result) > 0) {
1404
        $result_array = Database::fetch_array($result);
1405
        if ($checkIfUserOnline) {
1406
            $use_status_in_platform = user_is_online($user_id);
1407
1408
            $result_array['user_is_online'] = $use_status_in_platform;
1409
            $user_online_in_chat = 0;
1410
1411
            if ($use_status_in_platform) {
1412
                $user_status = UserManager::get_extra_user_data_by_field(
1413
                    $user_id,
1414
                    'user_chat_status',
1415
                    false,
1416
                    true
1417
                );
1418
                if (intval($user_status['user_chat_status']) == 1) {
1419
                    $user_online_in_chat = 1;
1420
                }
1421
            }
1422
            $result_array['user_is_online_in_chat'] = $user_online_in_chat;
1423
        }
1424
1425
        if ($loadExtraData) {
1426
            $fieldValue = new ExtraFieldValue('user');
1427
1428
            $result_array['extra'] = $fieldValue->getAllValuesForAnItem(
1429
                $user_id,
1430
                $loadOnlyVisibleExtraData
1431
            );
1432
        }
1433
        $user = _api_format_user($result_array, $showPassword);
1434
1435
        return $user;
1436
    }
1437
    return false;
1438
}
1439
1440
/**
1441
 * @param int $userId
1442
 * @return User
1443
 */
1444
function api_get_user_entity($userId)
1445
{
1446
    /** @var \Chamilo\UserBundle\Repository\UserRepository $repo */
1447
    $repo = Database::getManager()->getRepository('ChamiloUserBundle:User');
1448
1449
    return $repo->find($userId);
1450
}
1451
1452
/**
1453
 * @param int $courseId
1454
 *
1455
 * @return Course
1456
 */
1457
function api_get_user_course_entity($courseId = null)
1458
{
1459
    if (empty($courseId)) {
1460
        $courseId = api_get_course_int_id();
1461
    }
1462
    return CourseManager::getManager()->find($courseId);
1463
}
1464
1465
/**
1466
 * Finds all the information about a user from username instead of user id
1467
 * @param string $username
1468
 * @return array $user_info array user_id, lastname, firstname, username, email
1469
 * @author Yannick Warnier <[email protected]>
1470
 */
1471 View Code Duplication
function api_get_user_info_from_username($username = '')
1472
{
1473
    if (empty($username)) {
1474
        return false;
1475
    }
1476
    $username = trim($username);
1477
1478
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1479
            WHERE username='".Database::escape_string($username)."'";
1480
    $result = Database::query($sql);
1481
    if (Database::num_rows($result) > 0) {
1482
        $result_array = Database::fetch_array($result);
1483
        return _api_format_user($result_array);
1484
    }
1485
    return false;
1486
}
1487
1488
/**
1489
 * Get first user with an email
1490
 * @param string $email
1491
 * @return array|bool
1492
 */
1493 View Code Duplication
function api_get_user_info_from_email($email = '')
1494
{
1495
    if (empty($email)) {
1496
        return false;
1497
    }
1498
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1499
            WHERE email ='".Database::escape_string($email)."' LIMIT 1";
1500
    $result = Database::query($sql);
1501
    if (Database::num_rows($result) > 0) {
1502
        $result_array = Database::fetch_array($result);
1503
        return _api_format_user($result_array);
1504
    }
1505
1506
    return false;
1507
}
1508
1509
/**
1510
 * @return string
1511
 */
1512
function api_get_course_id()
1513
{
1514
    return Session::read('_cid', null);
1515
}
1516
1517
/**
1518
 * Returns the current course id (integer)
1519
 * @param   string  $code   Optional course code
1520
 * @return int
1521
 */
1522
function api_get_course_int_id($code = null)
1523
{
1524 View Code Duplication
    if (!empty($code)) {
1525
        $code = Database::escape_string($code);
1526
        $row = Database::select(
1527
            'id',
1528
            Database::get_main_table(TABLE_MAIN_COURSE),
1529
            array('where'=> array('code = ?' => array($code))),
1530
            'first'
1531
        );
1532
1533
        if (is_array($row) && isset($row['id'])) {
1534
            return $row['id'];
1535
        } else {
1536
            return false;
1537
        }
1538
    }
1539
    return Session::read('_real_cid', 0);
1540
}
1541
1542
/**
1543
 * Returns the current course directory
1544
 *
1545
 * This function relies on api_get_course_info()
1546
 * @param string    The course code - optional (takes it from session if not given)
1547
 * @return string   The directory where the course is located inside the Chamilo "courses" directory
1548
 * @author Yannick Warnier <[email protected]>
1549
 */
1550
function api_get_course_path($course_code = null)
1551
{
1552
    $info = !empty($course_code) ? api_get_course_info($course_code) : api_get_course_info();
1553
    return $info['path'];
1554
}
1555
1556
/**
1557
 * Gets a course setting from the current course_setting table. Try always using integer values.
1558
 * @param string    The name of the setting we want from the table
1559
 * @param string    Optional: course code
1560
 * @param string $setting_name
1561
 * @return mixed    The value of that setting in that table. Return -1 if not found.
1562
 */
1563
function api_get_course_setting($setting_name, $course_code = null)
1564
{
1565
    $course_info = api_get_course_info($course_code);
1566
    $table = Database::get_course_table(TABLE_COURSE_SETTING);
1567
    $setting_name = Database::escape_string($setting_name);
1568
    if (!empty($course_info['real_id']) && !empty($setting_name)) {
1569
        $sql = "SELECT value FROM $table
1570
                WHERE c_id = {$course_info['real_id']} AND variable = '$setting_name'";
1571
        $res = Database::query($sql);
1572
        if (Database::num_rows($res) > 0) {
1573
            $row = Database::fetch_array($res);
1574
            return $row['value'];
1575
        }
1576
    }
1577
    return -1;
1578
}
1579
1580
/**
1581
 * Gets an anonymous user ID
1582
 *
1583
 * For some tools that need tracking, like the learnpath tool, it is necessary
1584
 * to have a usable user-id to enable some kind of tracking, even if not
1585
 * perfect. An anonymous ID is taken from the users table by looking for a
1586
 * status of "6" (anonymous).
1587
 * @return int  User ID of the anonymous user, or O if no anonymous user found
1588
 */
1589 View Code Duplication
function api_get_anonymous_id()
1590
{
1591
    $table = Database::get_main_table(TABLE_MAIN_USER);
1592
    $sql = "SELECT user_id FROM $table WHERE status = ".ANONYMOUS;
1593
    $res = Database::query($sql);
1594
    if (Database::num_rows($res) > 0) {
1595
        $row = Database::fetch_array($res);
1596
        return $row['user_id'];
1597
    }
1598
1599
    // No anonymous user was found.
1600
    return 0;
1601
}
1602
1603
/**
1604
 * @param string $courseCode
1605
 * @param int $sessionId
1606
 * @param int $groupId
1607
 * @return string
1608
 */
1609
function api_get_cidreq_params($courseCode, $sessionId = 0, $groupId = 0)
1610
{
1611
    $courseCode = !empty($courseCode) ? htmlspecialchars($courseCode) : '';
1612
    $sessionId = !empty($sessionId) ? (int) $sessionId : 0;
1613
    $groupId = !empty($groupId) ? (int) $groupId : 0;
1614
1615
    $url = 'cidReq='.$courseCode;
1616
    $url .= '&id_session='.$sessionId;
1617
    $url .= '&gidReq='.$groupId;
1618
1619
    return $url;
1620
}
1621
1622
/**
1623
 * Returns the current course url part including session, group, and gradebook params
1624
 *
1625
 * @param bool $addSessionId
1626
 * @param bool $addGroupId
1627
 * @param string $origin
1628
 *
1629
 * @return  string  Course & session references to add to a URL
1630
 *
1631
 */
1632
function api_get_cidreq($addSessionId = true, $addGroupId = true, $origin = '')
1633
{
1634
    $courseCode = api_get_course_id();
1635
    $url = empty($courseCode) ? '' : 'cidReq='.htmlspecialchars($courseCode);
1636
    $origin = empty($origin) ? api_get_origin() : Security::remove_XSS($origin);
1637
1638
    if ($addSessionId) {
1639
        if (!empty($url)) {
1640
            $url .= api_get_session_id() == 0 ? '&id_session=0' : '&id_session='.api_get_session_id();
1641
        }
1642
    }
1643
1644
    if ($addGroupId) {
1645
        if (!empty($url)) {
1646
            $url .= api_get_group_id() == 0 ? '&gidReq=0' : '&gidReq='.api_get_group_id();
1647
        }
1648
    }
1649
1650
    if (!empty($url)) {
1651
        $url .= '&gradebook='.intval(api_is_in_gradebook());
1652
        $url .= '&origin='.$origin;
1653
    }
1654
1655
    return $url;
1656
}
1657
1658
/**
1659
 * get gradebook in session
1660
 */
1661
function api_is_in_gradebook()
1662
{
1663
    return Session::read('in_gradebook', false);
1664
}
1665
1666
/**
1667
 * set gradebook session
1668
 */
1669
function api_set_in_gradebook()
1670
{
1671
    Session::write('in_gradebook', true);
1672
}
1673
1674
/**
1675
 * remove gradebook session
1676
 */
1677
function api_remove_in_gradebook()
1678
{
1679
    Session::erase('in_gradebook');
1680
}
1681
1682
/**
1683
 * Returns the current course info array see api_format_course_array()
1684
 * If the course_code is given, the returned array gives info about that
1685
 * particular course, if none given it gets the course info from the session.
1686
 *
1687
 * @param string $course_code
1688
 * @param bool $strict
1689
 *
1690
 * @return array
1691
 */
1692
function api_get_course_info($course_code = null, $strict = false)
1693
{
1694
    if (!empty($course_code)) {
1695
        $course_code = Database::escape_string($course_code);
1696
        $courseId = api_get_course_int_id($course_code);
1697
1698
        if (empty($courseId)) {
1699
            return array();
1700
        }
1701
1702
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1703
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1704
        $sql = "SELECT
1705
                    course.*,
1706
                    course_category.code faCode,
1707
                    course_category.name faName
1708
                FROM $course_table
1709
                LEFT JOIN $course_cat_table
1710
                ON course.category_code = course_category.code
1711
                WHERE course.id = $courseId";
1712
        $result = Database::query($sql);
1713
        $courseInfo = array();
1714
        if (Database::num_rows($result) > 0) {
1715
            $data = Database::fetch_array($result);
1716
            $courseInfo = api_format_course_array($data);
1717
        }
1718
1719
        return $courseInfo;
1720
    }
1721
1722
    $_course = Session::read('_course');
1723
    if ($_course == '-1') {
1724
        $_course = array();
1725
    }
1726
1727
    return $_course;
1728
}
1729
1730
/**
1731
 * Returns the current course info array.
1732
1733
 * Now if the course_code is given, the returned array gives info about that
1734
 * particular course, not specially the current one.
1735
 * @param int $id Numeric ID of the course
1736
 * @return array The course info as an array formatted by api_format_course_array, including category.name
1737
 */
1738
function api_get_course_info_by_id($id = null)
1739
{
1740
    if (!empty($id)) {
1741
        $id = intval($id);
1742
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1743
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1744
        $sql = "SELECT
1745
                    course.*,
1746
                    course_category.code faCode,
1747
                    course_category.name faName
1748
                FROM $course_table
1749
                LEFT JOIN $course_cat_table
1750
                ON course.category_code =  course_category.code
1751
                WHERE course.id = $id";
1752
        $result = Database::query($sql);
1753
        $_course = array();
1754
        if (Database::num_rows($result) > 0) {
1755
            $course_data = Database::fetch_array($result);
1756
            $_course = api_format_course_array($course_data);
1757
        }
1758
        return $_course;
1759
    }
1760
1761
    global $_course;
1762
    if ($_course == '-1') $_course = array();
1763
    return $_course;
1764
}
1765
1766
/**
1767
 * Reformat the course array (output by api_get_course_info()) in order, mostly,
1768
 * to switch from 'code' to 'id' in the array. This is a legacy feature and is
1769
 * now possibly causing massive confusion as a new "id" field has been added to
1770
 * the course table in 1.9.0.
1771
 * @param $course_data
1772
 * @return array
1773
 * @todo eradicate the false "id"=code field of the $_course array and use the int id
1774
 */
1775
function api_format_course_array($course_data)
1776
{
1777
    if (empty($course_data)) {
1778
        return array();
1779
    }
1780
1781
    $_course = array();
1782
    $_course['id'] = $course_data['code'];
1783
    $_course['real_id'] = $course_data['id'];
1784
1785
    // Added
1786
    $_course['code'] = $course_data['code'];
1787
    $_course['name'] = $course_data['title'];
1788
    $_course['title'] = $course_data['title'];
1789
    $_course['official_code'] = $course_data['visual_code'];
1790
    $_course['visual_code'] = $course_data['visual_code'];
1791
    $_course['sysCode'] = $course_data['code'];
1792
    $_course['path'] = $course_data['directory']; // Use as key in path.
1793
    $_course['directory'] = $course_data['directory'];
1794
    $_course['creation_date'] = $course_data['creation_date'];
1795
    $_course['titular'] = $course_data['tutor_name'];
1796
    $_course['language'] = $course_data['course_language'];
1797
    $_course['extLink']['url'] = $course_data['department_url'];
1798
    $_course['extLink']['name'] = $course_data['department_name'];
1799
    $_course['categoryCode'] = $course_data['faCode'];
1800
    $_course['categoryName'] = $course_data['faName'];
1801
    $_course['visibility'] = $course_data['visibility'];
1802
    $_course['subscribe_allowed'] = $course_data['subscribe'];
1803
    $_course['subscribe'] = $course_data['subscribe'];
1804
    $_course['unsubscribe'] = $course_data['unsubscribe'];
1805
    $_course['course_language'] = $course_data['course_language'];
1806
    $_course['activate_legal'] = isset($course_data['activate_legal']) ? $course_data['activate_legal'] : false;
1807
    $_course['legal'] = $course_data['legal'];
1808
    $_course['show_score'] = $course_data['show_score']; //used in the work tool
1809
    $_course['department_name'] = $course_data['department_name'];
1810
    $_course['department_url'] = $course_data['department_url'];
1811
1812
    // Course password
1813
    $_course['registration_code'] = !empty($course_data['registration_code']) ? sha1($course_data['registration_code']) : null;
1814
    $_course['disk_quota'] = $course_data['disk_quota'];
1815
    $_course['course_public_url'] = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/index.php';
1816
1817
    if (array_key_exists('add_teachers_to_sessions_courses', $course_data)) {
1818
        $_course['add_teachers_to_sessions_courses'] = $course_data['add_teachers_to_sessions_courses'];
1819
    }
1820
1821
    if (file_exists(api_get_path(SYS_COURSE_PATH).$course_data['directory'].'/course-pic85x85.png')) {
1822
        $url_image = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/course-pic85x85.png';
1823
    } else {
1824
        $url_image = Display::return_icon('course.png', null, null, ICON_SIZE_BIG, null, true, false);
1825
    }
1826
    $_course['course_image'] = $url_image;
1827
1828
    if (file_exists(api_get_path(SYS_COURSE_PATH).$course_data['directory'].'/course-pic.png')) {
1829
        $url_image = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/course-pic.png';
1830
    } else {
1831
        $url_image = Display::returnIconPath('session_default.png');
1832
    }
1833
    $_course['course_image_large'] = $url_image;
1834
1835
    $_course['extra_fields'] = isset($course_data['extra_fields']) ? $course_data['extra_fields'] : array();
1836
    $_course['settings'] = isset($course_data['settings']) ? $course_data['settings'] : array();
1837
    $_course['teacher_list'] = isset($course_data['teacher_list']) ? $course_data['teacher_list'] : array();
1838
    $_course['teacher_list_formatted'] = isset($course_data['teacher_list_formatted']) ? $course_data['teacher_list_formatted'] : array();
1839
1840
    return $_course;
1841
}
1842
1843
/**
1844
 * Add a parameter to the existing URL. If this parameter already exists,
1845
 * just replace it with the new value
1846
 * @param   string  The URL
1847
 * @param   string  param=value string
1848
 * @param   boolean Whether to filter XSS or not
1849
 * @return  string  The URL with the added parameter
1850
 */
1851
function api_add_url_param($url, $param, $filter_xss = true) {
1852
    if (empty($param)) {
1853
        return $url;
1854
    }
1855
    if (strpos($url, '?') !== false) {
1856
        if ($param[0] != '&') {
1857
            $param = '&'.$param;
1858
        }
1859
        list (, $query_string) = explode('?', $url);
1860
        $param_list1 = explode('&', $param);
1861
        $param_list2 = explode('&', $query_string);
1862
        $param_list1_keys = $param_list1_vals = array();
1863
        foreach ($param_list1 as $key => $enreg) {
1864
            list ($param_list1_keys[$key], $param_list1_vals[$key]) = explode('=', $enreg);
1865
        }
1866
        $param_list1 = array ('keys' => $param_list1_keys, 'vals' => $param_list1_vals);
1867
        foreach ($param_list2 as $enreg) {
1868
            $enreg = explode('=', $enreg);
1869
            $key = array_search($enreg[0], $param_list1['keys']);
1870
            if (!is_null($key) && !is_bool($key)) {
1871
                $url = str_replace($enreg[0].'='.$enreg[1], $enreg[0].'='.$param_list1['vals'][$key], $url);
1872
                $param = str_replace('&'.$enreg[0].'='.$param_list1['vals'][$key], '', $param);
1873
            }
1874
        }
1875
        $url .= $param;
1876
    } else {
1877
        $url = $url.'?'.$param;
1878
    }
1879
    if ($filter_xss === true) {
1880
        $url = Security::remove_XSS(urldecode($url));
1881
    }
1882
    return $url;
1883
}
1884
1885
/**
1886
 * Returns a difficult to guess password.
1887
 * @param int $length the length of the password
1888
 * @return string the generated password
1889
 */
1890
function api_generate_password($length = 8)
1891
{
1892
    $characters = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
1893
    $numbers = '23456789';
1894
1895
    if ($length < 2) {
1896
        $length = 2;
1897
    }
1898
    $password = '';
1899
    for ($i = 0; $i < $length; $i ++) {
1900
        $password .= $characters[rand() % strlen($characters)];
1901
    }
1902
1903
    // At least 2 digits
1904
    for ($i = 0; $i < 2; $i ++) {
1905
        $password .= $numbers[rand() % strlen($numbers)];
1906
    }
1907
1908
    return $password;
1909
}
1910
1911
/**
1912
 * Checks a password to see wether it is OK to use.
1913
 * @param string $password
1914
 * @return boolean if the password is acceptable, false otherwise
1915
 * Notes about what a password "OK to use" is:
1916
 * 1. The password should be at least 5 characters long.
1917
 * 2. Only English letters (uppercase or lowercase, it doesn't matter) and digits are allowed.
1918
 * 3. The password should contain at least 3 letters.
1919
 * 4. It should contain at least 2 digits.
1920
 * 5. It should not contain 3 or more consequent (according to ASCII table) characters.
1921
 */
1922
function api_check_password($password) {
1923
    $password_length = api_strlen($password);
1924
    if ($password_length < 5) {
1925
        return false;
1926
    }
1927
    $password = api_strtolower($password);
1928
    $letters = 0;
1929
    $digits = 0;
1930
    $consequent_characters = 0;
1931
    $previous_character_code = 0;
1932
    for ($i = 0; $i < $password_length; $i ++) {
1933
        $current_character_code = api_ord(api_substr($password, $i, 1));
0 ignored issues
show
Security Bug introduced by
It seems like api_substr($password, $i, 1) targeting api_substr() can also be of type false; however, api_ord() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
1934
        if ($i && abs($current_character_code - $previous_character_code) <= 1) {
1935
            $consequent_characters ++;
1936
            if ($consequent_characters == 3) {
1937
                return false;
1938
            }
1939
        } else {
1940
            $consequent_characters = 1;
1941
        }
1942
        if ($current_character_code >= 97 && $current_character_code <= 122) {
1943
            $letters ++;
1944
        } elseif ($current_character_code >= 48 && $current_character_code <= 57) {
1945
            $digits ++;
1946
        } else {
1947
            return false;
1948
        }
1949
        $previous_character_code = $current_character_code;
1950
    }
1951
    return ($letters >= 3 && $digits >= 2);
1952
}
1953
1954
/**
1955
 * Clears the user ID from the session if it was the anonymous user. Generally
1956
 * used on out-of-tools pages to remove a user ID that could otherwise be used
1957
 * in the wrong context.
1958
 * This function is to be used in conjunction with the api_set_anonymous()
1959
 * function to simulate the user existence in case of an anonymous visit.
1960
 * @param bool      database check switch - passed to api_is_anonymous()
1961
 * @return bool     true if succesfully unregistered, false if not anonymous.
1962
 */
1963
function api_clear_anonymous($db_check = false)
1964
{
1965
    global $_user;
1966
    if (api_is_anonymous($_user['user_id'], $db_check)) {
1967
        unset($_user['user_id']);
1968
        Session::erase('_uid');
1969
        return true;
1970
    }
1971
    return false;
1972
}
1973
1974
/**
1975
 * Returns the status string corresponding to the status code
1976
 * @author Noel Dieschburg
1977
 * @param the int status code
1978
 */
1979
function get_status_from_code($status_code)
1980
{
1981
    switch ($status_code) {
1982
        case STUDENT:
1983
            return get_lang('Student', '');
1984
        case TEACHER:
1985
            return get_lang('Teacher', '');
1986
        case COURSEMANAGER:
1987
            return get_lang('Manager', '');
1988
        case SESSIONADMIN:
1989
            return get_lang('SessionsAdmin', '');
1990
        case DRH:
1991
            return get_lang('Drh', '');
1992
    }
1993
}
1994
1995
/**
1996
 * Sets the current user as anonymous if it hasn't been identified yet. This
1997
 * function should be used inside a tool only. The function api_clear_anonymous()
1998
 * acts in the opposite direction by clearing the anonymous user's data every
1999
 * time we get on a course homepage or on a neutral page (index, admin, my space)
2000
 * @return bool     true if set user as anonymous, false if user was already logged in or anonymous id could not be found
2001
 */
2002
function api_set_anonymous() {
2003
    global $_user;
2004
2005
    if (!empty($_user['user_id'])) {
2006
        return false;
2007
    }
2008
    $user_id = api_get_anonymous_id();
2009
    if ($user_id == 0) {
2010
        return false;
2011
    }
2012
    Session::erase('_user');
2013
    $_user['user_id'] = $user_id;
2014
    $_user['is_anonymous'] = true;
2015
    $GLOBALS['_user'] = $_user;
2016
    Session::write('_user', $_user);
2017
    return true;
2018
}
2019
2020
/**
2021
 * Gets the current Chamilo (not PHP/cookie) session ID
2022
 * @return  int     O if no active session, the session ID otherwise
2023
 */
2024
function api_get_session_id()
2025
{
2026
    return Session::read('id_session', 0);
2027
}
2028
2029
/**
2030
 * Gets the current Chamilo (not social network) group ID
2031
 * @return  int     O if no active session, the session ID otherwise
2032
 */
2033
function api_get_group_id()
2034
{
2035
    return Session::read('_gid', 0);
2036
}
2037
2038
/**
2039
 * Gets the current or given session name
2040
 * @param   int     Session ID (optional)
2041
 * @return  string  The session name, or null if unfound
2042
 */
2043
function api_get_session_name($session_id = 0)
2044
{
2045
    if (empty($session_id)) {
2046
        $session_id = api_get_session_id();
2047
        if (empty($session_id)) {
2048
            return null;
2049
        }
2050
    }
2051
    $t = Database::get_main_table(TABLE_MAIN_SESSION);
2052
    $s = "SELECT name FROM $t WHERE id = ".(int)$session_id;
2053
    $r = Database::query($s);
2054
    $c = Database::num_rows($r);
2055
    if ($c > 0) {
2056
        //technically, there can be only one, but anyway we take the first
2057
        $rec = Database::fetch_array($r);
2058
        return $rec['name'];
2059
    }
2060
    return null;
2061
}
2062
2063
/**
2064
 * Gets the session info by id
2065
 * @param int       Session ID
2066
 * @return array    information of the session
2067
 */
2068
function api_get_session_info($session_id)
2069
{
2070
    return SessionManager::fetch($session_id);
2071
}
2072
2073
/**
2074
 * Gets the session visibility by session id
2075
 * @param int $session_id
2076
 * @param int $courseId
2077
 * @param bool $ignore_visibility_for_admins
2078
 * @return int
2079
 *  0 = session still available,
2080
 *  SESSION_VISIBLE_READ_ONLY = 1,
2081
 *  SESSION_VISIBLE = 2,
2082
 *  SESSION_INVISIBLE = 3
2083
 */
2084
function api_get_session_visibility(
2085
    $session_id,
2086
    $courseId = null,
2087
    $ignore_visibility_for_admins = true
2088
) {
2089
    // Means that the session is still available.
2090
    $visibility = 0;
2091
2092
    if (api_is_platform_admin()) {
2093
        if ($ignore_visibility_for_admins) {
2094
            return SESSION_AVAILABLE;
2095
        }
2096
    }
2097
2098
    $now = time();
2099
    if (!empty($session_id)) {
2100
        $session_id = intval($session_id);
2101
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2102
2103
        $sql = "SELECT * FROM $tbl_session
2104
                WHERE id = $session_id ";
2105
2106
        $result = Database::query($sql);
2107
2108
        if (Database::num_rows($result) > 0) {
2109
            $row = Database::fetch_array($result, 'ASSOC');
2110
            $visibility = $original_visibility = $row['visibility'];
2111
2112
            // I don't care the session visibility.
2113
            if (empty($row['access_start_date']) && empty($row['access_end_date'])) {
2114
                // Session duration per student.
2115
                if (isset($row['duration']) && !empty($row['duration'])) {
2116
                    $duration = $row['duration'] * 24 * 60 * 60;
2117
2118
                    $courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser(
2119
                        $session_id,
2120
                        api_get_user_id()
2121
                    );
2122
2123
                    // If there is a session duration but there is no previous
2124
                    // access by the user, then the session is still available
2125
                    if (count($courseAccess) == 0) {
2126
                        return SESSION_AVAILABLE;
2127
                    }
2128
2129
                    $currentTime = time();
2130
                    $firstAccess = 0;
2131
                    if (isset($courseAccess['login_course_date'])) {
2132
                        $firstAccess = api_strtotime(
2133
                            $courseAccess['login_course_date'],
2134
                            'UTC'
2135
                        );
2136
                    }
2137
                    $userDurationData = SessionManager::getUserSession(
2138
                        api_get_user_id(),
2139
                        $session_id
2140
                    );
2141
                    $userDuration = 0;
2142
                    if (isset($userDurationData['duration'])) {
2143
                        $userDuration = intval($userDurationData['duration']) * 24 * 60 * 60;
2144
                    }
2145
2146
                    $totalDuration = $firstAccess + $duration + $userDuration;
2147
                    if ($totalDuration > $currentTime) {
2148
                        return SESSION_AVAILABLE;
2149
                    } else {
2150
                        return SESSION_INVISIBLE;
2151
                    }
2152
                }
2153
2154
                return SESSION_AVAILABLE;
2155
            } else {
2156
                // If start date was set.
2157
                if (!empty($row['access_start_date'])) {
2158
                    if ($now > api_strtotime($row['access_start_date'], 'UTC')) {
2159
                        $visibility = SESSION_AVAILABLE;
2160
                    } else {
2161
                        $visibility = SESSION_INVISIBLE;
2162
                    }
2163
                }
2164
2165
                // If the end date was set.
2166
                if (!empty($row['access_end_date'])) {
2167
                    // Only if date_start said that it was ok
2168
                    if ($visibility === SESSION_AVAILABLE) {
2169
                        if ($now < api_strtotime($row['access_end_date'], 'UTC')) {
2170
                            // Date still available
2171
                            $visibility = SESSION_AVAILABLE;
2172
                        } else {
2173
                            // Session ends
2174
                            $visibility = $row['visibility'];
2175
                        }
2176
                    }
2177
                }
2178
            }
2179
2180
            /* If I'm a coach the visibility can change in my favor depending in
2181
             the coach dates */
2182
            $isCoach = api_is_coach($session_id, $courseId);
2183
2184
            if ($isCoach) {
2185
                // Test end date.
2186
                if (!empty($row['coach_access_end_date'])) {
2187
                    $endDateCoach = api_strtotime($row['coach_access_end_date'], 'UTC');
2188
2189
                    if ($endDateCoach >= $now) {
2190
                        $visibility = SESSION_AVAILABLE;
2191
                    } else {
2192
                        $visibility = SESSION_INVISIBLE;
2193
                    }
2194
                }
2195
2196
                // Test start date.
2197
                if (!empty($row['coach_access_start_date'])) {
2198
                    $start = api_strtotime($row['coach_access_start_date'], 'UTC');
2199
                    if ($start < $now) {
2200
                        $visibility = SESSION_AVAILABLE;
2201
                    } else {
2202
                        $visibility = SESSION_INVISIBLE;
2203
                    }
2204
                }
2205
            }
2206
        } else {
2207
            $visibility = SESSION_INVISIBLE;
2208
        }
2209
    }
2210
    return $visibility;
2211
}
2212
2213
/**
2214
 * This function returns a (star) session icon if the session is not null and
2215
 * the user is not a student
2216
 * @param int   $session_id
2217
 * @param int   $status_id User status id - if 5 (student), will return empty
2218
 * @return string   Session icon
2219
 */
2220
function api_get_session_image($session_id, $status_id)
2221
{
2222
    $session_id = (int)$session_id;
2223
    $session_img = '';
2224
    if ((int)$status_id != 5) { //check whether is not a student
2225
        if ($session_id > 0) {
2226
            $session_img = "&nbsp;&nbsp;".Display::return_icon(
2227
                'star.png',
2228
                get_lang('SessionSpecificResource'),
2229
                array('align' => 'absmiddle'),
2230
                ICON_SIZE_SMALL
2231
            );
2232
        }
2233
    }
2234
    return $session_img;
2235
}
2236
2237
/**
2238
 * This function add an additional condition according to the session of the course
2239
 * @param int       $session_id session id
2240
 * @param bool      $and optional, true if more than one condition false if the only condition in the query
2241
 * @param bool      $with_base_content optional, true to accept content with session=0 as well, false for strict session condition
2242
 * @return string   condition of the session
2243
 */
2244
function api_get_session_condition(
2245
    $session_id,
2246
    $and = true,
2247
    $with_base_content = false,
2248
    $session_field = "session_id"
2249
) {
2250
    $session_id = intval($session_id);
2251
2252
    if (empty($session_field)) {
2253
        $session_field = "session_id";
2254
    }
2255
    // Condition to show resources by session
2256
    $condition_add = $and ? " AND " : " WHERE ";
2257
2258
    if ($with_base_content) {
2259
        $condition_session = $condition_add." ( $session_field = $session_id OR $session_field = 0 OR $session_field IS NULL) ";
2260
    } else {
2261
        if (empty($session_id)) {
2262
            $condition_session = $condition_add." ($session_field = $session_id OR $session_field IS NULL)";
2263
        } else {
2264
            $condition_session = $condition_add." $session_field = $session_id ";
2265
        }
2266
    }
2267
    return $condition_session;
2268
}
2269
2270
/**
2271
 * Returns the value of a setting from the web-adjustable admin config settings.
2272
 *
2273
 * WARNING true/false are stored as string, so when comparing you need to check e.g.
2274
 * if (api_get_setting('course.show_navigation_menu') == 'true') //CORRECT
2275
 * instead of
2276
 * if (api_get_setting('course.show_navigation_menu') == true) //INCORRECT
2277
 * @param string    $variable The variable name
2278
 * @return string
2279
 *
2280
 * @author Julio Montoya
2281
 */
2282
function api_get_setting($variable)
2283
{
2284
    $variable = trim($variable);
2285
2286
    switch ($variable) {
2287 View Code Duplication
        case 'header_extra_content':
2288
            $filename = api_get_path(SYS_PATH).api_get_home_path().'header_extra_content.txt';
2289
            if (file_exists($filename)) {
2290
                $value = file_get_contents($filename);
2291
                    return $value ;
2292
            } else {
2293
                return '';
2294
            }
2295
            break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

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

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

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

    return false;
}

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

Loading history...
2296 View Code Duplication
        case 'footer_extra_content':
2297
            $filename = api_get_path(SYS_PATH).api_get_home_path().'footer_extra_content.txt';
2298
            if (file_exists($filename)) {
2299
                $value = file_get_contents($filename);
2300
                    return $value ;
2301
            } else {
2302
                return '';
2303
            }
2304
            break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

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

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

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

    return false;
}

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

Loading history...
2305
        case 'server_type':
2306
            $test = ['dev', 'test'];
2307
            $environment = Container::getEnvironment();
2308
            if (in_array($environment, $test)) {
2309
                return 'test';
2310
            }
2311
            return 'prod';
2312
        case 'stylesheets':
2313
            $variable = 'platform.theme';
2314
            break;
2315
        default:
2316
            return Container::getSettingsManager()->getSetting($variable);
2317
    }
2318
}
2319
2320
/**
2321
 * @param string $plugin
2322
 * @param string $variable
2323
 * @return string
2324
 */
2325
function api_get_plugin_setting($plugin, $variable)
2326
{
2327
    $variableName = $plugin.'_'.$variable;
2328
    $result = api_get_setting($variableName);
2329
    if (isset($result[$plugin])) {
2330
        return $result[$plugin];
2331
    }
2332
2333
    return null;
2334
}
2335
2336
/**
2337
 * Returns the value of a setting from the web-adjustable admin config settings.
2338
 **/
2339
function api_get_settings_params($params) {
2340
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2341
    $result = Database::select('*', $table, array('where' => $params));
2342
    return $result;
2343
}
2344
2345
function api_get_settings_params_simple($params) {
2346
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2347
    $result = Database::select('*', $table, array('where' => $params), 'one');
2348
    return $result;
2349
}
2350
2351
/**
2352
 * Returns the value of a setting from the web-adjustable admin config settings.
2353
 **/
2354
function api_delete_settings_params($params) {
2355
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2356
    $result = Database::delete($table, $params);
2357
    return $result;
2358
}
2359
2360
/**
2361
 * Returns an escaped version of $_SERVER['PHP_SELF'] to avoid XSS injection
2362
 * @return string   Escaped version of $_SERVER['PHP_SELF']
2363
 */
2364
function api_get_self() {
2365
    return htmlentities($_SERVER['PHP_SELF']);
2366
}
2367
2368
/**
2369
 * Checks whether current user is a platform administrator
2370
 * @param boolean $allowSessionAdmins Whether session admins should be considered admins or not
2371
 * @param boolean $allowDrh Whether HR directors should be considered admins or not
2372
 * @return boolean True if the user has platform admin rights,
2373
 * false otherwise.
2374
 * @see usermanager::is_admin(user_id) for a user-id specific function
2375
 */
2376
function api_is_platform_admin($allowSessionAdmins = false, $allowDrh = false)
2377
{
2378
    $checker = Container::getAuthorizationChecker();
2379
    if ($checker) {
2380
        if ($checker->isGranted('ROLE_ADMIN')) {
2381
        return true;
2382
    }
2383
        if ($allow_sessions_admins) {
0 ignored issues
show
Bug introduced by
The variable $allow_sessions_admins does not exist. Did you forget to declare it?

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

Loading history...
2384
            if ($checker->isGranted('ROLE_SESSION_MANAGER')) {
2385
                return true;
2386
            }
2387
        }
2388
    }
2389
2390
    return false;
2391
2392
    $isPlatformAdmin = Session::read('is_platformAdmin');
0 ignored issues
show
Unused Code introduced by
$isPlatformAdmin = \Cham...ad('is_platformAdmin'); does not seem to be reachable.

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

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

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

    return false;
}

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

Loading history...
2393
    if ($isPlatformAdmin) {
2394
        return true;
2395
    }
2396
    $_user = api_get_user_info();
2397
2398
    return
2399
        isset($_user['status']) &&
2400
        (
2401
            ($allow_sessions_admins && $_user['status'] == SESSIONADMIN) ||
2402
            ($allow_drh && $_user['status'] == DRH)
2403
        );
2404
}
2405
2406
/**
2407
 * Checks whether the user given as user id is in the admin table.
2408
 * @param int $user_id. If none provided, will use current user
0 ignored issues
show
Documentation introduced by
There is no parameter named $user_id.. Did you maybe mean $user_id?

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

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

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

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

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

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

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

Loading history...
2938
            );
2939
2940
            $courseIsVisible = !in_array(
2941
                $course['visibility'],
2942
                $closedVisibilityList
2943
            );
2944
            if ($courseIsVisible === false || $sessionCourseVisibility == SESSION_INVISIBLE) {
2945
                $blockedCourseCount++;
2946
            }
2947
        }
2948
2949
        // If all courses are blocked then no show in the list.
2950
        if ($blockedCourseCount === count($courseList)) {
2951
            $visibility = SESSION_INVISIBLE;
2952
        } else {
2953
            $visibility = SESSION_VISIBLE;
2954
        }
2955
    }
2956
2957
    switch ($visibility) {
2958
        case SESSION_VISIBLE_READ_ONLY:
2959
        case SESSION_VISIBLE:
2960
        case SESSION_AVAILABLE:
2961
            return true;
2962
            break;
2963
        case SESSION_INVISIBLE:
2964
            return false;
2965
    }
2966
2967
    return false;
2968
}
2969
2970
/**
2971
* Checks if a student can edit contents in a session depending
2972
* on the session visibility
2973
* @param bool $tutor  Whether to check if the user has the tutor role
2974
* @param bool  $coach Whether to check if the user has the coach role
2975
* @return boolean true: the user has the rights to edit, false: he does not
2976
*/
2977
function api_is_allowed_to_session_edit($tutor = false, $coach = false)
2978
{
2979
    if (api_is_allowed_to_edit($tutor, $coach)) {
2980
        // If I'm a teacher, I will return true in order to not affect the normal behaviour of Chamilo tools.
2981
        return true;
2982
    } else {
2983
        if (api_get_session_id() == 0) {
2984
            // I'm not in a session so i will return true to not affect the normal behaviour of Chamilo tools.
2985
            return true;
2986
        } else {
2987
            // I'm in a session and I'm a student
2988
            $session_id = api_get_session_id();
2989
2990
            // Get the session visibility
2991
            $session_visibility = api_get_session_visibility($session_id);
2992
            // if 5 the session is still available
2993
2994
            //@todo We could load the session_rel_course_rel_user permission to increase the level of detail.
2995
            //echo api_get_user_id();
2996
            //echo api_get_course_id();
2997
2998
            switch ($session_visibility) {
2999
                case SESSION_VISIBLE_READ_ONLY: // 1
3000
                    return false;
3001
                case SESSION_VISIBLE:           // 2
3002
                    return true;
3003
                case SESSION_INVISIBLE:         // 3
3004
                    return false;
3005
                case SESSION_AVAILABLE:         //5
3006
                    return true;
3007
            }
3008
        }
3009
    }
3010
}
3011
3012
/**
3013
* Checks whether the user is allowed in a specific tool for a specific action
3014
* @param string $tool the tool we are checking if the user has a certain permission
3015
* @param string $action the action we are checking (add, edit, delete, move, visibility)
3016
* @author Patrick Cool <[email protected]>, Ghent University
3017
* @author Julio Montoya
3018
* @version 1.0
3019
*/
3020
function api_is_allowed($tool, $action, $task_id = 0)
3021
{
3022
    $_user = api_get_user_info();
3023
    $_course = api_get_course_info();
3024
3025
    if (api_is_course_admin()) {
3026
        return true;
3027
    }
3028
    //if (!$_SESSION['total_permissions'][$_course['code']] and $_course)
3029
    if (is_array($_course) and count($_course) > 0) {
3030
        require_once api_get_path(SYS_CODE_PATH).'permissions/permissions_functions.inc.php';
3031
3032
        // Getting the permissions of this user.
3033
        if ($task_id == 0) {
3034
            $user_permissions = get_permissions('user', $_user['user_id']);
3035
            $_SESSION['total_permissions'][$_course['code']] = $user_permissions;
3036
        }
3037
3038
        // Getting the permissions of the task.
3039
        if ($task_id != 0) {
3040
            $task_permissions = get_permissions('task', $task_id);
3041
            /* !!! */$_SESSION['total_permissions'][$_course['code']] = $task_permissions;
3042
        }
3043
        //print_r($_SESSION['total_permissions']);
3044
3045
        // Getting the permissions of the groups of the user
3046
        //$groups_of_user = GroupManager::get_group_ids($_course['db_name'], $_user['user_id']);
3047
3048
        //foreach($groups_of_user as $group)
3049
        //   $this_group_permissions = get_permissions('group', $group);
3050
3051
        // Getting the permissions of the courseroles of the user
3052
        $user_courserole_permissions = get_roles_permissions('user', $_user['user_id']);
3053
3054
        // Getting the permissions of the platformroles of the user
3055
        //$user_platformrole_permissions = get_roles_permissions('user', $_user['user_id'], ', platform');
3056
3057
        // Getting the permissions of the roles of the groups of the user
3058
        //foreach($groups_of_user as $group)
3059
        //    $this_group_courserole_permissions = get_roles_permissions('group', $group);
3060
3061
        // Getting the permissions of the platformroles of the groups of the user
3062
        //foreach($groups_of_user as $group)
3063
        //    $this_group_platformrole_permissions = get_roles_permissions('group', $group, 'platform');
3064
    }
3065
3066
    // If the permissions are limited, we have to map the extended ones to the limited ones.
3067
    if (api_get_setting('permissions') == 'limited') {
3068
        if ($action == 'Visibility') {
3069
            $action = 'Edit';
3070
        }
3071
        if ($action == 'Move') {
3072
            $action = 'Edit';
3073
        }
3074
    }
3075
3076
    // The session that contains all the permissions already exists for this course
3077
    // so there is no need to requery everything.
3078
    //my_print_r($_SESSION['total_permissions'][$_course['code']][$tool]);
3079
    if (is_array($_SESSION['total_permissions'][$_course['code']][$tool])) {
3080
        if (in_array($action, $_SESSION['total_permissions'][$_course['code']][$tool])) {
3081
            return true;
3082
        } else {
3083
            return false;
3084
        }
3085
    }
3086
}
3087
3088
/**
3089
 * Tells whether this user is an anonymous user
3090
 * @param int  $user_id      User ID (optional, will take session ID if not provided)
3091
 * @param bool $db_check     Whether to check in the database (true) or simply in
3092
 * the session (false) to see if the current user is the anonymous user
3093
 * @return bool     true if this user is anonymous, false otherwise
3094
 */
3095
function api_is_anonymous($user_id = null, $db_check = false)
3096
{
3097
    if (!isset($user_id)) {
3098
        $user_id = api_get_user_id();
3099
    }
3100
3101
    if ($db_check) {
3102
        $info = api_get_user_info($user_id);
3103
        if ($info['status'] == ANONYMOUS) {
3104
            return true;
3105
        }
3106
    }
3107
3108
    $_user = api_get_user_info();
3109
3110
    if (isset($_user['status']) && $_user['status'] == ANONYMOUS) {
3111
        //if ($_user['user_id'] == 0) {
3112
        // In some cases, api_set_anonymous doesn't seem to be triggered in local.inc.php. Make sure it is.
3113
        // Occurs in agenda for admin links - YW
3114
        global $use_anonymous;
3115
        if (isset($use_anonymous) && $use_anonymous) {
3116
            api_set_anonymous();
3117
        }
3118
3119
        return true;
3120
    }
3121
3122
    return (isset($_user['is_anonymous']) && $_user['is_anonymous'] === true) || $_user === false;
3123
}
3124
3125
/**
3126
 * Displays message "You are not allowed here..." and exits the entire script.
3127
 * @param bool   $print_headers    Whether or not to print headers (default = false -> does not print them)
3128
 * @param string $message
3129
 */
3130
function api_not_allowed($print_headers = false, $message = null)
3131
{
3132
    if (empty($message)) {
3133
        $message = get_lang('NotAllowed');
3134
    }
3135
    throw new Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException($message);
3136
3137
    if (api_get_setting('sso_authentication') === 'true') {
0 ignored issues
show
Unused Code introduced by
if (api_get_setting('sso...osso->logout(); } } does not seem to be reachable.

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

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

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

    return false;
}

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

Loading history...
3138
        global $osso;
3139
        if ($osso) {
3140
            $osso->logout();
3141
        }
3142
    }
3143
    $home_url = api_get_path(WEB_PATH);
3144
    $user_id = api_get_user_id();
3145
    $course = api_get_course_id();
3146
3147
    global $this_section;
3148
3149
    if (CustomPages::enabled() && !isset($user_id)) {
3150
3151
        if (empty($user_id)) {
3152
            // Why the CustomPages::enabled() need to be to set the request_uri
3153
            $_SESSION['request_uri'] = $_SERVER['REQUEST_URI'];
3154
        }
3155
3156
        CustomPages::display(CustomPages::INDEX_UNLOGGED);
3157
    }
3158
3159
    $origin = isset($_GET['origin']) ? $_GET['origin'] : '';
3160
3161
    $msg = null;
3162
    if (isset($message)) {
3163
        $msg = $message;
3164 View Code Duplication
    } else {
3165
        $msg = Display::return_message(
3166
            get_lang('NotAllowedClickBack').'<br/><br/><a href="'.$home_url.'">'.get_lang('ReturnToCourseHomepage').'</a>',
3167
            'error',
3168
            false
3169
        );
3170
    }
3171
3172
    $msg = Display::div($msg, array('align'=>'center'));
3173
3174
    $show_headers = 0;
3175
3176
    if ($print_headers && $origin != 'learnpath') {
3177
        $show_headers = 1;
3178
    }
3179
3180
    $tpl = new Template(null, $show_headers, $show_headers);
3181
    $tpl->assign('hide_login_link', 1);
3182
    $tpl->assign('content', $msg);
3183
3184
    if (($user_id != 0 && !api_is_anonymous()) &&
3185
        (!isset($course) || $course == -1) &&
3186
        empty($_GET['cidReq'])
3187
    ) {
3188
        // if the access is not authorized and there is some login information
3189
        // but the cidReq is not found, assume we are missing course data and send the user
3190
        // to the user_portal
3191
        $tpl->display_one_col_template();
3192
        exit;
3193
    }
3194
3195
    if (!empty($_SERVER['REQUEST_URI']) &&
3196
        (!empty($_GET['cidReq']) ||
3197
            $this_section == SECTION_MYPROFILE ||
3198
            $this_section == SECTION_PLATFORM_ADMIN
3199
        )
3200
    ) {
3201
        $courseCode = api_get_course_id();
3202
        // Only display form and return to the previous URL if there was a course ID included
3203
        if ($user_id != 0 && !api_is_anonymous()) {
3204
            //if there is a user ID, then the user is not allowed but the session is still there. Say so and exit
3205
            $tpl->assign('content', $msg);
3206
            $tpl->display_one_col_template();
3207
            exit;
3208
        }
3209
3210
        if (!is_null($courseCode)) {
3211
            api_set_firstpage_parameter($courseCode);
3212
        }
3213
3214
        // If the user has no user ID, then his session has expired
3215
        $action = api_get_self().'?'.Security::remove_XSS($_SERVER['QUERY_STRING']);
3216
        $action = str_replace('&amp;', '&', $action);
3217
        $form = new FormValidator(
3218
            'formLogin',
3219
            'post',
3220
            $action,
3221
            null,
3222
            array(),
3223
            FormValidator::LAYOUT_BOX_NO_LABEL
3224
        );
3225
        $form->addElement(
3226
            'text',
3227
            'login',
3228
            null,
3229
            array('placeholder' => get_lang('UserName'), 'autocapitalize' => 'none')
3230
        );
3231
        $form->addElement(
3232
            'password',
3233
            'password',
3234
            null,
3235
            array('placeholder' => get_lang('Password'), 'autocapitalize' => 'none')
3236
        );
3237
        $form->addButton('submitAuth', get_lang('LoginEnter'), '', 'primary');
3238
3239
        // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (above)
3240
        $content = Display::return_message(get_lang('NotAllowed'), 'error', false);
3241
3242
        if (!empty($courseCode)) {
3243
            $content .= '<h4>'.get_lang('LoginToGoToThisCourse').'</h4>';
3244
        }
3245
3246
        if (api_is_cas_activated()) {
3247
            $content .= Display::return_message(sprintf(get_lang('YouHaveAnInstitutionalAccount'), api_get_setting("Institution")), '', false);
3248
            $content .= Display::div("<br/><a href='".get_cas_direct_URL(api_get_course_id())."'>".sprintf(get_lang('LoginWithYourAccount'), api_get_setting("Institution"))."</a><br/><br/>", array('align'=>'center'));
3249
            $content .= Display::return_message(get_lang('YouDontHaveAnInstitutionAccount'));
3250
            $content .= "<p style='text-align:center'><a href='#' onclick='$(this).parent().next().toggle()'>".get_lang('LoginWithExternalAccount')."</a></p>";
3251
            $content .= "<div style='display:none;'>";
3252
        }
3253
        $content .= '<div class="well">';
3254
        $content .= $form->returnForm();
3255
        $content .='</div>';
3256
        if (api_is_cas_activated()) {
3257
            $content .= "</div>";
3258
        }
3259
3260
        if (!empty($courseCode)) {
3261
            $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
3262
                get_lang('ReturnToCourseHomepage').'</a></p>';
3263
        } else {
3264
            $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
3265
                get_lang('BackHome').'</a></p>';
3266
        }
3267
3268
        $tpl->setLoginBodyClass();
3269
        $tpl->assign('content', $content);
3270
        $tpl->display_one_col_template();
3271
        exit;
3272
    }
3273
3274
    if ($user_id != 0 && !api_is_anonymous()) {
3275
        $tpl->display_one_col_template();
3276
        exit;
3277
    }
3278
3279
    $msg = null;
3280
3281
    // The session is over and we were not in a course,
3282
    // or we try to get directly to a private course without being logged
3283
    $courseId = api_get_course_int_id();
3284
    if (!empty($courseId)) {
3285
        api_set_firstpage_parameter(api_get_course_id());
3286
        $tpl->setLoginBodyClass();
3287
        $action = api_get_self().'?'.Security::remove_XSS($_SERVER['QUERY_STRING']);
3288
        $action = str_replace('&amp;', '&', $action);
3289
        $form = new FormValidator('formLogin', 'post', $action, null, array('class'=>'form-stacked'));
3290
        $form->addElement('text', 'login', null, array('autocapitalize' => 'none', 'placeholder' => get_lang('UserName'), 'class' => 'col-md-3'));
3291
        $form->addElement('password', 'password', null, array('placeholder' => get_lang('Password'), 'class' => 'col-md-3')); //new
3292
        $form->addButtonNext(get_lang('LoginEnter'), 'submitAuth');
3293
3294
        // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (bellow)
3295
        $msg = Display::return_message(get_lang('NotAllowed'), 'error', false);
3296
        $msg .= '<h4>'.get_lang('LoginToGoToThisCourse').'</h4>';
3297
        $casEnabled = api_is_cas_activated();
3298
        if ($casEnabled) {
3299
            $msg .= Display::return_message(sprintf(get_lang('YouHaveAnInstitutionalAccount'), api_get_setting("Institution")), '', false);
3300
            $msg .= Display::div("<br/><a href='".get_cas_direct_URL(api_get_course_int_id())."'>".getCASLogoHTML()." ".sprintf(get_lang('LoginWithYourAccount'), api_get_setting("Institution"))."</a><br/><br/>", array('align'=>'center'));
3301
            $msg .= Display::return_message(get_lang('YouDontHaveAnInstitutionAccount'));
3302
            $msg .= "<p style='text-align:center'><a href='#' onclick='$(this).parent().next().toggle()'>".get_lang('LoginWithExternalAccount')."</a></p>";
3303
            $msg .= "<div style='display:none;'>";
3304
        }
3305
        $msg .= '<div class="well">';
3306
        $msg .= $form->returnForm();
3307
        $msg .='</div>';
3308
        if ($casEnabled) {
3309
            $msg .= "</div>";
3310
        }
3311 View Code Duplication
    } else {
3312
        // we were not in a course, return to home page
3313
        $msg = Display::return_message(
3314
            get_lang('NotAllowed').'<br/><br/><a href="'.$home_url.'">'.get_lang('BackHome').'</a><br />',
3315
            'error',
3316
            false
3317
        );
3318
    }
3319
3320
    $tpl->assign('content', $msg);
3321
    $tpl->display_one_col_template();
3322
    exit;
3323
}
3324
3325
/**
3326
 * Gets a UNIX timestamp from a database (MySQL) datetime format string
3327
 * @param $last_post_datetime standard output date in a sql query
3328
 * @return integer timestamp
3329
 * @author Toon Van Hoecke <[email protected]>
3330
 * @version October 2003
3331
 * @desc convert sql date to unix timestamp
3332
 */
3333
function convert_sql_date($last_post_datetime) {
3334
    list ($last_post_date, $last_post_time) = explode(' ', $last_post_datetime);
3335
    list ($year, $month, $day) = explode('-', $last_post_date);
3336
    list ($hour, $min, $sec) = explode(':', $last_post_time);
3337
    return mktime((int)$hour, (int)$min, (int)$sec, (int)$month, (int)$day, (int)$year);
3338
}
3339
3340
/**
3341
 * Gets item visibility from the item_property table
3342
 *
3343
 * Getting the visibility is done by getting the last updated visibility entry,
3344
 * using the largest session ID found if session 0 and another was found (meaning
3345
 * the only one that is actually from the session, in case there are results from
3346
 * session 0 *AND* session n).
3347
 * @param array     Course properties array (result of api_get_course_info())
3348
 * @param string    Tool (learnpath, document, etc)
3349
 * @param int       The item ID in the given tool
3350
 * @param int       The session ID (optional)
3351
 * @param string $tool
3352
 * @param integer $user_id
3353
 * @param string $type
3354
 * @return int      -1 on error, 0 if invisible, 1 if visible
3355
 */
3356
function api_get_item_visibility(
3357
    $_course,
3358
    $tool,
3359
    $id,
3360
    $session = 0,
3361
    $user_id = null,
3362
    $type = null,
3363
    $group_id = null
3364
) {
3365
    if (!is_array($_course) || count($_course) == 0 || empty($tool) || empty($id)) {
3366
        return -1;
3367
    }
3368
3369
    $tool = Database::escape_string($tool);
3370
    $id = intval($id);
3371
    $session = (int) $session;
3372
    $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
3373
    $course_id = intval($_course['real_id']);
3374
3375
    $userCondition = '';
3376
    if (!empty($user_id)) {
3377
        $user_id = intval($user_id);
3378
        $userCondition = " AND to_user_id = $user_id ";
3379
    }
3380
3381
    $typeCondition = '';
3382
    if (!empty($type)) {
3383
        $type = Database::escape_string($type);
3384
        $typeCondition = " AND lastedit_type = '$type' ";
3385
    }
3386
3387
    $groupCondition = '';
3388
    if (!empty($group_id)) {
3389
        $group_id = intval($group_id);
3390
        $groupCondition = " AND to_group_id = '$group_id' ";
3391
    }
3392
3393
    $sql = "SELECT visibility
3394
            FROM $TABLE_ITEMPROPERTY
3395
            WHERE
3396
                c_id = $course_id AND
3397
                tool = '$tool' AND
3398
                ref = $id AND
3399
                (session_id = $session OR session_id = 0 OR session_id IS NULL)
3400
                $userCondition $typeCondition $groupCondition
3401
            ORDER BY session_id DESC, lastedit_date DESC
3402
            LIMIT 1";
3403
3404
    $res = Database::query($sql);
3405
    if ($res === false || Database::num_rows($res) == 0) {
3406
        return -1;
3407
    }
3408
    $row = Database::fetch_array($res);
3409
3410
    return $row['visibility'];
3411
}
3412
3413
/**
3414
 * Delete a row in the c_item_property table
3415
 *
3416
 * @param array $courseInfo
3417
 * @param string $tool
3418
 * @param int $itemId
3419
 * @param int $userId
3420
 * @param int $groupId
3421
 * @param int $sessionId
3422
 * @return false|null
3423
 */
3424
function api_item_property_delete(
3425
    $courseInfo,
3426
    $tool,
3427
    $itemId,
3428
    $userId,
3429
    $groupId = 0,
3430
    $sessionId = 0
3431
) {
3432
    if (empty($courseInfo)) {
3433
        return false;
3434
    }
3435
3436
    $courseId = intval($courseInfo['real_id']);
3437
3438
    if (empty($courseId) || empty($tool) || empty($itemId)) {
3439
        return false;
3440
    }
3441
3442
    $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3443
    $tool = Database::escape_string($tool);
3444
    $itemId = intval($itemId);
3445
    $userId = intval($userId);
3446
    $groupId = intval($groupId);
3447
    $sessionId = intval($sessionId);
3448
3449
    $groupCondition = " AND to_group_id = $groupId ";
3450
    if (empty($groupId)) {
3451
        $groupCondition = " AND (to_group_id is NULL OR to_group_id = 0) ";
3452
    }
3453
3454
    $userCondition = " AND to_user_id = $userId ";
3455
    if (empty($userId)) {
3456
        $userCondition = " AND (to_user_id is NULL OR to_user_id = 0) ";
3457
    }
3458
    $sessionCondition = api_get_session_condition($sessionId, true, false, 'session_id');
3459
    $sql = "DELETE FROM $table
3460
            WHERE
3461
                c_id = $courseId AND
3462
                tool  = '$tool' AND
3463
                ref = $itemId
3464
                $sessionCondition
3465
                $userCondition
3466
                $groupCondition
3467
            ";
3468
3469
    Database::query($sql);
3470
}
3471
3472
/**
3473
 * Updates or adds item properties to the Item_propetry table
3474
 * Tool and lastedit_type are language independant strings (langvars->get_lang!)
3475
 *
3476
 * @param array $_course array with course properties
3477
 * @param string $tool tool id, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
3478
 * @param int $item_id id of the item itself, linked to key of every tool ('id', ...)
3479
 * @param string $last_edit_type add or update action
3480
 * (1) message to be translated (in trad4all) : e.g. DocumentAdded, DocumentUpdated;
3481
 * (2) "delete"
3482
 * (3) "visible"
3483
 * (4) "invisible"
3484
 * @param int $user_id id of the editing/adding user
3485
 * @param int $to_group_id group.iid
3486
 * @param int $to_user_id id of the intended user (always has priority over $to_group_id !), only relevant for $type (1)
3487
 * @param string $start_visible 0000-00-00 00:00:00 format
3488
 * @param string $end_visible 0000-00-00 00:00:00 format
3489
 * @param int $session_id The session ID, if any, otherwise will default to 0
3490
 * @return boolean False if update fails.
3491
 * @author Toon Van Hoecke <[email protected]>, Ghent University
3492
 * @version January 2005
3493
 * @desc update the item_properties table (if entry not exists, insert) of the course
3494
 */
3495
function api_item_property_update(
3496
    $_course,
3497
    $tool,
3498
    $item_id,
3499
    $last_edit_type,
3500
    $user_id,
3501
    $to_group_id = 0,
3502
    $to_user_id = null,
3503
    $start_visible = '',
3504
    $end_visible = '',
3505
    $session_id = 0
3506
) {
3507
    if (empty($_course)) {
3508
        return false;
3509
    }
3510
3511
    $course_id = $_course['real_id'];
3512
3513
    if (empty($course_id)) {
3514
        return false;
3515
    }
3516
3517
    $em = Database::getManager();
3518
3519
    // Definition of variables.
3520
    $tool = Database::escape_string($tool);
3521
    $item_id = intval($item_id);
3522
    $lastEditTypeNoFilter = $last_edit_type;
3523
    $last_edit_type = Database::escape_string($last_edit_type);
3524
    $user_id = intval($user_id);
3525
3526
    $startVisible = "NULL";
3527
    if (!empty($start_visible)) {
3528
        $start_visible = Database::escape_string($start_visible);
3529
        $startVisible = "'$start_visible'";
3530
    }
3531
3532
    $endVisible = "NULL";
3533
    if (!empty($end_visible)) {
3534
        $end_visible = Database::escape_string($end_visible);
3535
        $endVisible = "'$end_visible'";
3536
    }
3537
3538
    $to_filter = '';
3539
    $time = api_get_utc_datetime();
3540
3541
    if (!empty($session_id)) {
3542
        $session_id = intval($session_id);
3543
    } else {
3544
        $session_id = api_get_session_id();
3545
    }
3546
3547
    // Definition of tables.
3548
    $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
3549
3550
    if ($to_user_id <= 0) {
3551
        $to_user_id = null; // No to_user_id set
3552
    }
3553
3554
    if (!is_null($to_user_id)) {
3555
        // $to_user_id has more priority than $to_group_id
3556
        $to_user_id = intval($to_user_id);
3557
        $to_field = 'to_user_id';
3558
        $to_value = $to_user_id;
3559
    } else {
3560
        // $to_user_id is not set.
3561
        $to_field = 'to_group_id';
3562
        $to_value = $to_group_id;
3563
    }
3564
3565
    $toValueCondition = empty($to_value) ? "NULL" : "'$to_value'";
3566
3567
    // Set filters for $to_user_id and $to_group_id, with priority for $to_user_id
3568
    $condition_session = " AND session_id = $session_id ";
3569
    if (empty($session_id)) {
3570
        $condition_session = " AND (session_id = 0 OR session_id IS NULL) ";
3571
    }
3572
3573
    $filter = " c_id = $course_id AND tool = '$tool' AND ref = $item_id $condition_session ";
3574
3575
    // Check whether $to_user_id and $to_group_id are passed in the function call.
3576
    // If both are not passed (both are null) then it is a message for everybody and $to_group_id should be 0 !
3577
    if (is_null($to_user_id) && is_null($to_group_id)) {
3578
        $to_group_id = 0;
3579
    }
3580
3581
    if (!is_null($to_user_id)) {
3582
        // Set filter to intended user.
3583
        $to_filter = " AND to_user_id = $to_user_id $condition_session";
3584
    } else {
3585
        // Set filter to intended group.
3586
        if (($to_group_id != 0) && $to_group_id == strval(intval($to_group_id))) {
3587
            $to_filter = " AND to_group_id = $to_group_id $condition_session";
3588
        }
3589
    }
3590
3591
    // Adding filter if set.
3592
    $filter .= $to_filter;
3593
3594
    // Update if possible
3595
    $set_type = '';
3596
3597
    switch ($lastEditTypeNoFilter) {
3598 View Code Duplication
        case 'delete':
3599
            // delete = make item only visible for the platform admin.
3600
            $visibility = '2';
3601
            if (!empty($session_id)) {
3602
                // Check whether session id already exist into item_properties for updating visibility or add it.
3603
                $sql = "SELECT session_id FROM $tableItemProperty
3604
                        WHERE
3605
                            c_id = $course_id AND
3606
                            tool = '$tool' AND
3607
                            ref = $item_id AND
3608
                            session_id = $session_id";
3609
                $rs = Database::query($sql);
3610
                if (Database::num_rows($rs) > 0) {
3611
                    $sql = "UPDATE $tableItemProperty
3612
                            SET lastedit_type       = '".str_replace('_', '', ucwords($tool))."Deleted',
3613
                                lastedit_date       = '$time',
3614
                                lastedit_user_id    = $user_id,
3615
                                visibility          = $visibility,
3616
                                session_id          = $session_id $set_type
3617
                            WHERE $filter";
3618
                    $result = Database::query($sql);
3619
                } else {
3620
                    $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)
3621
                            VALUES ($course_id, '$tool',$item_id, '$time', $user_id, '$time', '$last_edit_type',$user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3622
                    $result = Database::query($sql);
3623
                    $id = Database::insert_id();
3624
                    if ($id) {
3625
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3626
                        Database::query($sql);
3627
                    }
3628
                }
3629
            } else {
3630
                $sql = "UPDATE $tableItemProperty
3631
                        SET
3632
                            lastedit_type='".str_replace('_', '', ucwords($tool))."Deleted',
3633
                            lastedit_date='$time',
3634
                            lastedit_user_id = $user_id,
3635
                            visibility = $visibility $set_type
3636
                        WHERE $filter";
3637
                $result = Database::query($sql);
3638
            }
3639
            break;
3640 View Code Duplication
        case 'visible' : // Change item to visible.
3641
            $visibility = '1';
3642
            if (!empty($session_id)) {
3643
                // Check whether session id already exist into item_properties for updating visibility or add it.
3644
                $sql = "SELECT session_id FROM $tableItemProperty
3645
                        WHERE
3646
                            c_id = $course_id AND
3647
                            tool = '$tool' AND
3648
                            ref = $item_id AND
3649
                            session_id = $session_id";
3650
                $rs = Database::query($sql);
3651
                if (Database::num_rows($rs) > 0) {
3652
                    $sql = "UPDATE $tableItemProperty
3653
                            SET
3654
                                lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
3655
                                lastedit_date='$time',
3656
                                lastedit_user_id = $user_id,
3657
                                visibility = $visibility,
3658
                                session_id = $session_id $set_type
3659
                            WHERE $filter";
3660
                    $result = Database::query($sql);
3661
                } else {
3662
                    $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)
3663
                            VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3664
                    $result = Database::query($sql);
3665
                    $id = Database::insert_id();
3666
                    if ($id) {
3667
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3668
                        Database::query($sql);
3669
                    }
3670
                }
3671
            } else {
3672
                $sql = "UPDATE $tableItemProperty
3673
                        SET
3674
                            lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
3675
                            lastedit_date='$time',
3676
                            lastedit_user_id = $user_id,
3677
                            visibility = $visibility $set_type
3678
                        WHERE $filter";
3679
                $result = Database::query($sql);
3680
            }
3681
            break;
3682 View Code Duplication
        case 'invisible' : // Change item to invisible.
3683
            $visibility = '0';
3684
            if (!empty($session_id)) {
3685
                // Check whether session id already exist into item_properties for updating visibility or add it
3686
                $sql = "SELECT session_id FROM $tableItemProperty
3687
                        WHERE
3688
                            c_id = $course_id AND
3689
                            tool = '$tool' AND
3690
                            ref = $item_id AND
3691
                            session_id = $session_id";
3692
                $rs = Database::query($sql);
3693
                if (Database::num_rows($rs) > 0) {
3694
                    $sql = "UPDATE $tableItemProperty
3695
                            SET
3696
                                lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
3697
                                lastedit_date = '$time',
3698
                                lastedit_user_id = $user_id,
3699
                                visibility = $visibility,
3700
                                session_id = $session_id $set_type
3701
                            WHERE $filter";
3702
                    $result = Database::query($sql);
3703
                } else {
3704
                    $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)
3705
                            VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3706
                    $result = Database::query($sql);
3707
                    $id = Database::insert_id();
3708
                    if ($id) {
3709
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3710
                        Database::query($sql);
3711
                    }
3712
                }
3713
            } else {
3714
                $sql = "UPDATE $tableItemProperty
3715
                        SET
3716
                            lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
3717
                            lastedit_date = '$time',
3718
                            lastedit_user_id = $user_id,
3719
                            visibility = $visibility $set_type
3720
                        WHERE $filter";
3721
                $result = Database::query($sql);
3722
            }
3723
            break;
3724
        default: // The item will be added or updated.
3725
            $set_type = ", lastedit_type = '$last_edit_type' ";
3726
            $visibility = '1';
3727
            //$filter .= $to_filter; already added
3728
            $sql = "UPDATE $tableItemProperty
3729
                    SET
3730
                      lastedit_date = '$time',
3731
                      lastedit_user_id = $user_id $set_type
3732
                    WHERE $filter";
3733
            $result = Database::query($sql);
3734
    }
3735
3736
    // Insert if no entries are found (can only happen in case of $last_edit_type switch is 'default').
3737
    if ($result == false || Database::affected_rows($result) == 0) {
0 ignored issues
show
Bug introduced by
It seems like $result can be null; however, affected_rows() does not accept null, maybe add an additional type check?

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

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

function doesNotAcceptNull(stdClass $x) { }

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

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

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
3738
        $objCourse = $em->find('ChamiloCoreBundle:Course', intval($course_id));
3739
        $objTime = new DateTime('now', new DateTimeZone('UTC'));
3740
        $objUser = $em->find('ChamiloUserBundle:User', intval($user_id));
3741
        $objGroup = $em->find('ChamiloCourseBundle:CGroupInfo', intval($to_group_id));
3742
        $objToUser = $em->find('ChamiloUserBundle:User', intval($to_user_id));
3743
        $objSession = $em->find('ChamiloCoreBundle:Session', intval($session_id));
3744
3745
        $startVisibleDate = !empty($start_visible) ? new DateTime($start_visible, new DateTimeZone('UTC')) : null;
3746
        $endVisibleDate = !empty($endVisibleDate) ? new DateTime($endVisibleDate, new DateTimeZone('UTC')) : null;
0 ignored issues
show
Bug introduced by
The variable $endVisibleDate seems only to be defined at a later point. As such the call to empty() seems to always evaluate to true.

This check marks calls to isset(...) or empty(...) that are found before the variable itself is defined. These will always have the same result.

This is likely the result of code being shifted around. Consider removing these calls.

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

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

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

function doesNotAcceptNull(stdClass $x) { }

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

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

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

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
4996
                // Such a setting does not exist.
4997
                //error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all', 0);
4998
            }
4999
        } else {
5000
            // Other access url.
5001
            if (!empty($subvar)) {
5002
                $select .= " AND subkey = '$subvar'";
5003
            }
5004
            if (!empty($cat)) {
5005
                $select .= " AND category = '$cat'";
5006
            }
5007
            $res = Database::query($select);
5008
5009
            if (Database::num_rows($res) > 0) {
5010
                // We have a setting for access_url 1, but none for the current one, so create one.
5011
                $row = Database::fetch_array($res);
5012
                if ($row['access_url_changeable'] == 1) {
5013
                    $insert = "INSERT INTO $t_settings (variable,subkey, type,category, selected_value,title, comment,scope, subkeytext,access_url, access_url_changeable) VALUES
5014
                            ('".$row['variable']."',".
5015
                            (!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL")."," .
5016
                            "'".$row['type']."','".$row['category']."'," .
5017
                            "'$value','".$row['title']."'," .
5018
                            "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".
5019
                            (!empty($row['scope']) ? "'".$row['scope']."'" : "NULL")."," .
5020
                            "".(!empty($row['subkeytext']) ? "'".$row['subkeytext']."'" : "NULL").",$access_url,".$row['access_url_changeable'].")";
5021
                    Database::query($insert);
5022
                }
5023
            } else { // Such a setting does not exist.
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
5024
                //error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all. The access_url is: '.$access_url.' ',0);
5025
            }
5026
        }
5027
    }
5028
}
5029
5030
/**
5031
 * Sets a whole category of settings to one specific value
5032
 * @param string    Category
5033
 * @param string    Value
5034
 * @param int       Access URL. Optional. Defaults to 1
5035
 * @param array     Optional array of filters on field type
5036
 * @param string $category
5037
 * @param string $value
5038
 */
5039
function api_set_settings_category($category, $value = null, $access_url = 1, $fieldtype = array())
5040
{
5041
    if (empty($category)) {
5042
        return false;
5043
    }
5044
    $category = Database::escape_string($category);
5045
    $t_s = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5046
    $access_url = (int) $access_url;
5047
    if (empty($access_url)) { $access_url = 1; }
5048
    if (isset($value)) {
5049
        $value = Database::escape_string($value);
5050
        $sql = "UPDATE $t_s SET selected_value = '$value'
5051
                WHERE category = '$category' AND access_url = $access_url";
5052 View Code Duplication
        if (is_array($fieldtype) && count($fieldtype)>0) {
5053
            $sql .= " AND ( ";
5054
            $i = 0;
5055
            foreach ($fieldtype as $type){
5056
                if ($i > 0) {
5057
                    $sql .= ' OR ';
5058
                }
5059
                $type = Database::escape_string($type);
5060
                $sql .= " type='".$type."' ";
5061
                $i++;
5062
            }
5063
            $sql .= ")";
5064
        }
5065
        $res = Database::query($sql);
5066
        return $res !== false;
5067
    } else {
5068
        $sql = "UPDATE $t_s SET selected_value = NULL
5069
                WHERE category = '$category' AND access_url = $access_url";
5070 View Code Duplication
        if (is_array($fieldtype) && count($fieldtype)>0) {
5071
            $sql .= " AND ( ";
5072
            $i = 0;
5073
            foreach ($fieldtype as $type){
5074
                if ($i > 0) {
5075
                    $sql .= ' OR ';
5076
                }
5077
                $type = Database::escape_string($type);
5078
                $sql .= " type='".$type."' ";
5079
                $i++;
5080
            }
5081
            $sql .= ")";
5082
        }
5083
        $res = Database::query($sql);
5084
        return $res !== false;
5085
    }
5086
}
5087
5088
/**
5089
 * Gets all available access urls in an array (as in the database)
5090
 * @return array    An array of database records
5091
 */
5092
function api_get_access_urls($from = 0, $to = 1000000, $order = 'url', $direction = 'ASC')
5093
{
5094
    $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5095
    $from = (int) $from;
5096
    $to = (int) $to;
5097
    $order = Database::escape_string($order, null, false);
5098
    $direction = Database::escape_string($direction, null, false);
5099
    $sql = "SELECT id, url, description, active, created_by, tms
5100
            FROM $table
5101
            ORDER BY $order $direction
5102
            LIMIT $to OFFSET $from";
5103
    $res = Database::query($sql);
5104
    return Database::store_result($res);
5105
}
5106
5107
/**
5108
 * Gets the access url info in an array
5109
 * @param int $id Id of the access url
5110
 * @param bool $returnDefault Set to false if you want the real URL if URL 1 is still 'http://localhost/'
5111
 * @return array All the info (url, description, active, created_by, tms)
5112
 * from the access_url table
5113
 * @author Julio Montoya
5114
 */
5115
function api_get_access_url($id, $returnDefault = true)
5116
{
5117
    $id = intval($id);
5118
    // Calling the Database:: library dont work this is handmade.
5119
    $table_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5120
    $sql = "SELECT url, description, active, created_by, tms
5121
            FROM $table_access_url WHERE id = '$id' ";
5122
    $res = Database::query($sql);
5123
    $result = @Database::fetch_array($res);
5124
    // If the result url is 'http://localhost/' (the default) and the root_web
5125
    // (=current url) is different, and the $id is = 1 (which might mean
5126
    // api_get_current_access_url_id() returned 1 by default), then return the
5127
    // root_web setting instead of the current URL
5128
    // This is provided as an option to avoid breaking the storage of URL-specific
5129
    // homepages in home/localhost/
5130
    if ($id === 1 && $returnDefault === false) {
5131
        $currentUrl = api_get_current_access_url_id();
5132
        // only do this if we are on the main URL (=1), otherwise we could get
5133
        // information on another URL instead of the one asked as parameter
5134
        if ($currentUrl === 1) {
5135
            $rootWeb = api_get_path(WEB_PATH);
5136
            $default = 'http://localhost/';
5137
            if ($result['url'] === $default && $rootWeb != $default) {
5138
                $result['url'] = $rootWeb;
5139
            }
5140
        }
5141
    }
5142
5143
    return $result;
5144
}
5145
5146
/**
5147
 * Gets all the current settings for a specific access url
5148
 * @param string    The category, if any, that we want to get
5149
 * @param string    Whether we want a simple list (display a category) or
5150
 * a grouped list (group by variable as in settings.php default). Values: 'list' or 'group'
5151
 * @param int       Access URL's ID. Optional. Uses 1 by default, which is the unique URL
5152
 * @return array    Array of database results for the current settings of the current access URL
5153
 */
5154
function &api_get_settings($cat = null, $ordering = 'list', $access_url = 1, $url_changeable = 0)
5155
{
5156
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5157
    $access_url = (int) $access_url;
5158
    $where_condition = '';
5159
    if ($url_changeable == 1) {
5160
        $where_condition = " AND access_url_changeable= '1' ";
5161
    }
5162
    if (empty($access_url) || $access_url == -1) {
5163
        $access_url = 1;
5164
    }
5165
    $sql = "SELECT * FROM $table
5166
            WHERE access_url = $access_url  $where_condition ";
5167
5168
    if (!empty($cat)) {
5169
        $cat = Database::escape_string($cat);
5170
        $sql .= " AND category='$cat' ";
5171
    }
5172
    if ($ordering == 'group') {
5173
        $sql .= " ORDER BY id ASC";
5174
    } else {
5175
        $sql .= " ORDER BY 1,2 ASC";
5176
    }
5177
    $result = Database::query($sql);
5178
    $result = Database::store_result($result,'ASSOC');
0 ignored issues
show
Bug introduced by
It seems like $result can be null; however, store_result() does not accept null, maybe add an additional type check?

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

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

function doesNotAcceptNull(stdClass $x) { }

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

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

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
5179
5180
    return $result;
5181
}
5182
5183
/**
5184
 * Sets a platform configuration setting to a given value
5185
 * @param string    The value we want to record
5186
 * @param string    The variable name we want to insert
5187
 * @param string    The subkey for the variable we want to insert
5188
 * @param string    The type for the variable we want to insert
5189
 * @param string    The category for the variable we want to insert
5190
 * @param string    The title
5191
 * @param string    The comment
5192
 * @param string    The scope
5193
 * @param string    The subkey text
5194
 * @param int       The access_url for which this parameter is valid
5195
 * @param int       The changeability of this setting for non-master urls
5196
 * @param string $val
5197
 * @param string $var
5198
 * @param string $sk
5199
 * @param string $c
5200
 * @return boolean  true on success, false on failure
5201
 */
5202
function api_add_setting(
5203
    $val,
5204
    $var,
5205
    $sk = null,
5206
    $type = 'textfield',
5207
    $c = null,
5208
    $title = '',
5209
    $com = '',
5210
    $sc = null,
5211
    $skt = null,
5212
    $a = 1,
5213
    $v = 0
5214
) {
5215
    if (empty($var) || !isset($val)) { return false; }
5216
    $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5217
    $var = Database::escape_string($var);
5218
    $val = Database::escape_string($val);
5219
    $a = (int) $a;
5220
    if (empty($a)) { $a = 1; }
5221
    // Check if this variable doesn't exist already
5222
    $select = "SELECT id FROM $t_settings WHERE variable = '$var' ";
5223
    if (!empty($sk)) {
5224
        $sk = Database::escape_string($sk);
5225
        $select .= " AND subkey = '$sk'";
5226
    }
5227
    if ($a > 1) {
5228
        $select .= " AND access_url = $a";
5229
    } else {
5230
        $select .= " AND access_url = 1 ";
5231
    }
5232
    $res = Database::query($select);
5233
    if (Database::num_rows($res) > 0) { // Found item for this access_url.
5234
        $row = Database::fetch_array($res);
5235
        Database::update(
5236
            $t_settings,
5237
            array('selected_value' => $val),
5238
            array('id = ?' => array($row['id']))
5239
        );
5240
        return $row['id'];
5241
    }
5242
5243
    // Item not found for this access_url, we have to check if the whole thing is missing
5244
    // (in which case we ignore the insert) or if there *is* a record but just for access_url = 1
5245
    $insert = "INSERT INTO $t_settings " .
5246
                "(variable,selected_value," .
5247
                "type,category," .
5248
                "subkey,title," .
5249
                "comment,scope," .
5250
                "subkeytext,access_url,access_url_changeable)" .
5251
                " VALUES ('$var','$val',";
5252
    if (isset($type)) {
5253
        $type = Database::escape_string($type);
5254
        $insert .= "'$type',";
5255
    } else {
5256
        $insert .= "NULL,";
5257
    }
5258
    if (isset($c)) { // Category
5259
        $c = Database::escape_string($c);
5260
        $insert .= "'$c',";
5261
    } else {
5262
        $insert .= "NULL,";
5263
    }
5264
    if (isset($sk)) { // Subkey
5265
        $sk = Database::escape_string($sk);
5266
        $insert .= "'$sk',";
5267
    } else {
5268
        $insert .= "NULL,";
5269
    }
5270
    if (isset($title)) { // Title
5271
        $title = Database::escape_string($title);
5272
        $insert .= "'$title',";
5273
    } else {
5274
        $insert .= "NULL,";
5275
    }
5276
    if (isset($com)) { // Comment
5277
        $com = Database::escape_string($com);
5278
        $insert .= "'$com',";
5279
    } else {
5280
        $insert .= "NULL,";
5281
    }
5282
    if (isset($sc)) { // Scope
5283
        $sc = Database::escape_string($sc);
5284
        $insert .= "'$sc',";
5285
    } else {
5286
        $insert .= "NULL,";
5287
    }
5288
    if (isset($skt)) { // Subkey text
5289
        $skt = Database::escape_string($skt);
5290
        $insert .= "'$skt',";
5291
    } else {
5292
        $insert .= "NULL,";
5293
    }
5294
    $insert .= "$a,$v)";
5295
    $res = Database::query($insert);
5296
    return $res;
5297
}
5298
5299
/**
5300
 * Checks wether a user can or can't view the contents of a course.
5301
 *
5302
 * @param   int $userid     User id or NULL to get it from $_SESSION
5303
 * @param   int $cid        Course id to check whether the user is allowed.
5304
 * @return  bool
5305
 */
5306
function api_is_course_visible_for_user($userid = null, $cid = null) {
5307
    if ($userid === null) {
5308
        $userid = api_get_user_id();
5309
    }
5310
    if (empty($userid) || strval(intval($userid)) != $userid) {
5311
        if (api_is_anonymous()) {
5312
            $userid = api_get_anonymous_id();
5313
        } else {
5314
            return false;
5315
        }
5316
    }
5317
    $cid = Database::escape_string($cid);
5318
5319
    $courseInfo = api_get_course_info($cid);
5320
    $courseId = $courseInfo['real_id'];
5321
5322
    global $is_platformAdmin;
5323
5324
    $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
5325
    $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
5326
5327
    $sql = "SELECT
5328
                $course_table.category_code,
5329
                $course_table.visibility,
5330
                $course_table.code,
5331
                $course_cat_table.code
5332
            FROM $course_table
5333
            LEFT JOIN $course_cat_table
5334
                ON $course_table.category_code = $course_cat_table.code
5335
            WHERE
5336
                $course_table.code = '$cid'
5337
            LIMIT 1";
5338
5339
    $result = Database::query($sql);
5340
5341
    if (Database::num_rows($result) > 0) {
5342
        $visibility = Database::fetch_array($result);
5343
        $visibility = $visibility['visibility'];
5344
    } else {
5345
        $visibility = 0;
5346
    }
5347
    // Shortcut permissions in case the visibility is "open to the world".
5348
    if ($visibility === COURSE_VISIBILITY_OPEN_WORLD) {
5349
        return true;
5350
    }
5351
5352
    $tbl_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
5353
5354
    $sql = "SELECT
5355
                is_tutor, status
5356
            FROM $tbl_course_user
5357
            WHERE
5358
                user_id  = '$userid' AND
5359
                relation_type <> '".COURSE_RELATION_TYPE_RRHH."' AND
5360
                c_id = $courseId
5361
            LIMIT 1";
5362
5363
    $result = Database::query($sql);
5364
5365 View Code Duplication
    if (Database::num_rows($result) > 0) {
5366
        // This user has got a recorded state for this course.
5367
        $cuData = Database::fetch_array($result);
5368
        $is_courseMember = true;
5369
        $is_courseTutor = ($cuData['is_tutor'] == 1);
5370
        $is_courseAdmin = ($cuData['status'] == 1);
5371
    }
5372
5373
    if (!$is_courseAdmin) {
5374
        // This user has no status related to this course.
5375
        // Is it the session coach or the session admin?
5376
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
5377
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
5378
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
5379
5380
        $sql = "SELECT
5381
                    session.id_coach, session_admin_id, session.id
5382
                FROM
5383
                    $tbl_session as session
5384
                INNER JOIN $tbl_session_course
5385
                    ON session_rel_course.session_id = session.id
5386
                    AND session_rel_course.c_id = '$courseId'
5387
                LIMIT 1";
5388
5389
        $result = Database::query($sql);
5390
        $row = Database::store_result($result);
5391
5392
        if ($row[0]['id_coach'] == $userid) {
5393
            $is_courseMember = true;
5394
            $is_courseTutor = true;
5395
            $is_courseAdmin = false;
5396
            $is_courseCoach = true;
5397
            $is_sessionAdmin = false;
5398
        }
5399
        elseif ($row[0]['session_admin_id'] == $userid) {
5400
            $is_courseMember = false;
5401
            $is_courseTutor = false;
5402
            $is_courseAdmin = false;
5403
            $is_courseCoach = false;
5404
            $is_sessionAdmin = true;
5405
        } else {
5406
            // Check if the current user is the course coach.
5407
            $sql = "SELECT 1
5408
                    FROM $tbl_session_course
5409
                    WHERE session_rel_course.c_id = '$courseId'
5410
                    AND session_rel_course.id_coach = '$userid'
5411
                    LIMIT 1";
5412
5413
            $result = Database::query($sql);
5414
5415
            //if ($row = Database::fetch_array($result)) {
5416
            if (Database::num_rows($result) > 0 ) {
5417
                $is_courseMember = true;
5418
                $is_courseTutor = true;
5419
                $is_courseCoach = true;
5420
                $is_sessionAdmin = false;
5421
5422
                $tbl_user = Database :: get_main_table(TABLE_MAIN_USER);
5423
5424
                $sql = "SELECT status FROM $tbl_user
5425
                        WHERE user_id = $userid
5426
                        LIMIT 1";
5427
5428
                $result = Database::query($sql);
5429
5430
                if (Database::result($result, 0, 0) == 1) {
5431
                    $is_courseAdmin = true;
5432
                } else {
5433
                    $is_courseAdmin = false;
5434
                }
5435
            } else {
5436
                // Check if the user is a student is this session.
5437
                $sql = "SELECT  id
5438
                        FROM $tbl_session_course_user
5439
                        WHERE
5440
                            user_id  = '$userid' AND
5441
                            c_id = '$courseId'
5442
                        LIMIT 1";
5443
5444
                if (Database::num_rows($result) > 0) {
5445
                    // This user haa got a recorded state for this course.
5446
                    while ($row = Database::fetch_array($result)) {
5447
                        $is_courseMember = true;
5448
                        $is_courseTutor = false;
5449
                        $is_courseAdmin = false;
5450
                        $is_sessionAdmin = false;
5451
                    }
5452
                }
5453
            }
5454
        }
5455
    }
5456
5457
    switch ($visibility) {
5458
        case COURSE_VISIBILITY_OPEN_WORLD:
5459
            return true;
5460
        case COURSE_VISIBILITY_OPEN_PLATFORM:
5461
            return isset($userid);
5462
        case COURSE_VISIBILITY_REGISTERED:
5463
        case COURSE_VISIBILITY_CLOSED:
5464
            return $is_platformAdmin || $is_courseMember || $is_courseAdmin;
5465
        case COURSE_VISIBILITY_HIDDEN:
5466
            return $is_platformAdmin;
5467
    }
5468
5469
    return false;
5470
}
5471
5472
/**
5473
 * Returns whether an element (forum, message, survey ...) belongs to a session or not
5474
 * @param String the tool of the element
5475
 * @param int the element id in database
5476
 * @param int the session_id to compare with element session id
5477
 * @param string $tool
5478
 * @return boolean true if the element is in the session, false else
5479
 */
5480
function api_is_element_in_the_session($tool, $element_id, $session_id = null) {
5481
    if (is_null($session_id)) {
5482
        $session_id = api_get_session_id();
5483
    }
5484
5485
    // Get information to build query depending of the tool.
5486
    switch ($tool) {
5487
        case TOOL_SURVEY :
5488
            $table_tool = Database::get_course_table(TABLE_SURVEY);
5489
            $key_field = 'survey_id';
5490
            break;
5491
        case TOOL_ANNOUNCEMENT :
5492
            $table_tool = Database::get_course_table(TABLE_ANNOUNCEMENT);
5493
            $key_field = 'id';
5494
            break;
5495
        case TOOL_AGENDA :
5496
            $table_tool = Database::get_course_table(TABLE_AGENDA);
5497
            $key_field = 'id';
5498
            break;
5499
        case TOOL_GROUP :
5500
            $table_tool = Database::get_course_table(TABLE_GROUP);
5501
            $key_field = 'id';
5502
            break;
5503
        default:
5504
            return false;
5505
    }
5506
    $course_id = api_get_course_int_id();
5507
5508
    $sql = "SELECT session_id FROM $table_tool 
5509
            WHERE c_id = $course_id AND $key_field =  ".intval($element_id);
5510
    $rs = Database::query($sql);
5511
    if ($element_session_id = Database::result($rs, 0, 0)) {
5512
        if ($element_session_id == intval($session_id)) {
5513
            // The element belongs to the session.
5514
            return true;
5515
        }
5516
    }
5517
    return false;
5518
}
5519
5520
/**
5521
 * Replaces "forbidden" characters in a filename string.
5522
 *
5523
 * @param string $filename
5524
 * @param bool $treat_spaces_as_hyphens
5525
 *
5526
 * @return string
5527
 */
5528
function api_replace_dangerous_char($filename, $treat_spaces_as_hyphens = true)
5529
{
5530
    return URLify::filter($filename, 250, '', true, true, false, false, $treat_spaces_as_hyphens);
5531
}
5532
5533
/**
5534
 * Fixes the $_SERVER['REQUEST_URI'] that is empty in IIS6.
5535
 * @author Ivan Tcholakov, 28-JUN-2006.
5536
 */
5537
function api_request_uri() {
5538
    if (!empty($_SERVER['REQUEST_URI'])) {
5539
        return $_SERVER['REQUEST_URI'];
5540
    }
5541
    $uri = $_SERVER['SCRIPT_NAME'];
5542
    if (!empty($_SERVER['QUERY_STRING'])) {
5543
        $uri .= '?'.$_SERVER['QUERY_STRING'];
5544
    }
5545
    $_SERVER['REQUEST_URI'] = $uri;
5546
    return $uri;
5547
}
5548
5549
5550
/** Gets the current access_url id of the Chamilo Platform
5551
 * @author Julio Montoya <[email protected]>
5552
 * @return int access_url_id of the current Chamilo Installation
5553
 */
5554 View Code Duplication
function api_get_current_access_url_id() {
5555
    $access_url_table = Database :: get_main_table(TABLE_MAIN_ACCESS_URL);
5556
    $path = Database::escape_string(api_get_path(WEB_PATH));
5557
    $sql = "SELECT id FROM $access_url_table WHERE url = '".$path."'";
5558
    $result = Database::query($sql);
5559
    if (Database::num_rows($result) > 0) {
5560
        $access_url_id = Database::result($result, 0, 0);
5561
        return $access_url_id;
5562
    }
5563
    //if the url in WEB_PATH was not found, it can only mean that there is
5564
    // either a configuration problem or the first URL has not been defined yet
5565
    // (by default it is http://localhost/). Thus the more sensible thing we can
5566
    // do is return 1 (the main URL) as the user cannot hack this value anyway
5567
    return 1;
5568
}
5569
5570
/**
5571
 * Gets the registered urls from a given user id
5572
 * @author Julio Montoya <[email protected]>
5573
 * @return int user id
5574
 */
5575 View Code Duplication
function api_get_access_url_from_user($user_id) {
5576
    $user_id = intval($user_id);
5577
    $table_url_rel_user = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
5578
    $table_url          = Database :: get_main_table(TABLE_MAIN_ACCESS_URL);
5579
    $sql = "SELECT access_url_id
5580
            FROM $table_url_rel_user url_rel_user
5581
            INNER JOIN $table_url u
5582
            ON (url_rel_user.access_url_id = u.id)
5583
            WHERE user_id = ".intval($user_id);
5584
    $result = Database::query($sql);
5585
    $url_list = array();
5586
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5587
        $url_list[] = $row['access_url_id'];
5588
    }
5589
    return $url_list;
5590
}
5591
5592
/**
5593
 * Gets the status of a user in a course
5594
 * @param int       $user_id
5595
 * @param int    $courseId
5596
 * @return int      user status
5597
 */
5598
function api_get_status_of_user_in_course($user_id, $courseId)
5599
{
5600
    $tbl_rel_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
5601
    if (!empty($user_id) && !empty($courseId)) {
5602
        $user_id = intval($user_id);
5603
        $courseId = intval($courseId);
5604
        $sql = 'SELECT status
5605
                FROM '.$tbl_rel_course_user.'
5606
                WHERE user_id='.$user_id.' AND c_id = '.$courseId;
5607
        $result = Database::query($sql);
5608
        $row_status = Database::fetch_array($result, 'ASSOC');
5609
        return $row_status['status'];
5610
    } else {
5611
        return 0;
5612
    }
5613
}
5614
5615
/**
5616
 * Checks whether the curent user is in a group or not.
5617
 *
5618
 * @param string        The group id - optional (takes it from session if not given)
5619
 * @param string        The course code - optional (no additional check by course if course code is not given)
5620
 * @return boolean
5621
 * @author Ivan Tcholakov
5622
 */
5623
function api_is_in_group($groupIdParam = null, $courseCodeParam = null)
5624
{
5625
    if (!empty($courseCodeParam)) {
5626
        $courseCode = api_get_course_id();
5627
        if (!empty($courseCode)) {
5628
            if ($courseCodeParam != $courseCode) {
5629
                return false;
5630
            }
5631
        } else {
5632
            return false;
5633
        }
5634
    }
5635
5636
    $groupId = api_get_group_id();
5637
5638
    if (isset($groupId) && $groupId != '') {
5639
        if (!empty($groupIdParam)) {
5640
            return $groupIdParam == $groupId;
5641
        } else {
5642
            return true;
5643
        }
5644
    }
5645
5646
    return false;
5647
}
5648
5649
/**
5650
 * Checks whether a secret key is valid
5651
 * @param string $original_key_secret  - secret key from (webservice) client
5652
 * @param string $security_key - security key from Chamilo
5653
 * @return boolean - true if secret key is valid, false otherwise
5654
 */
5655
function api_is_valid_secret_key($original_key_secret, $security_key) {
5656
    return $original_key_secret == sha1($security_key);
5657
}
5658
5659
/**
5660
 * Checks whether a user is into course
5661
 * @param int $course_id - the course id
5662
 * @param int $user_id - the user id
5663
 */
5664
function api_is_user_of_course($course_id, $user_id) {
5665
    $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5666
    $sql = 'SELECT user_id FROM '.$tbl_course_rel_user.'
5667
            WHERE
5668
                c_id ="'.intval($course_id).'" AND
5669
                user_id = "'.intval($user_id).'" AND
5670
                relation_type <> '.COURSE_RELATION_TYPE_RRHH.' ';
5671
    $result = Database::query($sql);
5672
    return Database::num_rows($result) == 1;
5673
}
5674
5675
/**
5676
 * Checks whether the server's operating system is Windows (TM).
5677
 * @return boolean - true if the operating system is Windows, false otherwise
5678
 */
5679
function api_is_windows_os() {
5680
    if (function_exists('php_uname')) {
5681
        // php_uname() exists as of PHP 4.0.2, according to the documentation.
5682
        // We expect that this function will always work for Chamilo 1.8.x.
5683
        $os = php_uname();
5684
    }
5685
    // The following methods are not needed, but let them stay, just in case.
5686
    elseif (isset($_ENV['OS'])) {
5687
        // Sometimes $_ENV['OS'] may not be present (bugs?)
5688
        $os = $_ENV['OS'];
5689
    }
5690
    elseif (defined('PHP_OS')) {
5691
        // PHP_OS means on which OS PHP was compiled, this is why
5692
        // using PHP_OS is the last choice for detection.
5693
        $os = PHP_OS;
5694
    } else {
5695
        return false;
5696
    }
5697
    return strtolower(substr((string)$os, 0, 3 )) == 'win';
5698
}
5699
5700
/**
5701
 * This function informs whether the sent request is XMLHttpRequest
5702
 */
5703
function api_is_xml_http_request() {
5704
    return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
5705
}
5706
5707
/**
5708
 * This wrapper function has been implemented for avoiding some known problems about the function getimagesize().
5709
 * @link http://php.net/manual/en/function.getimagesize.php
5710
 * @link http://www.dokeos.com/forum/viewtopic.php?t=12345
5711
 * @link http://www.dokeos.com/forum/viewtopic.php?t=16355
5712
 * @return integer
5713
 */
5714
function api_getimagesize($path) {
5715
    $image = new Image($path);
5716
    return $image->get_image_size();
5717
}
5718
5719
/**
5720
 * This function resizes an image, with preserving its proportions (or aspect ratio).
5721
 * @author Ivan Tcholakov, MAY-2009.
5722
 * @param int $image            System path or URL of the image
5723
 * @param int $target_width     Targeted width
5724
 * @param int $target_height    Targeted height
5725
 * @return array                Calculated new width and height
5726
 */
5727
function api_resize_image($image, $target_width, $target_height) {
5728
    $image_properties = api_getimagesize($image);
5729
    return api_calculate_image_size($image_properties['width'], $image_properties['height'], $target_width, $target_height);
5730
}
5731
5732
/**
5733
 * This function calculates new image size, with preserving image's proportions (or aspect ratio).
5734
 * @author Ivan Tcholakov, MAY-2009.
5735
 * @author The initial idea has been taken from code by Patrick Cool, MAY-2004.
5736
 * @param int $image_width      Initial width
5737
 * @param int $image_height     Initial height
5738
 * @param int $target_width     Targeted width
5739
 * @param int $target_height    Targeted height
5740
 * @return array                Calculated new width and height
5741
 */
5742
function api_calculate_image_size($image_width, $image_height, $target_width, $target_height) {
5743
    // Only maths is here.
5744
    $result = array('width' => $image_width, 'height' => $image_height);
5745
    if ($image_width <= 0 || $image_height <= 0) {
5746
        return $result;
5747
    }
5748
    $resize_factor_width = $target_width / $image_width;
5749
    $resize_factor_height = $target_height / $image_height;
5750
    $delta_width = $target_width - $image_width * $resize_factor_height;
5751
    $delta_height = $target_height - $image_height * $resize_factor_width;
5752
    if ($delta_width > $delta_height) {
5753
        $result['width'] = ceil($image_width * $resize_factor_height);
5754
        $result['height'] = ceil($image_height * $resize_factor_height);
5755
    }
5756
    elseif ($delta_width < $delta_height) {
5757
        $result['width'] = ceil($image_width * $resize_factor_width);
5758
        $result['height'] = ceil($image_height * $resize_factor_width);
5759
    }
5760
    else {
5761
        $result['width'] = ceil($target_width);
5762
        $result['height'] = ceil($target_height);
5763
    }
5764
    return $result;
5765
}
5766
5767
/**
5768
 * Returns a list of Chamilo's tools or
5769
 * checks whether a given identificator is a valid Chamilo's tool.
5770
 * @author Isaac flores paz
5771
 * @param string The tool name to filter
5772
 * @return mixed Filtered string or array
5773
 */
5774
function api_get_tools_lists($my_tool = null) {
5775
    $tools_list = array(
5776
        TOOL_DOCUMENT,
5777
        TOOL_THUMBNAIL,
5778
        TOOL_HOTPOTATOES,
5779
        TOOL_CALENDAR_EVENT,
5780
        TOOL_LINK,
5781
        TOOL_COURSE_DESCRIPTION,
5782
        TOOL_SEARCH,
5783
        TOOL_LEARNPATH,
5784
        TOOL_ANNOUNCEMENT,
5785
        TOOL_FORUM,
5786
        TOOL_THREAD,
5787
        TOOL_POST,
5788
        TOOL_DROPBOX,
5789
        TOOL_QUIZ,
5790
        TOOL_USER,
5791
        TOOL_GROUP,
5792
        TOOL_BLOGS,
5793
        TOOL_CHAT,
5794
        TOOL_STUDENTPUBLICATION,
5795
        TOOL_TRACKING,
5796
        TOOL_HOMEPAGE_LINK,
5797
        TOOL_COURSE_SETTING,
5798
        TOOL_BACKUP,
5799
        TOOL_COPY_COURSE_CONTENT,
5800
        TOOL_RECYCLE_COURSE,
5801
        TOOL_COURSE_HOMEPAGE,
5802
        TOOL_COURSE_RIGHTS_OVERVIEW,
5803
        TOOL_UPLOAD,
5804
        TOOL_COURSE_MAINTENANCE,
5805
        TOOL_SURVEY,
5806
        TOOL_WIKI,
5807
        TOOL_GLOSSARY,
5808
        TOOL_GRADEBOOK,
5809
        TOOL_NOTEBOOK,
5810
        TOOL_ATTENDANCE,
5811
        TOOL_COURSE_PROGRESS,
5812
    );
5813
    if (empty($my_tool)) {
5814
        return $tools_list;
5815
    }
5816
    return in_array($my_tool, $tools_list) ? $my_tool : '';
5817
}
5818
5819
/**
5820
 * Checks whether we already approved the last version term and condition
5821
 * @param int user id
5822
 * @return bool true if we pass false otherwise
5823
 */
5824
function api_check_term_condition($user_id)
5825
{
5826
    if (api_get_setting('allow_terms_conditions') == 'true') {
5827
        //check if exists terms and conditions
5828
        if (LegalManager::count() == 0) {
5829
5830
            return true;
5831
        }
5832
5833
        $extraFieldValue = new ExtraFieldValue('user');
5834
        $data = $extraFieldValue->get_values_by_handler_and_field_variable(
5835
            $user_id,
5836
            'legal_accept'
5837
        );
5838
5839
        if (!empty($data) && isset($data['value'])) {
5840
            $rowv = $data['value'];
5841
            $user_conditions = explode(':', $rowv);
5842
            $version = $user_conditions[0];
5843
            $lang_id = $user_conditions[1];
5844
            $real_version = LegalManager::get_last_version($lang_id);
5845
5846
            return $version >= $real_version;
5847
        }
5848
        return false;
5849
    }
5850
    return false;
5851
}
5852
5853
/**
5854
 * Gets all information of a tool into course
5855
 * @param int The tool id
5856
 * @return array
5857
 */
5858
function api_get_tool_information($tool_id) {
5859
    $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
5860
    $course_id = api_get_course_int_id();
5861
    $sql = "SELECT * FROM $t_tool WHERE c_id = $course_id AND id = ".intval($tool_id);
5862
    $rs  = Database::query($sql);
5863
    return Database::fetch_array($rs);
5864
}
5865
5866
/**
5867
 * Gets all information of a tool into course
5868
 * @param int The tool id
5869
 * @return array
5870
 */
5871 View Code Duplication
function api_get_tool_information_by_name($name) {
5872
    $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
5873
    $course_id = api_get_course_int_id();
5874
    $sql = "SELECT * FROM $t_tool
5875
            WHERE c_id = $course_id  AND name = '".Database::escape_string($name)."' ";
5876
    $rs  = Database::query($sql);
5877
    return Database::fetch_array($rs, 'ASSOC');
5878
}
5879
5880
/**
5881
 * Function used to protect a "global" admin script.
5882
 * The function blocks access when the user has no global platform admin rights.
5883
 * Global admins are the admins that are registered in the main.admin table
5884
 * AND the users who have access to the "principal" portal.
5885
 * That means that there is a record in the main.access_url_rel_user table
5886
 * with his user id and the access_url_id=1
5887
 *
5888
 * @author Julio Montoya
5889
 * @param integer $user_id
5890
 */
5891
function api_is_global_platform_admin($user_id = null)
5892
{
5893
    $user_id = intval($user_id);
5894
    if (empty($user_id)) {
5895
        $user_id = api_get_user_id();
5896
    }
5897
    if (api_is_platform_admin_by_id($user_id)) {
5898
        $urlList = api_get_access_url_from_user($user_id);
5899
        // The admin is registered in the first "main" site with access_url_id = 1
5900
        if (in_array(1, $urlList)) {
5901
            return true;
5902
        } else {
5903
            return false;
5904
        }
5905
    }
5906
    return false;
5907
}
5908
5909
/**
5910
 * @param int $admin_id_to_check
5911
 * @param int  $my_user_id
5912
 * @param bool $allow_session_admin
5913
 * @return bool
5914
 */
5915
function api_global_admin_can_edit_admin($admin_id_to_check, $my_user_id = null, $allow_session_admin = false)
5916
{
5917
    if (empty($my_user_id)) {
5918
        $my_user_id = api_get_user_id();
5919
    }
5920
5921
    $iam_a_global_admin = api_is_global_platform_admin($my_user_id);
5922
    $user_is_global_admin = api_is_global_platform_admin($admin_id_to_check);
5923
5924
    if ($iam_a_global_admin) {
5925
        // Global admin can edit everything
5926
        return true;
5927
    } else {
5928
        // If i'm a simple admin
5929
        $is_platform_admin = api_is_platform_admin_by_id($my_user_id);
5930
5931
        if ($allow_session_admin) {
5932
            $is_platform_admin = api_is_platform_admin_by_id($my_user_id) || (api_get_user_status($my_user_id) == SESSIONADMIN);
5933
        }
5934
5935
        if ($is_platform_admin) {
5936
            if ($user_is_global_admin) {
5937
                return false;
5938
            } else {
5939
                return true;
5940
            }
5941
        } else {
5942
            return false;
5943
        }
5944
    }
5945
}
5946
5947
/**
5948
 * @param int $admin_id_to_check
5949
 * @param int  $my_user_id
5950
 * @param bool $allow_session_admin
5951
 * @return boolean|null
5952
 */
5953
function api_protect_super_admin($admin_id_to_check, $my_user_id = null, $allow_session_admin = false)
5954
{
5955
    if (api_global_admin_can_edit_admin($admin_id_to_check, $my_user_id, $allow_session_admin)) {
5956
        return true;
5957
    } else {
5958
        api_not_allowed();
5959
    }
5960
}
5961
5962
/**
5963
 * Function used to protect a global admin script.
5964
 * The function blocks access when the user has no global platform admin rights.
5965
 * See also the api_is_global_platform_admin() function wich defines who's a "global" admin
5966
 *
5967
 * @author Julio Montoya
5968
 */
5969
function api_protect_global_admin_script() {
5970
    if (!api_is_global_platform_admin()) {
5971
        api_not_allowed();
5972
        return false;
5973
    }
5974
    return true;
5975
}
5976
5977
/**
5978
 * Get active template
5979
 * @param string    theme type (optional: default)
5980
 * @param string    path absolute(abs) or relative(rel) (optional:rel)
5981
 * @return string   actived template path
5982
 */
5983
function api_get_template($path_type = 'rel') {
5984
    $path_types = array('rel', 'abs');
5985
    $template_path = '';
5986
    if (in_array($path_type, $path_types)) {
5987
        if ($path_type == 'rel') {
5988
            $template_path = api_get_path(SYS_TEMPLATE_PATH);
5989
        } else {
5990
            $template_path = api_get_path(WEB_TEMPLATE_PATH);
5991
        }
5992
    }
5993
    $actived_theme = 'default';
5994
    if (api_get_setting('active_template')) {
5995
        $actived_theme = api_get_setting('active_template');
5996
    }
5997
    $actived_theme_path = $template_path.$actived_theme.DIRECTORY_SEPARATOR;
5998
    return $actived_theme_path;
5999
}
6000
6001
/**
6002
 * Check browser support for type files
6003
 * This function check if the users browser support a file format or
6004
 * return the current browser and major ver when $format=check_browser
6005
 * @param string $format
6006
 *
6007
 * @return bool or return text array if $format=check_browser
6008
 * @author Juan Carlos Raña Trabado
6009
 */
6010
function api_browser_support($format = '')
6011
{
6012
    $browser = new Browser();
6013
    $current_browser = $browser->getBrowser();
6014
    $a_versiontemp = explode('.', $browser->getVersion());
6015
    $current_majorver = $a_versiontemp[0];
6016
6017
    // Native svg support
6018
    if ($format == 'svg') {
6019
        if (($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6020
            ($current_browser == 'Firefox' && $current_majorver > 1) ||
6021
            ($current_browser == 'Safari' && $current_majorver >= 4) ||
6022
            ($current_browser == 'Chrome' && $current_majorver >= 1) ||
6023
            ($current_browser == 'Opera' && $current_majorver >= 9)
6024
        ) {
6025
            return true;
6026
        } else {
6027
            return false;
6028
        }
6029
    } elseif ($format == 'pdf') {
6030
        //native pdf support
6031
        if ($current_browser == 'Chrome' && $current_majorver >= 6) {
6032
            return true;
6033
        } else {
6034
            return false;
6035
        }
6036
    } elseif ($format == 'tif' || $format == 'tiff') {
6037
        //native tif support
6038
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6039
            return true;
6040
        } else {
6041
            return false;
6042
        }
6043 View Code Duplication
    } elseif ($format == 'ogg' || $format == 'ogx' || $format == 'ogv' || $format == 'oga') {
6044
        //native ogg, ogv,oga support
6045
        if (($current_browser == 'Firefox' && $current_majorver >= 3) ||
6046
            ($current_browser == 'Chrome' && $current_majorver >= 3) ||
6047
            ($current_browser == 'Opera' && $current_majorver >= 9)) {
6048
            return true;
6049
        } else {
6050
            return false;
6051
        }
6052
    } elseif ($format == 'mpg' || $format == 'mpeg') {
6053
        //native mpg support
6054
        if (($current_browser == 'Safari' && $current_majorver >= 5)) {
6055
            return true;
6056
        } else {
6057
            return false;
6058
        }
6059
    } elseif ($format == 'mp4') {
6060
        //native mp4 support (TODO: Android, iPhone)
6061
        if ($current_browser == 'Android' || $current_browser == 'iPhone') {
6062
            return true;
6063
        } else {
6064
            return false;
6065
        }
6066
    } elseif ($format == 'mov') {
6067
        //native mov support( TODO:check iPhone)
6068
        if ($current_browser == 'Safari' && $current_majorver >= 5 || $current_browser == 'iPhone') {
6069
            return true;
6070
        } else {
6071
            return false;
6072
        }
6073
    } elseif ($format == 'avi') {
6074
        //native avi support
6075
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6076
            return true;
6077
        } else {
6078
            return false;
6079
        }
6080
    } elseif ($format == 'wmv') {
6081
        //native wmv support
6082
        if ($current_browser == 'Firefox' && $current_majorver >= 4) {
6083
            return true;
6084
        } else {
6085
            return false;
6086
        }
6087 View Code Duplication
    } elseif ($format == 'webm') {
6088
        //native webm support (TODO:check IE9, Chrome9, Android)
6089
        if (($current_browser == 'Firefox' && $current_majorver >= 4) ||
6090
            ($current_browser == 'Opera' && $current_majorver >= 9) ||
6091
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6092
            ($current_browser == 'Chrome' && $current_majorver >= 9) ||
6093
            $current_browser == 'Android'
6094
        ) {
6095
            return true;
6096
        } else {
6097
            return false;
6098
        }
6099
    } elseif ($format == 'wav') {
6100
        //native wav support (only some codecs !)
6101
        if (($current_browser == 'Firefox' && $current_majorver >= 4) ||
6102
            ($current_browser == 'Safari' && $current_majorver >= 5) ||
6103
            ($current_browser == 'Opera' && $current_majorver >= 9) ||
6104
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6105
            ($current_browser == 'Chrome' && $current_majorver > 9) ||
6106
            $current_browser == 'Android' ||
6107
            $current_browser == 'iPhone'
6108
        ) {
6109
            return true;
6110
        } else {
6111
            return false;
6112
        }
6113
    } elseif ($format == 'mid' || $format == 'kar') {
6114
        //native midi support (TODO:check Android)
6115
        if ($current_browser == 'Opera' && $current_majorver >= 9 || $current_browser == 'Android') {
6116
            return true;
6117
        } else {
6118
            return false;
6119
        }
6120
    } elseif ($format == 'wma') {
6121
        //native wma support
6122
        if ($current_browser == 'Firefox' && $current_majorver >= 4) {
6123
            return true;
6124
        } else {
6125
            return false;
6126
        }
6127
    } elseif ($format == 'au') {
6128
        //native au support
6129
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6130
            return true;
6131
        } else {
6132
            return false;
6133
        }
6134 View Code Duplication
    } elseif ($format == 'mp3') {
6135
        //native mp3 support (TODO:check Android, iPhone)
6136
        if (($current_browser == 'Safari' && $current_majorver >= 5) ||
6137
            ($current_browser == 'Chrome' && $current_majorver >= 6) ||
6138
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6139
            $current_browser == 'Android' ||
6140
            $current_browser == 'iPhone' ||
6141
            $current_browser == 'Firefox'
6142
        ) {
6143
            return true;
6144
        } else {
6145
            return false;
6146
        }
6147
    } elseif ($format == "check_browser") {
6148
        $array_check_browser = array($current_browser, $current_majorver);
6149
        return $array_check_browser;
6150
    } else {
6151
        return false;
6152
    }
6153
}
6154
6155
/**
6156
 * This function checks if exist path and file browscap.ini
6157
 * In order for this to work, your browscap configuration setting in php.ini
6158
 * must point to the correct location of the browscap.ini file on your system
6159
 * http://php.net/manual/en/function.get-browser.php
6160
 *
6161
 * @return bool
6162
 *
6163
 * @author Juan Carlos Raña Trabado
6164
 */
6165
function api_check_browscap() {
6166
    $setting = ini_get('browscap');
6167
    if ($setting) {
6168
        $browser = get_browser($_SERVER['HTTP_USER_AGENT'], true);
6169
        if (strpos($setting, 'browscap.ini') && !empty($browser)) {
6170
            return true;
6171
        }
6172
    }
6173
    return false;
6174
}
6175
6176
/**
6177
 * Returns the <script> HTML tag
6178
 */
6179
function api_get_js($file) {
6180
    return '<script type="text/javascript" src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/'.$file.'"></script>'."\n";
6181
}
6182
6183
/**
6184
 * Returns the <script> HTML tag
6185
 * @return string
6186
 */
6187
function api_get_asset($file)
6188
{
6189
    return '<script type="text/javascript" src="'.api_get_path(WEB_PATH).'web/assets/'.$file.'"></script>'."\n";
6190
}
6191
6192
/**
6193
 * Returns the <script> HTML tag
6194
 * @return string
6195
 */
6196
function api_get_css_asset($file, $media = 'screen')
6197
{
6198
    return '<link href="'.api_get_path(WEB_PATH).'web/assets/'.$file.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
6199
}
6200
6201
/**
6202
 * Returns the <link> HTML tag
6203
 * @param string $file
6204
 */
6205
function api_get_css($file, $media = 'screen') {
6206
    return '<link href="'.$file.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
6207
}
6208
6209
/**
6210
 * Returns the js header to include the jquery library
6211
 */
6212
function api_get_jquery_js()
6213
{
6214
    return api_get_asset('jquery/dist/jquery.min.js');
6215
}
6216
6217
/**
6218
 * Returns the jquery path
6219
 * @return string
6220
 */
6221
function api_get_jquery_web_path()
6222
{
6223
    return api_get_path(WEB_PATH).'web/assets/jquery/dist/jquery.min.js';
6224
}
6225
6226
/**
6227
 * @return string
6228
 */
6229
function api_get_jquery_ui_js_web_path()
6230
{
6231
    return api_get_path(WEB_PATH).'web/assets/jquery-ui/jquery-ui.min.js';
6232
}
6233
6234
/**
6235
 * @return string
6236
 */
6237
function api_get_jquery_ui_css_web_path()
6238
{
6239
    return api_get_path(WEB_PATH).'web/assets/jquery-ui/themes/smoothness/jquery-ui.min.css';
6240
}
6241
6242
/**
6243
 * Returns the jquery-ui library js headers
6244
 * @param   bool    add the jqgrid library
6245
 * @return  string  html tags
6246
 *
6247
 */
6248
function api_get_jquery_ui_js($include_jqgrid = false) {
6249
    $libraries = array();
6250
    if ($include_jqgrid) {
6251
       $libraries[]='jqgrid';
6252
    }
6253
    return api_get_jquery_libraries_js($libraries);
6254
}
6255
6256
function api_get_jqgrid_js() {
6257
    return api_get_jquery_libraries_js(array('jqgrid'));
6258
}
6259
6260
/**
6261
 * Returns the jquery library js and css headers
6262
 *
6263
 * @param   array   list of jquery libraries supported jquery-ui, jqgrid
6264
 * @param   bool    add the jquery library
6265
 * @return  string  html tags
6266
 *
6267
 */
6268
function api_get_jquery_libraries_js($libraries) {
6269
    $js = '';
6270
    $js_path = api_get_path(WEB_LIBRARY_PATH).'javascript/';
6271
6272
    //jqgrid js and css
6273
    if (in_array('jqgrid', $libraries)) {
6274
        $languaje   = 'en';
6275
        $platform_isocode = strtolower(api_get_language_isocode());
6276
6277
        //languages supported by jqgrid see files in main/inc/lib/javascript/jqgrid/js/i18n
6278
        $jqgrid_langs = array(
6279
            'bg', 'bg1251', 'cat','cn','cs','da','de','el','en','es','fa','fi','fr','gl','he','hu','is','it','ja','nl','no','pl','pt-br','pt','ro','ru','sk','sr','sv','tr','ua'
6280
        );
6281
6282
        if (in_array($platform_isocode, $jqgrid_langs)) {
6283
            $languaje = $platform_isocode;
6284
        }
6285
        //$js .= '<link rel="stylesheet" href="'.$js_path.'jqgrid/css/ui.jqgrid.css" type="text/css">';
6286
        $js .= api_get_css($js_path.'jqgrid/css/ui.jqgrid.css');
6287
        $js .= api_get_js('jqgrid/js/i18n/grid.locale-'.$languaje.'.js');
6288
        $js .= api_get_js('jqgrid/js/jquery.jqGrid.min.js');
6289
    }
6290
6291
    //Document multiple upload funcionality
6292
    if (in_array('jquery-upload', $libraries)) {
6293
6294
        $js .= api_get_asset('blueimp-load-image/js/load-image.all.min.js');
6295
        $js .= api_get_asset('blueimp-canvas-to-blob/js/canvas-to-blob.min.js');
6296
        $js .= api_get_asset('jquery-file-upload/js/jquery.iframe-transport.js');
6297
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload.js');
6298
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-process.js');
6299
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-image.js');
6300
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-audio.js');
6301
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-video.js');
6302
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-validate.js');
6303
6304
        $js .= api_get_css(api_get_path(WEB_PATH).'web/assets/jquery-file-upload/css/jquery.fileupload.css');
6305
        $js .= api_get_css(api_get_path(WEB_PATH).'web/assets/jquery-file-upload/css/jquery.fileupload-ui.css');
6306
    }
6307
6308
    // jquery datepicker
6309
    if (in_array('datepicker', $libraries)) {
6310
        $languaje   = 'en-GB';
6311
        $platform_isocode = strtolower(api_get_language_isocode());
6312
6313
        // languages supported by jqgrid see files in main/inc/lib/javascript/jqgrid/js/i18n
6314
        $datapicker_langs = array(
6315
            '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'
6316
        );
6317
        if (in_array($platform_isocode, $datapicker_langs)) {
6318
            $languaje = $platform_isocode;
6319
        }
6320
6321
        $js .= api_get_js('jquery-ui/jquery-ui-i18n.min.js');
6322
        $script = '<script>
6323
        $(function(){
6324
            $.datepicker.setDefaults($.datepicker.regional["'.$languaje.'"]);
6325
            $.datepicker.regional["local"] = $.datepicker.regional["'.$languaje.'"];
6326
        });
6327
        </script>
6328
        ';
6329
        $js .= $script;
6330
    }
6331
    return $js;
6332
}
6333
6334
/**
6335
 * Returns the course's URL
6336
 *
6337
 * This function relies on api_get_course_info()
6338
 * @param   string  The course code - optional (takes it from session if not given)
6339
 * @param   int     The session id  - optional (takes it from session if not given)
6340
 * @param integer $session_id
6341
 * @return  string|null   The URL of the course or null if something does not work
6342
 * @author  Julio Montoya <[email protected]>
6343
 */
6344
function api_get_course_url($course_code = null, $session_id = null)
6345
{
6346
    if (empty($course_code)) {
6347
        $course_info = api_get_course_info();
6348
    } else {
6349
        $course_info = api_get_course_info($course_code);
6350
    }
6351
    if (empty($session_id)) {
6352
        $session_url = '?id_session='.api_get_session_id();
6353
    } else {
6354
        $session_url = '?id_session='.intval($session_id);
6355
    }
6356
    /*
6357
    if (empty($group_id)) {
6358
        $group_url = '&gidReq='.api_get_group_id();
6359
    } else {
6360
        $group_url = '&gidReq='.intval($group_id);
6361
    }*/
6362
    if (!empty($course_info['path'])) {
6363
        return api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php'.$session_url;
6364
    }
6365
    return null;
6366
}
6367
6368
/**
6369
 *
6370
 * Check if the current portal has the $_configuration['multiple_access_urls'] parameter on
6371
 * @return bool true if multi site is enabled
6372
 *
6373
 **/
6374
function api_get_multiple_access_url() {
6375
    global $_configuration;
6376
    if (isset($_configuration['multiple_access_urls']) && $_configuration['multiple_access_urls']) {
6377
        return true;
6378
    }
6379
    return false;
6380
}
6381
6382
/**
6383
 * @return bool
6384
 */
6385
function api_is_multiple_url_enabled() {
6386
    return api_get_multiple_access_url();
6387
}
6388
6389
/**
6390
 * Returns a md5 unique id
6391
 * @todo add more parameters
6392
 */
6393
function api_get_unique_id() {
6394
    $id = md5(time().uniqid().api_get_user_id().api_get_course_id().api_get_session_id());
6395
    return $id;
6396
}
6397
6398
/**
6399
 * Get home path
6400
 * @return string
6401
 */
6402
function api_get_home_path()
6403
{
6404
    // FIX : Start the routing determination from central path definition
6405
    $home = api_get_path(SYS_HOME_PATH);
6406
    if (api_get_multiple_access_url()) {
6407
        $access_url_id = api_get_current_access_url_id();
6408
        $url_info = api_get_access_url($access_url_id);
6409
        $url = api_remove_trailing_slash(preg_replace('/https?:\/\//i', '', $url_info['url']));
6410
        $clean_url = api_replace_dangerous_char($url);
6411
        $clean_url = str_replace('/', '-', $clean_url);
6412
        $clean_url .= '/';
6413
        if ($clean_url != 'localhost/') {
6414
            // means that the multiple URL was not well configured we don't rename the $home variable
6415
            return "{$home}{$clean_url}";
6416
        }
6417
    }
6418
6419
    return $home;
6420
}
6421
6422
/**
6423
 *
6424
 * @param int Course id
6425
 * @param int tool id: TOOL_QUIZ, TOOL_FORUM, TOOL_STUDENTPUBLICATION, TOOL_LEARNPATH
6426
 * @param int the item id (tool id, exercise id, lp id)
6427
 *
6428
 */
6429
function api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code = null) {
6430
    if (api_is_platform_admin()) {
6431
        return false;
6432
    }
6433
    if (api_get_setting('gradebook_locking_enabled') == 'true') {
6434
        if (empty($course_code)) {
6435
            $course_code = api_get_course_id();
6436
        }
6437
        $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
6438
        $item_id = intval($item_id);
6439
        $link_type = intval($link_type);
6440
        $course_code = Database::escape_string($course_code);
6441
        $sql = "SELECT locked FROM $table
6442
                WHERE locked = 1 AND ref_id = $item_id AND type = $link_type AND course_code = '$course_code' ";
6443
        $result = Database::query($sql);
6444
        if (Database::num_rows($result)) {
6445
            return true;
6446
        }
6447
    }
6448
    return false;
6449
}
6450
6451
/**
6452
 * Blocks a page if the item was added in a gradebook
6453
 *
6454
 * @param int       exercise id, work id, thread id,
6455
 * @param int       LINK_EXERCISE, LINK_STUDENTPUBLICATION, LINK_LEARNPATH LINK_FORUM_THREAD, LINK_ATTENDANCE
6456
 * see gradebook/lib/be/linkfactory
6457
 * @param string    course code
6458
 * @return false|null
6459
 */
6460
function api_block_course_item_locked_by_gradebook($item_id, $link_type, $course_code = null) {
6461
    if (api_is_platform_admin()) {
6462
        return false;
6463
    }
6464
6465
    if (api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code)) {
6466
        $message = Display::return_message(get_lang('ResourceLockedByGradebook'), 'warning');
6467
        api_not_allowed(true, $message);
6468
    }
6469
}
6470
/**
6471
 * Checks the PHP version installed is enough to run Chamilo
6472
 * @param string Include path (used to load the error page)
6473
 * @return void
6474
 */
6475
function api_check_php_version($my_inc_path = null) {
6476
    if (!function_exists('version_compare') || version_compare( phpversion(), REQUIRED_PHP_VERSION, '<')) {
6477
        $global_error_code = 1;
6478
        // Incorrect PHP version
6479
        $global_page = $my_inc_path.'global_error_message.inc.php';
6480
        if (file_exists($global_page)) {
6481
            require $global_page;
6482
        }
6483
        exit;
6484
    }
6485
}
6486
/**
6487
 * Checks whether the Archive directory is present and writeable. If not,
6488
 * prints a warning message.
6489
 */
6490
function api_check_archive_dir() {
6491 View Code Duplication
    if (is_dir(api_get_path(SYS_ARCHIVE_PATH)) && !is_writable(api_get_path(SYS_ARCHIVE_PATH))) {
6492
        $message = Display::return_message(get_lang('ArchivesDirectoryNotWriteableContactAdmin'),'warning');
6493
        api_not_allowed(true, $message);
6494
    }
6495
}
6496
/**
6497
 * Returns an array of global configuration settings which should be ignored
6498
 * when printing the configuration settings screens
6499
 * @return array Array of strings, each identifying one of the excluded settings
6500
 */
6501
function api_get_locked_settings() {
6502
    return array(
6503
        'server_type',
6504
        'permanently_remove_deleted_files',
6505
        'account_valid_duration',
6506
        'service_ppt2lp',
6507
        'wcag_anysurfer_public_pages',
6508
        'upload_extensions_list_type',
6509
        'upload_extensions_blacklist',
6510
        'upload_extensions_whitelist',
6511
        'upload_extensions_skip',
6512
        'upload_extensions_replace_by',
6513
        'hide_dltt_markup',
6514
        'split_users_upload_directory',
6515
        'permissions_for_new_directories',
6516
        'permissions_for_new_files',
6517
        'platform_charset',
6518
        'ldap_description',
6519
        'cas_activate',
6520
        'cas_server',
6521
        'cas_server_uri',
6522
        'cas_port',
6523
        'cas_protocol',
6524
        'cas_add_user_activate',
6525
        'update_user_info_cas_with_ldap',
6526
        'languagePriority1',
6527
        'languagePriority2',
6528
        'languagePriority3',
6529
        'languagePriority4',
6530
        'login_is_email',
6531
        'chamilo_database_version'
6532
    );
6533
}
6534
6535
/**
6536
 * Checks if the user is corrently logged in. Returns the user ID if he is, or
6537
 * false if he isn't. If the user ID is given and is an integer, then the same
6538
 * ID is simply returned
6539
 * @param  integer User ID
6540
 * @return boolean Integer User ID is logged in, or false otherwise
6541
 */
6542
function api_user_is_login($user_id = null) {
6543
    $user_id = empty($user_id) ? api_get_user_id() : intval($user_id);
6544
    return $user_id && !api_is_anonymous();
6545
}
6546
6547
/**
6548
 * Guess the real ip for register in the database, even in reverse proxy cases.
6549
 * To be recognized, the IP has to be found in either $_SERVER['REMOTE_ADDR'] or
6550
 * in $_SERVER['HTTP_X_FORWARDED_FOR'], which is in common use with rproxies.
6551
 * @return string the user's real ip (unsafe - escape it before inserting to db)
6552
 * @author Jorge Frisancho Jibaja <[email protected]>, USIL - Some changes to allow the use of real IP using reverse proxy
6553
 * @version CEV CHANGE 24APR2012
6554
 */
6555
function api_get_real_ip(){
6556
    // Guess the IP if behind a reverse proxy
6557
    global $debug;
6558
    $ip = trim($_SERVER['REMOTE_ADDR']);
6559
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
6560
        if (preg_match('/,/', $_SERVER['HTTP_X_FORWARDED_FOR'])) {
6561
            @list($ip1, $ip2) = @explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
6562
        } else {
6563
            $ip1 = $_SERVER['HTTP_X_FORWARDED_FOR'];
6564
        }
6565
        $ip = trim($ip1);
6566
    }
6567
    if (!empty($debug)) error_log('Real IP: '.$ip);
6568
    return $ip;
6569
}
6570
6571
/**
6572
 * Checks whether an IP is included inside an IP range
6573
 * @param string IP address
6574
 * @param string IP range
6575
 * @param string $ip
6576
 * @return bool True if IP is in the range, false otherwise
6577
 * @author claudiu at cnixs dot com  on http://www.php.net/manual/fr/ref.network.php#55230
6578
 * @author Yannick Warnier for improvements and managment of multiple ranges
6579
 * @todo check for IPv6 support
6580
 */
6581
function api_check_ip_in_range($ip,$range)
6582
{
6583
    if (empty($ip) or empty($range)) {
6584
        return false;
6585
    }
6586
    $ip_ip = ip2long ($ip);
6587
    // divide range param into array of elements
6588
    if (strpos($range,',')!==false) {
6589
        $ranges = explode(',',$range);
6590
    } else {
6591
        $ranges = array($range);
6592
    }
6593
    foreach ($ranges as $range) {
6594
        $range = trim($range);
6595
        if (empty($range)) { continue; }
6596
        if (strpos($range,'/')===false) {
6597
            if (strcmp($ip,$range)===0) {
6598
                return true; // there is a direct IP match, return OK
6599
            }
6600
            continue; //otherwise, get to the next range
6601
        }
6602
        // the range contains a "/", so analyse completely
6603
        list ($net, $mask) = explode("/", $range);
6604
6605
        $ip_net = ip2long ($net);
6606
        // mask binary magic
6607
        $ip_mask = ~((1 << (32 - $mask)) - 1);
6608
6609
        $ip_ip_net = $ip_ip & $ip_mask;
6610
        if ($ip_ip_net == $ip_net) {
6611
            return true;
6612
        }
6613
    }
6614
6615
    return false;
6616
}
6617
6618
function api_check_user_access_to_legal($course_visibility) {
6619
    $course_visibility_list = array(COURSE_VISIBILITY_OPEN_WORLD, COURSE_VISIBILITY_OPEN_PLATFORM);
6620
    return in_array($course_visibility, $course_visibility_list) || api_is_drh();
6621
}
6622
6623
/**
6624
 * Checks if the global chat is enabled or not
6625
 *
6626
 * @return bool
6627
 */
6628
function api_is_global_chat_enabled()
6629
{
6630
    return
6631
        !api_is_anonymous() &&
6632
        api_get_setting('allow_global_chat') == 'true' &&
6633
        api_get_setting('allow_social_tool') == 'true';
6634
}
6635
6636
/**
6637
 * @todo Fix tool_visible_by_default_at_creation labels
6638
 * @todo Add sessionId parameter to avoid using context
6639
 *
6640
 * @param int $item_id
6641
 * @param int $tool_id
6642
 * @param int $group_id iid
6643
 * @param array $courseInfo
6644
 */
6645
function api_set_default_visibility(
6646
    $item_id,
6647
    $tool_id,
6648
    $group_id = 0,
6649
    $courseInfo = array(),
6650
    $sessionId = 0,
6651
    $userId = 0
6652
) {
6653
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
6654
    $courseId = $courseInfo['real_id'];
6655
    $courseCode = $courseInfo['code'];
6656
    $sessionId = empty($sessionId) ? api_get_session_id() : $sessionId;
6657
    $userId = empty($userId) ? api_get_user_id() : $userId;
6658
6659
    if (empty($group_id)) {
6660
        $group_id = api_get_group_id();
6661
    }
6662
6663
    $groupInfo = GroupManager::get_group_properties($group_id);
6664
    $groupIid = 0;
6665
    if ($groupInfo) {
6666
        $groupIid = $groupInfo['iid'];
6667
    }
6668
6669
    $original_tool_id = $tool_id;
6670
6671
    switch ($tool_id) {
6672
        case TOOL_LINK:
6673
        case TOOL_LINK_CATEGORY:
6674
            $tool_id = 'links';
6675
            break;
6676
        case TOOL_DOCUMENT:
6677
            $tool_id = 'documents';
6678
            break;
6679
        case TOOL_LEARNPATH:
6680
            $tool_id = 'learning';
6681
            break;
6682
        case TOOL_ANNOUNCEMENT:
6683
            $tool_id = 'announcements';
6684
            break;
6685
        case TOOL_FORUM:
6686
        case TOOL_FORUM_CATEGORY:
6687
        case TOOL_FORUM_THREAD:
6688
            $tool_id = 'forums';
6689
            break;
6690
        case TOOL_QUIZ:
6691
            $tool_id = 'quiz';
6692
            break;
6693
    }
6694
    $setting = api_get_setting('tool_visible_by_default_at_creation');
6695
6696
    if (isset($setting[$tool_id])) {
6697
        $visibility = 'invisible';
6698
        if ($setting[$tool_id] == 'true') {
6699
            $visibility = 'visible';
6700
        }
6701
6702
        // Read the portal and course default visibility
6703
        if ($tool_id == 'documents') {
6704
            $visibility = DocumentManager::getDocumentDefaultVisibility($courseCode);
6705
        }
6706
6707
        api_item_property_update(
6708
            $courseInfo,
6709
            $original_tool_id,
6710
            $item_id,
6711
            $visibility,
6712
            $userId,
6713
            $groupIid,
6714
            null,
6715
            null,
6716
            null,
6717
            api_get_session_id()
6718
        );
6719
6720
        // Fixes default visibility for tests
6721
6722
        switch ($original_tool_id) {
6723
            case TOOL_QUIZ:
6724
                if (empty($sessionId)) {
6725
                    $objExerciseTmp = new Exercise($courseId);
6726
                    $objExerciseTmp->read($item_id);
6727
                    if ($visibility == 'visible') {
6728
                        $objExerciseTmp->enable();
6729
                        $objExerciseTmp->save();
6730
                    } else {
6731
                        $objExerciseTmp->disable();
6732
                        $objExerciseTmp->save();
6733
                    }
6734
                }
6735
                break;
6736
        }
6737
    }
6738
}
6739
6740
/**
6741
 * @return string
6742
 */
6743
function api_get_security_key() {
6744
    return api_get_configuration_value('security_key');
6745
}
6746
6747
/**
6748
 * @param int $user_id
6749
 * @param int $courseId
6750
 * @param int $session_id
6751
 * @return array
6752
 */
6753
function api_detect_user_roles($user_id, $courseId, $session_id = 0)
6754
{
6755
    $user_roles = array();
6756
    /*$user_info = api_get_user_info($user_id);
6757
    $user_roles[] = $user_info['status'];*/
6758
    $courseInfo = api_get_course_info_by_id($courseId);
6759
    $course_code = $courseInfo['code'];
6760
6761
    $url_id = api_get_current_access_url_id();
6762
    if (api_is_platform_admin_by_id($user_id, $url_id)) {
6763
        $user_roles[] = PLATFORM_ADMIN;
6764
    }
6765
6766
    /*if (api_is_drh()) {
6767
        $user_roles[] = DRH;
6768
    }*/
6769
6770
    if (!empty($session_id)) {
6771
        if (SessionManager::user_is_general_coach($user_id, $session_id)) {
6772
            $user_roles[] = SESSION_GENERAL_COACH;
6773
        }
6774
    }
6775
6776
    if (!empty($course_code)) {
6777
        if (empty($session_id)) {
6778
            if (CourseManager::is_course_teacher($user_id, $course_code)) {
6779
                $user_roles[] = COURSEMANAGER;
6780
            }
6781
            if (CourseManager::get_tutor_in_course_status($user_id, $courseInfo['real_id'])) {
6782
                $user_roles[] = COURSE_TUTOR;
6783
            }
6784
6785
            if (CourseManager::is_user_subscribed_in_course($user_id, $course_code)) {
6786
                $user_roles[] = COURSE_STUDENT;
6787
            }
6788
        } else {
6789
            $user_status_in_session = SessionManager::get_user_status_in_course_session(
6790
                $user_id,
6791
                $courseId,
6792
                $session_id
6793
            );
6794
6795
            if (!empty($user_status_in_session)) {
6796
                if ($user_status_in_session == 0) {
6797
                    $user_roles[] = SESSION_STUDENT;
6798
                }
6799
                if ($user_status_in_session == 2) {
6800
                    $user_roles[] = SESSION_COURSE_COACH;
6801
                }
6802
            }
6803
6804
            /*if (api_is_course_session_coach($user_id, $course_code, $session_id)) {
6805
               $user_roles[] = SESSION_COURSE_COACH;
6806
            }*/
6807
        }
6808
    }
6809
    return $user_roles;
6810
}
6811
6812
/**
6813
 * @param int $courseId
6814
 * @param int $session_id
6815
 * @return bool
6816
 */
6817
function api_coach_can_edit_view_results($courseId = null, $session_id = null)
6818
{
6819
    $user_id = api_get_user_id();
6820
6821
    if (empty($courseId)) {
6822
        $courseId = api_get_course_int_id();
6823
    }
6824
6825
    if (empty($session_id)) {
6826
        $session_id = api_get_session_id();
6827
    }
6828
6829
    if (api_is_platform_admin()) {
6830
        return true;
6831
    }
6832
6833
    $roles = api_detect_user_roles($user_id, $courseId, $session_id);
6834
6835
    if (in_array(SESSION_COURSE_COACH, $roles)) {
6836
        //return api_get_setting('session_tutor_reports_visibility') == 'true';
6837
        return true;
6838
    } else {
6839
        if (in_array(COURSEMANAGER, $roles)) {
6840
            return true;
6841
        }
6842
        return false;
6843
    }
6844
}
6845
6846
function api_get_js_simple($file) {
6847
    return '<script type="text/javascript" src="'.$file.'"></script>'."\n";
6848
}
6849
6850
function api_set_settings_and_plugins() {
6851
    global $_configuration;
6852
    $_setting = array();
6853
    $_plugins = array();
6854
6855
    // access_url == 1 is the default chamilo location
6856
    $settings_by_access_list = array();
6857
    $access_url_id = api_get_current_access_url_id();
6858 View Code Duplication
    if ($access_url_id != 1) {
6859
        $url_info = api_get_access_url($_configuration['access_url']);
6860
        if ($url_info['active'] == 1) {
6861
            $settings_by_access = & api_get_settings(null, 'list', $_configuration['access_url'], 1);
6862
            foreach ($settings_by_access as & $row) {
6863
                if (empty($row['variable'])) {
6864
                    $row['variable'] = 0;
6865
                }
6866
                if (empty($row['subkey'])) {
6867
                    $row['subkey'] = 0;
6868
                }
6869
                if (empty($row['category'])) {
6870
                    $row['category'] = 0;
6871
                }
6872
                $settings_by_access_list[$row['variable']][$row['subkey']][$row['category']] = $row;
6873
            }
6874
        }
6875
    }
6876
6877
    $result = api_get_settings(null, 'list', 1);
6878
6879 View Code Duplication
    foreach ($result as & $row) {
6880
        if ($access_url_id != 1) {
6881
            if ($url_info['active'] == 1) {
6882
                $var = empty($row['variable']) ? 0 : $row['variable'];
6883
                $subkey = empty($row['subkey']) ? 0 : $row['subkey'];
6884
                $category = empty($row['category']) ? 0 : $row['category'];
6885
            }
6886
6887
            if ($row['access_url_changeable'] == 1 && $url_info['active'] == 1) {
6888
                if (isset($settings_by_access_list[$var]) &&
6889
                    $settings_by_access_list[$var][$subkey][$category]['selected_value'] != '') {
6890
                    if ($row['subkey'] == null) {
6891
                        $_setting[$row['variable']] = $settings_by_access_list[$var][$subkey][$category]['selected_value'];
6892
                    } else {
6893
                        $_setting[$row['variable']][$row['subkey']] = $settings_by_access_list[$var][$subkey][$category]['selected_value'];
6894
                    }
6895
                } else {
6896
                    if ($row['subkey'] == null) {
6897
                        $_setting[$row['variable']] = $row['selected_value'];
6898
                    } else {
6899
                        $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
6900
                    }
6901
                }
6902
            } else {
6903
                if ($row['subkey'] == null) {
6904
                    $_setting[$row['variable']] = $row['selected_value'];
6905
                } else {
6906
                    $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
6907
                }
6908
            }
6909
        } else {
6910
            if ($row['subkey'] == null) {
6911
                $_setting[$row['variable']] = $row['selected_value'];
6912
            } else {
6913
                $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
6914
            }
6915
        }
6916
    }
6917
6918
    $result = api_get_settings('Plugins', 'list', $access_url_id);
6919
    $_plugins = array();
6920 View Code Duplication
    foreach ($result as & $row) {
6921
        $key = & $row['variable'];
6922
        if (is_string($_setting[$key])) {
6923
            $_setting[$key] = array();
6924
        }
6925
        $_setting[$key][] = $row['selected_value'];
6926
        $_plugins[$key][] = $row['selected_value'];
6927
    }
6928
6929
    $_SESSION['_setting'] = $_setting;
6930
    $_SESSION['_plugins'] = $_plugins;
6931
}
6932
6933
/**
6934
 * Tries to set memory limit, if authorized and new limit is higher than current
6935
 * @param string New memory limit
6936
 * @param string $mem
6937
 * @return bool True on success, false on failure or current is higher than suggested
6938
 * @assert (null) === false
6939
 * @assert (-1) === false
6940
 * @assert (0) === true
6941
 * @assert ('1G') === true
6942
 */
6943
function api_set_memory_limit($mem){
6944
    //if ini_set() not available, this function is useless
6945
    if (!function_exists('ini_set') || is_null($mem) || $mem == -1) {
6946
        return false;
6947
    }
6948
6949
    $memory_limit = ini_get('memory_limit');
6950
    if (api_get_bytes_memory_limit($mem) > api_get_bytes_memory_limit($memory_limit)){
6951
        ini_set('memory_limit', $mem);
6952
        return true;
6953
    }
6954
    return false;
6955
}
6956
6957
/**
6958
 * Gets memory limit in bytes
6959
 * @param string The memory size (128M, 1G, 1000K, etc)
6960
 * @return int
6961
 * @assert (null) === false
6962
 * @assert ('1t')  === 1099511627776
6963
 * @assert ('1g')  === 1073741824
6964
 * @assert ('1m')  === 1048576
6965
 * @assert ('100k') === 102400
6966
 */
6967
function api_get_bytes_memory_limit($mem){
6968
    $size = strtolower(substr($mem,-1));
6969
6970
    switch ($size) {
6971
        case 't':
6972
            $mem = intval(substr($mem,-1))*1024*1024*1024*1024;
6973
            break;
6974
        case 'g':
6975
            $mem = intval(substr($mem,0,-1))*1024*1024*1024;
6976
            break;
6977
        case 'm':
6978
            $mem = intval(substr($mem,0,-1))*1024*1024;
6979
            break;
6980
        case 'k':
6981
            $mem = intval(substr($mem,0,-1))*1024;
6982
            break;
6983
        default:
6984
            // we assume it's integer only
6985
            $mem = intval($mem);
6986
            break;
6987
    }
6988
    return $mem;
6989
}
6990
6991
/**
6992
 * Finds all the information about a user from username instead of user id
6993
 *
6994
 * @param string $officialCode
6995
 * @return array $user_info user_id, lastname, firstname, username, email, ...
6996
 * @author Yannick Warnier <[email protected]>
6997
 */
6998 View Code Duplication
function api_get_user_info_from_official_code($officialCode)
6999
{
7000
    if (empty($officialCode)) {
7001
        return false;
7002
    }
7003
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
7004
            WHERE official_code ='".Database::escape_string($officialCode)."'";
7005
    $result = Database::query($sql);
7006
    if (Database::num_rows($result) > 0) {
7007
        $result_array = Database::fetch_array($result);
7008
        return _api_format_user($result_array);
7009
    }
7010
    return false;
7011
}
7012
7013
/**
7014
 * @param string $usernameInputId
7015
 * @param string $passwordInputId
7016
 * @return null|string
7017
 */
7018
function api_get_password_checker_js($usernameInputId, $passwordInputId)
7019
{
7020
    $checkPass = api_get_setting('allow_strength_pass_checker');
7021
    $useStrengthPassChecker = $checkPass === 'true';
7022
7023
    if ($useStrengthPassChecker === false) {
7024
        return null;
7025
    }
7026
7027
    $translations = [
7028
        'wordLength' => get_lang('PasswordIsTooShort'),
7029
        'wordNotEmail' => get_lang('YourPasswordCannotBeTheSameAsYourEmail'),
7030
        'wordSimilarToUsername' => get_lang('YourPasswordCannotContainYourUsername'),
7031
        'wordTwoCharacterClasses' => get_lang('WordTwoCharacterClasses'),
7032
        'wordRepetitions' => get_lang('TooManyRepetitions'),
7033
        'wordSequences' => get_lang('YourPasswordContainsSequences'),
7034
        'errorList' => get_lang('ErrorsFound'),
7035
        'veryWeak' => get_lang('PasswordVeryWeak'),
7036
        'weak' => get_lang('PasswordWeak'),
7037
        'normal' => get_lang('PasswordNormal'),
7038
        'medium' => get_lang('PasswordMedium'),
7039
        'strong' => get_lang('PasswordStrong'),
7040
        'veryStrong' => get_lang('PasswordVeryStrong')
7041
    ];
7042
7043
    $js = api_get_asset('pwstrength-bootstrap/dist/pwstrength-bootstrap.min.js');
7044
    $js .=  "<script>    
7045
    var errorMessages = {
7046
        password_to_short : \"" . get_lang('PasswordIsTooShort')."\",
7047
        same_as_username : \"".get_lang('YourPasswordCannotBeTheSameAsYourUsername')."\"
7048
    };
7049
7050
    $(document).ready(function() {
7051
        var lang = ".json_encode($translations).";     
7052
        var options = {        
7053
            onLoad : function () {
7054
                //$('#messages').text('Start typing password');
7055
            },
7056
            onKeyUp: function (evt) {
7057
                $(evt.target).pwstrength('outputErrorList');
7058
            },
7059
            errorMessages : errorMessages,
7060
            viewports: {
7061
                progress: '#password_progress',
7062
                verdict: '#password-verdict',
7063
                errors: '#password-errors'
7064
            },
7065
            usernameField: '$usernameInputId'
7066
        };
7067
        options.i18n = {
7068
            t: function (key) {
7069
                var result = lang[key];
7070
                return result === key ? '' : result; // This assumes you return the                
7071
            }
7072
        };
7073
        $('".$passwordInputId."').pwstrength(options);
7074
    });
7075
    </script>";
7076
7077
    return $js;
7078
}
7079
7080
/**
7081
 * @param string $username
7082
 * create an user extra field called 'captcha_blocked_until_date'
7083
 */
7084
function api_block_account_captcha($username)
7085
{
7086
    $userInfo = api_get_user_info_from_username($username);
7087
    if (empty($userInfo)) {
7088
        return false;
7089
    }
7090
    $minutesToBlock = api_get_setting('captcha_time_to_block');
7091
    $time = time() + $minutesToBlock*60;
7092
    UserManager::update_extra_field_value(
7093
        $userInfo['user_id'],
7094
        'captcha_blocked_until_date',
7095
        api_get_utc_datetime($time)
0 ignored issues
show
Bug introduced by
It seems like api_get_utc_datetime($time) targeting api_get_utc_datetime() can also be of type null or object<DateTime>; however, UserManager::update_extra_field_value() does only seem to accept string, maybe add an additional type check?

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

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

An additional type check may prevent trouble.

Loading history...
7096
    );
7097
}
7098
7099
/**
7100
 * @param string $username
7101
 */
7102
function api_clean_account_captcha($username)
7103
{
7104
    $userInfo = api_get_user_info_from_username($username);
7105
    if (empty($userInfo)) {
7106
        return false;
7107
    }
7108
    Session::erase('loginFailedCount');
7109
    UserManager::update_extra_field_value(
7110
        $userInfo['user_id'],
7111
        'captcha_blocked_until_date',
7112
        null
7113
    );
7114
}
7115
7116
/**
7117
 * @param string $username
7118
 * @return bool
7119
 */
7120
function api_get_user_blocked_by_captcha($username)
7121
{
7122
    $userInfo = api_get_user_info_from_username($username);
7123
    if (empty($userInfo)) {
7124
        return false;
7125
    }
7126
    $data = UserManager::get_extra_user_data_by_field(
7127
        $userInfo['user_id'],
7128
        'captcha_blocked_until_date'
7129
    );
7130
    if (isset($data) && isset($data['captcha_blocked_until_date'])) {
7131
        return $data['captcha_blocked_until_date'];
7132
    }
7133
    return false;
7134
}
7135
7136
/**
7137
 * Remove tags from HTML anf return the $in_number_char first non-HTML char
7138
 * Postfix the text with "..." if it has been truncated.
7139
 * @param integer $in_number_char
7140
 * @return string
7141
 * @author hubert borderiou
7142
 */
7143
function api_get_short_text_from_html($in_html, $in_number_char)
7144
{
7145
    $out_res = api_remove_tags_with_space($in_html, false);
7146
    $postfix = "...";
7147
    if (strlen($out_res) > $in_number_char) {
7148
        $out_res = substr($out_res, 0, $in_number_char).$postfix;
7149
    }
7150
    return $out_res;
7151
}
7152
7153
/**
7154
 * Replace tags with a space in a text.
7155
 * If $in_double_quote_replace, replace " with '' (for HTML attribute purpose, for exemple)
7156
 * @return string
7157
 * @author hubert borderiou
7158
 */
7159
function api_remove_tags_with_space($in_html, $in_double_quote_replace = true) {
7160
    $out_res = $in_html;
7161
    if ($in_double_quote_replace) {
7162
        $out_res = str_replace('"', "''", $out_res);
7163
    }
7164
    // avoid text stuck together when tags are removed, adding a space after >
7165
    $out_res = str_replace (">", "> ", $out_res);
7166
    $out_res = strip_tags($out_res);
7167
7168
    return $out_res;
7169
}
7170
7171
/**
7172
 * If true, the drh can access all content (courses, users) inside a session
7173
 * @return bool
7174
 */
7175
function api_drh_can_access_all_session_content()
7176
{
7177
    $value = api_get_setting('drh_can_access_all_session_content');
7178
7179
    return $value === 'true';
7180
}
7181
7182
/**
7183
 * @param string $tool
7184
 * @param string $setting
7185
 * @param integer $defaultValue
7186
 * @return string
7187
 */
7188
function api_get_default_tool_setting($tool, $setting, $defaultValue)
7189
{
7190
    global $_configuration;
7191
    if (isset($_configuration[$tool]) &&
7192
        isset($_configuration[$tool]['default_settings']) &&
7193
        isset($_configuration[$tool]['default_settings'][$setting])
7194
    ) {
7195
        return $_configuration[$tool]['default_settings'][$setting];
7196
    }
7197
7198
    return $defaultValue;
7199
}
7200
7201
/**
7202
 * Checks if user can login as another user
7203
 *
7204
 * @param int $loginAsUserId the user id to log in
7205
 * @param int $userId my user id
7206
 * @return bool
7207
 */
7208
function api_can_login_as($loginAsUserId, $userId = null)
7209
{
7210
    if (empty($userId)) {
7211
        $userId = api_get_user_id();
7212
    }
7213
    if ($loginAsUserId == $userId) {
7214
        return false;
7215
    }
7216
7217
    if (empty($loginAsUserId)) {
7218
        return false;
7219
    }
7220
7221
    if ($loginAsUserId != strval(intval($loginAsUserId))) {
7222
        return false;
7223
    }
7224
7225
    // Check if the user to login is an admin
7226
    if (api_is_platform_admin_by_id($loginAsUserId)) {
7227
        // Only super admins can login to admin accounts
7228
        if (!api_global_admin_can_edit_admin($loginAsUserId)) {
7229
            return false;
7230
        }
7231
    }
7232
7233
    $userInfo = api_get_user_info($userId);
7234
7235
    $isDrh = function() use($loginAsUserId) {
7236
        if (api_is_drh()) {
7237
            if (api_drh_can_access_all_session_content()) {
7238
                $users = SessionManager::getAllUsersFromCoursesFromAllSessionFromStatus('drh_all', api_get_user_id());
7239
                $userList = array();
7240
                if (is_array($users)) {
7241
                    foreach ($users as $user) {
7242
                        $userList[] = $user['user_id'];
7243
                    }
7244
                }
7245
                if (in_array($loginAsUserId, $userList)) {
7246
                    return true;
7247
                }
7248
            } else {
7249
                if (api_is_drh() && UserManager::is_user_followed_by_drh($loginAsUserId, api_get_user_id())) {
7250
                    return true;
7251
                }
7252
            }
7253
        }
7254
        return false;
7255
    };
7256
7257
    return api_is_platform_admin() || (api_is_session_admin() && $userInfo['status'] == 5) || $isDrh();
7258
}
7259
7260
/**
7261
 * @return bool
7262
 */
7263
function api_is_allowed_in_course()
7264
{
7265
    return Session::read('is_allowed_in_course');
7266
}
7267
7268
/**
7269
 * Set the cookie to go directly to the course code $in_firstpage
7270
 * after login
7271
 * @param string $in_firstpage is the course code of the course to go
7272
 */
7273
function api_set_firstpage_parameter($in_firstpage)
7274
{
7275
    setcookie('GotoCourse', $in_firstpage);
7276
}
7277
7278
/**
7279
 * Delete the cookie to go directly to the course code $in_firstpage
7280
 * after login
7281
 */
7282
function api_delete_firstpage_parameter()
7283
{
7284
    setcookie('GotoCourse', '', time() - 3600);
7285
}
7286
7287
/**
7288
 * @return boolean if course_code for direct course access after login is set
7289
 */
7290
function exist_firstpage_parameter()
7291
{
7292
    return (isset($_COOKIE['GotoCourse']) && $_COOKIE['GotoCourse'] != "");
7293
}
7294
7295
/**
7296
 * @return return the course_code of the course where user login
7297
 */
7298
function api_get_firstpage_parameter()
7299
{
7300
    return $_COOKIE['GotoCourse'];
7301
}
7302
7303
/**
7304
 * Return true on https install
7305
 * @return boolean
7306
 */
7307
function api_is_https()
7308
{
7309
    return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off');
7310
}
7311
7312
/**
7313
 * Return protocol (http or https)
7314
 * @return string
7315
 */
7316
function api_get_protocol()
7317
{
7318
    return api_is_https() ? 'https' : 'http';
7319
}
7320
7321
/**
7322
 * Return a string where " are replaced with 2 '
7323
 * It is useful when you pass a PHP variable in a Javascript browser dialog
7324
 * e.g. : alert("<?php get_lang('Message') ?>");
7325
 * and message contains character "
7326
 *
7327
 * @param string $in_text
7328
 * @return string
7329
 */
7330
function convert_double_quote_to_single($in_text)
7331
{
7332
    return api_preg_replace('/"/', "''", $in_text);
7333
}
7334
7335
/**
7336
 * Get origin
7337
 *
7338
 * @param string
7339
 * @return string
7340
 **/
7341
function api_get_origin()
7342
{
7343
    if (isset($_REQUEST['origin'])) {
7344
        return $_REQUEST['origin'] === 'learnpath' ? 'learnpath' : '';
7345
    }
7346
7347
    return '';
7348
}
7349
7350
/**
7351
 * Warns an user that the portal reach certain limit.
7352
 * @param string $limitName
7353
 */
7354
function api_warn_hosting_contact($limitName)
7355
{
7356
    $hostingParams = api_get_configuration_value(1);
7357
    $email = null;
7358
7359
    if (!empty($hostingParams)) {
7360
        if (isset($hostingParams['hosting_contact_mail'])) {
7361
            $email = $hostingParams['hosting_contact_mail'];
7362
        }
7363
    }
7364
7365
    if (!empty($email)) {
7366
        $subject = get_lang('HostingWarningReached');
7367
        $body = get_lang('PortalName').': '.api_get_path(WEB_PATH)." \n ";
7368
        $body .= get_lang('PortalLimitType').': '.$limitName." \n ";
7369
        if (isset($hostingParams[$limitName])) {
7370
            $body .= get_lang('Value') . ': ' . $hostingParams[$limitName];
7371
        }
7372
        api_mail_html(null, $email, $subject, $body);
7373
    }
7374
}
7375
7376
/**
7377
 * @param string $variable
7378
 * @return bool|mixed
7379
 */
7380
function api_get_configuration_value($variable)
7381
{
7382
    global $_configuration;
7383
    if (isset($_configuration[$variable])) {
7384
        return $_configuration[$variable];
7385
    }
7386
    return false;
7387
}
7388
7389
/**
7390
 * Returns supported image extensions in the portal
7391
 * @param   bool    $supportVectors Whether vector images should also be accepted or not
7392
 * @return  array   Supported image extensions in the portal
7393
 */
7394
function api_get_supported_image_extensions($supportVectors = true)
7395
{
7396
    // jpg can also be called jpeg, jpe, jfif and jif. See https://en.wikipedia.org/wiki/JPEG#JPEG_filename_extensions
7397
    $supportedImageExtensions = array('jpg', 'jpeg', 'png', 'gif', 'jpe', 'jfif', 'jif');
7398
    if ($supportVectors) {
7399
        array_push($supportedImageExtensions, 'svg');
7400
    }
7401
    if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
7402
        array_push($supportedImageExtensions, 'webp');
7403
    }
7404
    return $supportedImageExtensions;
7405
}
7406
7407
/**
7408
 * This setting changes the registration status for the campus
7409
 *
7410
 * @author Patrick Cool <[email protected]>, Ghent University
7411
 * @version August 2006
7412
 * @param   bool    $listCampus Whether we authorize
7413
 * @todo the $_settings should be reloaded here. => write api function for this and use this in global.inc.php also.
7414
 */
7415 View Code Duplication
function api_register_campus($listCampus = true) {
7416
    $tbl_settings = Database :: get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
7417
7418
    $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='registered'";
7419
    Database::query($sql);
7420
7421
    if (!$listCampus) {
7422
        $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='donotlistcampus'";
7423
        Database::query($sql);
7424
    }
7425
}
7426
7427
/**
7428
 * Checks whether current user is a student boss
7429
 * @global array $_user
7430
 * @return boolean
7431
 */
7432
function api_is_student_boss()
7433
{
7434
    $_user = api_get_user_info();
7435
7436
    return isset($_user['status']) && $_user['status'] == STUDENT_BOSS;
7437
}
7438
7439
/**
7440
 * Check whether the user type should be exclude.
7441
 * Such as invited or anonymous users
7442
 * @param boolean $checkDB Optional. Whether check the user status
7443
 * @param int $userId Options. The user id
7444
 *
7445
 * @return boolean
7446
 */
7447
function api_is_excluded_user_type($checkDB = false, $userId = 0)
7448
{
7449
    if ($checkDB) {
7450
        $userId = empty($userId) ? api_get_user_id() : intval($userId);
7451
7452
        if ($userId == 0) {
7453
            return true;
7454
        }
7455
7456
        $userInfo = api_get_user_info($userId);
7457
7458
        switch ($userInfo['status']) {
7459
            case INVITEE:
7460
                //no break;
7461
            case ANONYMOUS:
7462
                return true;
7463
            default:
7464
                return false;
7465
        }
7466
    }
7467
7468
    $isInvited = api_is_invitee();
7469
    $isAnonymous = api_is_anonymous();
7470
7471
    if ($isInvited || $isAnonymous) {
7472
        return true;
7473
    }
7474
7475
    return false;
7476
}
7477
7478
/**
7479
 * Get the user status to ignore in reports
7480
 * @param string $format Optional. The result type (array or string)
7481
 * @return array|string
7482
 */
7483
function api_get_users_status_ignored_in_reports($format = 'array')
7484
{
7485
    $excludedTypes = array(
7486
        INVITEE,
7487
        ANONYMOUS
7488
    );
7489
7490
    if ($format == 'string') {
7491
        return implode(', ', $excludedTypes);
7492
    }
7493
7494
    return $excludedTypes;
7495
}
7496
7497
/**
7498
 * Set the Site Use Cookie Warning for 1 year
7499
 */
7500
function api_set_site_use_cookie_warning_cookie()
7501
{
7502
    setcookie('ChamiloUsesCookies', 'ok', time()+31556926);
7503
}
7504
7505
/**
7506
 * Return true if the Site Use Cookie Warning Cookie warning exists
7507
 * @return bool
7508
 */
7509
function api_site_use_cookie_warning_cookie_exist()
7510
{
7511
    return isset($_COOKIE['ChamiloUsesCookies']);
7512
}
7513
7514
/**
7515
 * Given a number of seconds, format the time to show hours, minutes and seconds
7516
 * @param int $time The time in seconds
7517
 * @param string $originFormat Optional. PHP o JS
7518
 * @return string (00h00'00")
7519
 */
7520
function api_format_time($time, $originFormat = 'php')
7521
{
7522
    $h = get_lang('h');
7523
    $hours = $time / 3600;
7524
    $mins = ($time % 3600) / 60;
7525
    $secs = ($time % 60);
7526
7527
    if ($time < 0) {
7528
        $hours = 0;
7529
        $mins = 0;
7530
        $secs = 0;
7531
    }
7532
7533
    if ($originFormat == 'js') {
7534
        $formattedTime = trim(sprintf("%02d : %02d : %02d", $hours, $mins, $secs));
7535
    } else {
7536
        $formattedTime = trim(sprintf("%02d$h%02d'%02d\"", $hours, $mins, $secs));
7537
    }
7538
7539
    return $formattedTime;
7540
}
7541
7542
/**
7543
 * Create a new empty directory with index.html file
7544
 * @param string $name The new directory name
7545
 * @param string $parentDirectory Directory parent directory name
7546
 * @return boolean Return true if the directory was create. Otherwise return false
7547
 */
7548
function api_create_protected_dir($name, $parentDirectory)
7549
{
7550
    $isCreated = false;
7551
7552
    if (!is_writable($parentDirectory)) {
7553
        return false;
7554
    }
7555
7556
    $fullPath = $parentDirectory . api_replace_dangerous_char($name);
7557
7558
    if (mkdir($fullPath, api_get_permissions_for_new_directories(), true)) {
7559
        $fp = fopen($fullPath . '/index.html', 'w');
7560
7561
        if ($fp) {
7562
            if (fwrite($fp, '<html><head></head><body></body></html>')) {
7563
                $isCreated = true;
7564
            }
7565
        }
7566
7567
        fclose($fp);
7568
    }
7569
7570
    return $isCreated;
7571
}
7572
7573
/**
7574
 * Sends an HTML email using the phpmailer class (and multipart/alternative to downgrade gracefully)
7575
 * Sender name and email can be specified, if not specified
7576
 * name and email of the platform admin are used
7577
 *
7578
 * @author Bert Vanderkimpen ICT&O UGent
7579
 * @author Yannick Warnier <[email protected]>
7580
 *
7581
 * @param string    name of recipient
7582
 * @param string    email of recipient
7583
 * @param string    email subject
7584
 * @param string    email body
7585
 * @param string    sender name
7586
 * @param string    sender e-mail
7587
 * @param array     extra headers in form $headers = array($name => $value) to allow parsing
7588
 * @param array     data file (path and filename)
7589
 * @param bool      True for attaching a embedded file inside content html (optional)
7590
 * @param array     Additional parameters
7591
 * @return          integer true if mail was sent
7592
 * @see             class.phpmailer.php
7593
 */
7594
function api_mail_html(
7595
    $recipient_name,
7596
    $recipient_email,
7597
    $subject,
7598
    $message,
7599
    $senderName = '',
7600
    $senderEmail = '',
7601
    $extra_headers = array(),
7602
    $data_file = array(),
7603
    $embedded_image = false,
7604
    $additionalParameters = array()
7605
) {
7606
    global $platform_email;
7607
7608
    $mail = new PHPMailer();
7609
    $mail->Mailer = $platform_email['SMTP_MAILER'];
7610
    $mail->Host = $platform_email['SMTP_HOST'];
7611
    $mail->Port = $platform_email['SMTP_PORT'];
7612
    $mail->CharSet = $platform_email['SMTP_CHARSET'];
7613
    // Stay far below SMTP protocol 980 chars limit.
7614
    $mail->WordWrap = 200;
7615
7616
    if ($platform_email['SMTP_AUTH']) {
7617
        $mail->SMTPAuth = 1;
7618
        $mail->Username = $platform_email['SMTP_USER'];
7619
        $mail->Password = $platform_email['SMTP_PASS'];
7620
        if (isset($platform_email['SMTP_SECURE'])) {
7621
            $mail->SMTPSecure = $platform_email['SMTP_SECURE'];
7622
        }
7623
    }
7624
    $mail->SMTPDebug = isset($platform_email['SMTP_DEBUG'])?$platform_email['SMTP_DEBUG']:0;
7625
7626
    // 5 = low, 1 = high
7627
    $mail->Priority = 3;
7628
    $mail->SMTPKeepAlive = true;
7629
7630
    // Default values
7631
    $notification = new Notification();
7632
    $defaultEmail = $notification->getDefaultPlatformSenderEmail();
7633
    $defaultName = $notification->getDefaultPlatformSenderName();
7634
7635
    // If the parameter is set don't use the admin.
7636
    $senderName = !empty($senderName) ? $senderName : $defaultName;
7637
    $senderEmail = !empty($senderEmail) ? $senderEmail : $defaultEmail;
7638
7639
    // Reply to first
7640
    if (isset($extra_headers['reply_to'])) {
7641
        $mail->AddReplyTo(
7642
            $extra_headers['reply_to']['mail'],
7643
            $extra_headers['reply_to']['name']
7644
        );
7645
            // Errors to sender
7646
        $mail->AddCustomHeader('Errors-To: '.$extra_headers['reply_to']['mail']);
7647
        $mail->Sender = $extra_headers['reply_to']['mail'];
7648
        unset($extra_headers['reply_to']);
7649
    } else {
7650
        $mail->AddCustomHeader('Errors-To: '.$defaultEmail);
7651
    }
7652
7653
    //If the SMTP configuration only accept one sender
7654
    if ($platform_email['SMTP_UNIQUE_SENDER']) {
7655
        $senderName = $platform_email['SMTP_FROM_NAME'];
7656
        $senderEmail = $platform_email['SMTP_FROM_EMAIL'];
7657
    }
7658
    $mail->SetFrom($defaultEmail, $defaultName);
7659
    $mail->From = $defaultEmail;
7660
    $mail->Sender = $defaultEmail;
7661
    $mail->Subject = $subject;
7662
    $mail->AltBody = strip_tags(
7663
        str_replace('<br />', "\n", api_html_entity_decode($message))
7664
    );
7665
7666
    // Send embedded image.
7667
    if ($embedded_image) {
7668
        // Get all images html inside content.
7669
        preg_match_all("/<img\s+.*?src=[\"\']?([^\"\' >]*)[\"\']?[^>]*>/i", $message, $m);
7670
        // Prepare new tag images.
7671
        $new_images_html = array();
7672
        $i = 1;
7673
        if (!empty($m[1])) {
7674
            foreach ($m[1] as $image_path) {
7675
                $real_path = realpath($image_path);
7676
                $filename  = basename($image_path);
7677
                $image_cid = $filename.'_'.$i;
7678
                $encoding = 'base64';
7679
                $image_type = mime_content_type($real_path);
7680
                $mail->AddEmbeddedImage(
7681
                    $real_path,
7682
                    $image_cid,
7683
                    $filename,
7684
                    $encoding,
7685
                    $image_type
7686
                );
7687
                $new_images_html[] = '<img src="cid:'.$image_cid.'" />';
7688
                $i++;
7689
            }
7690
        }
7691
7692
        // Replace origin image for new embedded image html.
7693
        $x = 0;
7694
        if (!empty($m[0])) {
7695
            foreach ($m[0] as $orig_img) {
7696
                $message = str_replace($orig_img, $new_images_html[$x], $message);
7697
                $x++;
7698
            }
7699
        }
7700
    }
7701
7702
    $mailView = new Template(null, false, false, false, false, false, false);
7703
    $mailView->assign('content', $message);
7704
7705
    if (isset($additionalParameters['link'])) {
7706
        $mailView->assign('link', $additionalParameters['link']);
7707
    }
7708
7709
    $layout = $mailView->get_template('mail/mail.tpl');
7710
    $mail->Body = $mailView->fetch($layout);
7711
7712
    // Attachment ...
7713
    if (!empty($data_file)) {
7714
        $o = 0;
7715
        foreach ($data_file as $file_attach) {
7716
            if (!empty($file_attach['path']) && !empty($file_attach['filename'])) {
7717
                $mail->AddAttachment($file_attach['path'], $file_attach['filename']);
7718
            }
7719
            $o++;
7720
        }
7721
    }
7722
7723
    // Only valid addresses are accepted.
7724
    if (is_array($recipient_email)) {
7725
        foreach ($recipient_email as $dest) {
7726
            if (api_valid_email($dest)) {
7727
                $mail->AddAddress($dest, $recipient_name);
7728
            }
7729
        }
7730
    } else {
7731
        if (api_valid_email($recipient_email)) {
7732
            $mail->AddAddress($recipient_email, $recipient_name);
7733
        } else {
7734
            return 0;
7735
        }
7736
    }
7737
7738
    if (is_array($extra_headers) && count($extra_headers) > 0) {
7739
        foreach ($extra_headers as $key => $value) {
7740
            switch (strtolower($key)) {
7741
                case 'encoding':
7742
                case 'content-transfer-encoding':
7743
                    $mail->Encoding = $value;
7744
                    break;
7745
                case 'charset':
7746
                    $mail->Charset = $value;
7747
                    break;
7748
                case 'contenttype':
7749
                case 'content-type':
7750
                    $mail->ContentType = $value;
7751
                    break;
7752
                default:
7753
                    $mail->AddCustomHeader($key.':'.$value);
7754
                    break;
7755
            }
7756
        }
7757
    } else {
7758
        if (!empty($extra_headers)) {
7759
            $mail->AddCustomHeader($extra_headers);
7760
        }
7761
    }
7762
7763
    // WordWrap the html body (phpMailer only fixes AltBody) FS#2988
7764
    $mail->Body = $mail->WrapText($mail->Body, $mail->WordWrap);
7765
7766
    // Send the mail message.
7767
    if (!$mail->Send()) {
7768
        error_log('ERROR: mail not sent to '.$recipient_name.' ('.$recipient_email.') because of '.$mail->ErrorInfo.'<br />');
7769
        if ($mail->SMTPDebug) {
7770
            error_log(
7771
                "Connection details :: " .
7772
                "Protocol: " . $mail->Mailer . ' :: ' .
7773
                "Host/Port: " . $mail->Host . ':' . $mail->Port . ' :: ' .
7774
                "Authent/Open: " . ($mail->SMTPAuth?'Authent':'Open') . ' :: ' .
7775
                ($mail->SMTPAuth?"  User/Pass: " . $mail->Username . ':' . $mail->Password:'')
7776
            );
7777
        }
7778
        return 0;
7779
    }
7780
7781
    if (!empty($additionalParameters)) {
7782
        $plugin = new AppPlugin();
7783
        $smsPlugin = $plugin->getSMSPluginLibrary();
7784
        if ($smsPlugin) {
7785
            $smsPlugin->send($additionalParameters);
7786
        }
7787
    }
7788
7789
    // Clear all the addresses.
7790
    $mail->ClearAddresses();
7791
7792
    // Clear all attachments
7793
    $mail->ClearAttachments();
7794
7795
    return 1;
7796
}
7797
7798
/**
7799
 * @param string $tool Possible values:
7800
 * GroupManager::GROUP_TOOL_*
7801
 *
7802
 */
7803
function api_protect_course_group($tool, $showHeader = true)
7804
{
7805
    $userId = api_get_user_id();
7806
    $groupId = api_get_group_id();
7807
    $groupInfo = GroupManager::get_group_properties($groupId);
7808
7809
    if (!empty($groupInfo)) {
7810
        $allow = GroupManager::user_has_access(
7811
            $userId,
7812
            $groupInfo['iid'],
7813
            $tool
7814
        );
7815
7816
        if (!$allow) {
7817
            api_not_allowed($showHeader);
7818
        }
7819
    }
7820
}
7821
7822
/**
7823
 * Check if a date is in a date range
7824
 *
7825
 * @param datetime $startDate
7826
 * @param datetime $endDate
7827
 * @param datetime $currentDate
7828
 * @return bool true if date is in rage, false otherwise
7829
 */
7830
function api_is_date_in_date_range($startDate, $endDate, $currentDate = null)
7831
{
7832
    $startDate = strtotime(api_get_local_time($startDate));
7833
    $endDate = strtotime(api_get_local_time($endDate));
7834
    $currentDate = strtotime(api_get_local_time($currentDate));
7835
7836
    if ($currentDate >= $startDate && $currentDate <= $endDate) {
7837
        return true;
7838
    }
7839
7840
    return false;
7841
}
7842
7843
/**
7844
 * Eliminate the duplicates of a multidimensional array by sending the key
7845
 *
7846
 * @param array $array multidimensional array
7847
 * @param int $key key to find to compare
7848
 * @return array
7849
 *
7850
 */
7851
function api_unique_multidim_array($array, $key){
7852
    $temp_array = [];
7853
    $i = 0;
7854
    $key_array = [];
7855
7856
    foreach($array as $val){
7857
        if(!in_array($val[$key],$key_array)){
7858
            $key_array[$i] = $val[$key];
7859
            $temp_array[$i] = $val;
7860
        }
7861
        $i++;
7862
    }
7863
    return $temp_array;
7864
}
7865
7866
/**
7867
 * Limit the access to Session Admins wheen the limit_session_admin_role
7868
 * configuration variable is set to true
7869
 */
7870
function api_protect_limit_for_session_admin()
7871
{
7872
    $limitAdmin = api_get_setting('limit_session_admin_role');
7873
    if (api_is_session_admin() && $limitAdmin === 'true') {
7874
        api_not_allowed(true);
7875
    }
7876
}
7877
7878
function api_is_student_view_active() {
7879
    $studentView = Session::read('studentview');
7880
    return $studentView == 'studentview';
7881
}
7882
7883
/**
7884
 * Adds a file inside the upload/$type/id
7885
 *
7886
 * @param string $type
7887
 * @param array $file
7888
 * @param int $itemId
7889
 * @param string $cropParameters
7890
 * @return array|bool
7891
 */
7892
function api_upload_file($type, $file, $itemId, $cropParameters = '')
7893
{
7894
    $upload = process_uploaded_file($file);
7895
    if ($upload) {
7896
        $name = api_replace_dangerous_char($file['name']);
7897
7898
        // No "dangerous" files
7899
        $name = disable_dangerous_file($name);
7900
7901
        $pathId = '/'.substr((string)$itemId, 0, 1).'/'.$itemId.'/';
7902
        $path = api_get_path(SYS_UPLOAD_PATH).$type.$pathId;
7903
7904
        if (!is_dir($path)) {
7905
            mkdir($path, api_get_permissions_for_new_directories(), true);
7906
        }
7907
7908
        $pathToSave = $path.$name;
7909
7910
        $result = move_uploaded_file($file['tmp_name'], $pathToSave);
7911
        if ($result) {
7912
            if (!empty($cropParameters)) {
7913
                $image = new Image($pathToSave);
7914
                $image->crop($cropParameters);
7915
            }
7916
7917
            return ['path_to_save' => $pathId.$name];
7918
        }
7919
        return false;
7920
    }
7921
}
7922
7923
/**
7924
 * @param string $type
7925
 * @param string $file
7926
 */
7927
function api_remove_uploaded_file($type, $file)
7928
{
7929
    $path = api_get_path(SYS_UPLOAD_PATH).$type.'/'.$file;
7930
    if (file_exists($path)) {
7931
        unlink($path);
7932
    }
7933
}
7934