Completed
Push — master ( 632249...87746d )
by Julito
62:28 queued 32:25
created

api.lib.php ➔ api_mail_html()   D

Complexity

Conditions 43
Paths 24

Size

Total Lines 250
Code Lines 158

Duplication

Lines 14
Ratio 5.6 %

Importance

Changes 0
Metric Value
cc 43
eloc 158
nc 24
nop 10
dl 14
loc 250
rs 4.1818
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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

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

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

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

// Bar.php
namespace OtherDir;

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

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

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

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

// Bar.php
namespace OtherDir;

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

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

Let’s take a look at these examples:

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

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

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

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

    doSomethingElse(); //wrong
    break;

}

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

Loading history...
2363
2364
            break;
2365
        default:
2366
            return Container::getSettingsManager()->getSetting($variable);
2367
    }
2368
}
2369
2370
/**
2371
 * @param string $plugin
2372
 * @param string $variable
2373
 * @return string
2374
 */
2375
function api_get_plugin_setting($plugin, $variable)
2376
{
2377
    $variableName = $plugin.'_'.$variable;
2378
    $result = api_get_setting($variableName);
2379
    if (isset($result[$plugin])) {
2380
        return $result[$plugin];
2381
    }
2382
2383
    return null;
2384
}
2385
2386
/**
2387
 * Returns the value of a setting from the web-adjustable admin config settings.
2388
 **/
2389
function api_get_settings_params($params) {
2390
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2391
    $result = Database::select('*', $table, array('where' => $params));
2392
    return $result;
2393
}
2394
2395
function api_get_settings_params_simple($params) {
2396
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2397
    $result = Database::select('*', $table, array('where' => $params), 'one');
2398
    return $result;
2399
}
2400
2401
/**
2402
 * Returns the value of a setting from the web-adjustable admin config settings.
2403
 **/
2404
function api_delete_settings_params($params) {
2405
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2406
    $result = Database::delete($table, $params);
2407
    return $result;
2408
}
2409
2410
/**
2411
 * Returns an escaped version of $_SERVER['PHP_SELF'] to avoid XSS injection
2412
 * @return string   Escaped version of $_SERVER['PHP_SELF']
2413
 */
2414
function api_get_self() {
2415
    return htmlentities($_SERVER['PHP_SELF']);
2416
}
2417
2418
/**
2419
 * Checks whether current user is a platform administrator
2420
 * @param boolean $allowSessionAdmins Whether session admins should be considered admins or not
2421
 * @param boolean $allowDrh Whether HR directors should be considered admins or not
2422
 * @return boolean True if the user has platform admin rights,
2423
 * false otherwise.
2424
 * @see usermanager::is_admin(user_id) for a user-id specific function
2425
 */
2426
function api_is_platform_admin($allowSessionAdmins = false, $allowDrh = false)
2427
{
2428
    $checker = Container::getAuthorizationChecker();
2429
    if ($checker) {
2430
        if ($checker->isGranted('ROLE_ADMIN')) {
2431
        return true;
2432
    }
2433
        if ($allowSessionAdmins) {
2434
            if ($checker->isGranted('ROLE_SESSION_MANAGER')) {
2435
                return true;
2436
            }
2437
        }
2438
    }
2439
2440
    return false;
2441
2442
    $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...
2443
    if ($isPlatformAdmin) {
2444
        return true;
2445
    }
2446
    $_user = api_get_user_info();
2447
2448
    return
2449
        isset($_user['status']) &&
2450
        (
2451
            ($allowSessionAdmins && $_user['status'] == SESSIONADMIN) ||
2452
            ($allowDrh && $_user['status'] == DRH)
2453
        );
2454
}
2455
2456
/**
2457
 * Checks whether the user given as user id is in the admin table.
2458
 * @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...
2459
 * @param int $url URL ID. If provided, also check if the user is active on given URL
2460
 * @result bool True if the user is admin, false otherwise
2461
 */
2462
function api_is_platform_admin_by_id($user_id = null, $url = null)
2463
{
2464
    $user_id = intval($user_id);
2465
    if (empty($user_id)) {
2466
        $user_id = api_get_user_id();
2467
    }
2468
2469
    $em = Container::getEntityManager();
2470
    $user = $em->getRepository('ChamiloUserBundle:User')->find($user_id);
2471
    $is_admin = $user->hasRole('ROLE_ADMIN');
2472
2473
    if (!$is_admin or !isset($url)) {
2474
        return $is_admin;
2475
    }
2476
2477
    // We get here only if $url is set
2478
    $url = intval($url);
2479
    $url_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
2480
    $sql = "SELECT * FROM $url_user_table
2481
            WHERE access_url_id = $url AND user_id = $user_id";
2482
    $res = Database::query($sql);
2483
    $is_on_url = Database::num_rows($res) === 1;
2484
2485
    return $is_on_url;
2486
}
2487
2488
/**
2489
 * Returns the user's numeric status ID from the users table
2490
 * @param int $user_id If none provided, will use current user
2491
 * @return int User's status (1 for teacher, 5 for student, etc)
2492
 */
2493 View Code Duplication
function api_get_user_status($user_id = null)
2494
{
2495
    $user_id = intval($user_id);
2496
    if (empty($user_id)) {
2497
        $user_id = api_get_user_id();
2498
    }
2499
    $table = Database::get_main_table(TABLE_MAIN_USER);
2500
    $sql = "SELECT status FROM $table WHERE user_id = $user_id ";
2501
    $result = Database::query($sql);
2502
    $status = null;
2503
    if (Database::num_rows($result)) {
2504
        $row = Database::fetch_array($result);
2505
        $status = $row['status'];
2506
    }
2507
    return $status;
2508
}
2509
2510
/**
2511
 * Checks whether current user is allowed to create courses
2512
 * @return boolean True if the user has course creation rights,
2513
 * false otherwise.
2514
 */
2515
function api_is_allowed_to_create_course()
2516
{
2517
    if (api_is_platform_admin()) {
2518
        return true;
2519
    }
2520
2521
    // Teachers can only create courses
2522
    if (api_is_teacher()) {
2523
        if (api_get_setting('allow_users_to_create_courses') === 'true') {
2524
            return true;
2525
        } else {
2526
            return false;
2527
        }
2528
    }
2529
2530
    return Session::read('is_allowedCreateCourse');
2531
}
2532
2533
/**
2534
 * Checks whether the current user is a course administrator
2535
 * @return boolean True if current user is a course administrator
2536
 */
2537
function api_is_course_admin() {
2538
    if (api_is_platform_admin()) {
2539
        return true;
2540
    }
2541
    return Session::read('is_courseAdmin');
2542
}
2543
2544
/**
2545
 * Checks whether the current user is a course coach
2546
 * @return bool     True if current user is a course coach
2547
 */
2548
function api_is_course_coach() {
2549
    return Session::read('is_courseCoach');
2550
}
2551
2552
/**
2553
 * Checks whether the current user is a course tutor
2554
 * @return bool     True if current user is a course tutor
2555
 */
2556
function api_is_course_tutor() {
2557
    return Session::read('is_courseTutor');
2558
}
2559
2560
/**
2561
 * @param int $user_id
2562
 * @param int $courseId
2563
 * @param int $session_id
2564
 * @return bool
2565
 */
2566
function api_is_course_session_coach($user_id, $courseId, $session_id)
2567
{
2568
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2569
    $session_rel_course_rel_user_table  = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2570
2571
    $user_id = intval($user_id);
2572
    $session_id = intval($session_id);
2573
    $courseId = intval($courseId);
2574
2575
    $sql = "SELECT DISTINCT session.id
2576
            FROM $session_table
2577
            INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2578
            ON session.id = session_rc_ru.session_id
2579
            WHERE
2580
                session_rc_ru.user_id = '".$user_id."'  AND
2581
                session_rc_ru.c_id = '$courseId' AND
2582
                session_rc_ru.status = 2 AND
2583
                session_rc_ru.session_id = '$session_id'";
2584
    $result = Database::query($sql);
2585
2586
    return Database::num_rows($result) > 0;
2587
}
2588
2589
/**
2590
 * Checks whether the current user is a course or session coach
2591
 * @param int $session_id
2592
 * @param int $courseId
2593
 * @param bool  Check whether we are in student view and, if we are, return false
2594
 * @return boolean True if current user is a course or session coach
2595
 */
2596
function api_is_coach($session_id = 0, $courseId = null, $check_student_view = true)
2597
{
2598
    $userId = api_get_user_id();
2599
2600
    if (!empty($session_id)) {
2601
        $session_id = intval($session_id);
2602
    } else {
2603
        $session_id = api_get_session_id();
2604
    }
2605
2606
    // The student preview was on
2607
    if ($check_student_view &&
2608
        isset($_SESSION['studentview']) && $_SESSION['studentview'] == "studentview"
2609
    ) {
2610
        return false;
2611
    }
2612
2613
    if (!empty($courseId)) {
2614
        $courseId = intval($courseId);
2615
    } else {
2616
        $courseId = api_get_course_int_id();
2617
    }
2618
2619
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2620
    $session_rel_course_rel_user_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2621
    $sessionIsCoach = null;
2622
2623
    if (!empty($courseId)) {
2624
        $sql = "SELECT DISTINCT s.id, name, access_start_date, access_end_date
2625
                FROM $session_table s
2626
                INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2627
                ON session_rc_ru.session_id = s.id AND session_rc_ru.user_id = '".$userId."'
2628
                WHERE
2629
                    session_rc_ru.c_id = '$courseId' AND
2630
                    session_rc_ru.status = 2 AND
2631
                    session_rc_ru.session_id = '$session_id'";
2632
        $result = Database::query($sql);
2633
        $sessionIsCoach = Database::store_result($result);
2634
    }
2635
2636
    if (!empty($session_id)) {
2637
        $sql = "SELECT DISTINCT id, name, access_start_date, access_end_date
2638
                FROM $session_table
2639
                WHERE session.id_coach = $userId AND id = $session_id
2640
                ORDER BY access_start_date, access_end_date, name";
2641
        $result = Database::query($sql);
2642
        if (!empty($sessionIsCoach)) {
2643
            $sessionIsCoach = array_merge($sessionIsCoach , Database::store_result($result));
2644
        } else {
2645
            $sessionIsCoach = Database::store_result($result);
2646
        }
2647
    }
2648
2649
    return (count($sessionIsCoach) > 0);
2650
}
2651
2652
/**
2653
 * Checks whether the current user is a session administrator
2654
 * @return boolean True if current user is a course administrator
2655
 */
2656
function api_is_session_admin()
2657
{
2658
    $user = api_get_user_info();
2659
    return isset($user['status']) && $user['status'] == SESSIONADMIN;
2660
}
2661
2662
/**
2663
 * Checks whether the current user is a human resources manager
2664
 * @return boolean True if current user is a human resources manager
2665
 */
2666
function api_is_drh()
2667
{
2668
    $user = api_get_user_info();
2669
    return isset($user['status']) && $user['status'] == DRH;
2670
}
2671
2672
/**
2673
 * Checks whether the current user is a student
2674
 * @return boolean True if current user is a human resources manager
2675
 */
2676
function api_is_student()
2677
{
2678
    $user = api_get_user_info();
2679
    return isset($user['status']) && $user['status'] == STUDENT;
2680
}
2681
2682
/**
2683
 * Checks whether the current user has the status 'teacher'
2684
 * @return boolean True if current user is a human resources manager
2685
 */
2686
function api_is_teacher()
2687
{
2688
    $user = api_get_user_info();
2689
    return isset($user['status']) && $user['status'] == COURSEMANAGER;
2690
}
2691
2692
/**
2693
 * Checks whether the current user is a invited user
2694
 * @return boolean
2695
 */
2696
function api_is_invitee()
2697
{
2698
    $user = api_get_user_info();
2699
2700
    return isset($user['status']) && $user['status'] == INVITEE;
2701
}
2702
2703
/**
2704
 * This function checks whether a session is assigned into a category
2705
 * @param int       - session id
2706
 * @param string    - category name
2707
 * @return bool     - true if is found, otherwise false
2708
 */
2709
function api_is_session_in_category($session_id, $category_name)
2710
{
2711
    $session_id = intval($session_id);
2712
    $category_name = Database::escape_string($category_name);
2713
2714
    $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2715
    $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
2716
2717
    $sql = "SELECT 1
2718
            FROM $tbl_session
2719
            WHERE $session_id IN (
2720
                SELECT s.id FROM $tbl_session s, $tbl_session_category sc
2721
                WHERE
2722
                  s.session_category_id = sc.id AND
2723
                  sc.name LIKE '%$category_name'
2724
            )";
2725
    $rs = Database::query($sql);
2726
2727
    if (Database::num_rows($rs) > 0) {
2728
        return true;
2729
    } else {
2730
        return false;
2731
    }
2732
}
2733
2734
/**
2735
 * Displays the title of a tool.
2736
 * Normal use: parameter is a string:
2737
 * api_display_tool_title("My Tool")
2738
 *
2739
 * Optionally, there can be a subtitle below
2740
 * the normal title, and / or a supra title above the normal title.
2741
 *
2742
 * e.g. supra title:
2743
 * group
2744
 * GROUP PROPERTIES
2745
 *
2746
 * e.g. subtitle:
2747
 * AGENDA
2748
 * calender & events tool
2749
 *
2750
 * @author Hugues Peeters <[email protected]>
2751
 * @param  mixed $title_element - it could either be a string or an array
2752
 *                               containing 'supraTitle', 'mainTitle',
2753
 *                               'subTitle'
2754
 * @return void
2755
 */
2756
function api_display_tool_title($title_element) {
2757
    if (is_string($title_element)) {
2758
        $tit = $title_element;
2759
        unset ($title_element);
2760
        $title_element['mainTitle'] = $tit;
2761
    }
2762
    echo '<h3>';
2763
    if (!empty($title_element['supraTitle'])) {
2764
        echo '<small>'.$title_element['supraTitle'].'</small><br />';
2765
    }
2766
    if (!empty($title_element['mainTitle'])) {
2767
        echo $title_element['mainTitle'];
2768
    }
2769
    if (!empty($title_element['subTitle'])) {
2770
        echo '<br /><small>'.$title_element['subTitle'].'</small>';
2771
    }
2772
    echo '</h3>';
2773
}
2774
2775
/**
2776
 * Displays options for switching between student view and course manager view
2777
 *
2778
 * Changes in version 1.2 (Patrick Cool)
2779
 * Student view switch now behaves as a real switch. It maintains its current state until the state
2780
 * is changed explicitly
2781
 *
2782
 * Changes in version 1.1 (Patrick Cool)
2783
 * student view now works correctly in subfolders of the document tool
2784
 * student view works correctly in the new links tool
2785
 *
2786
 * Example code for using this in your tools:
2787
 * //if ($is_courseAdmin && api_get_setting('student_view_enabled') == 'true') {
2788
 * //   display_tool_view_option($isStudentView);
2789
 * //}
2790
 * //and in later sections, use api_is_allowed_to_edit()
2791
 *
2792
 * @author Roan Embrechts
2793
 * @author Patrick Cool
2794
 * @author Julio Montoya, changes added in Chamilo
2795
 * @version 1.2
2796
 * @todo rewrite code so it is easier to understand
2797
 */
2798
function api_display_tool_view_option() {
2799
    if (api_get_setting('student_view_enabled') != 'true') {
2800
        return '';
2801
    }
2802
2803
    $sourceurl = '';
2804
    $is_framed = false;
2805
    // Exceptions apply for all multi-frames pages
2806
    if (strpos($_SERVER['REQUEST_URI'], 'chat/chat_banner.php') !== false) {
2807
        // The chat is a multiframe bit that doesn't work too well with the student_view, so do not show the link
2808
        return '';
2809
    }
2810
2811
    // Uncomment to remove student view link from document view page
2812
    if (strpos($_SERVER['REQUEST_URI'], 'lp/lp_header.php') !== false) {
2813
        if (empty($_GET['lp_id'])) {
2814
            return '';
2815
        }
2816
        $sourceurl = substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], '?'));
2817
        $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);
2818
        //showinframes doesn't handle student view anyway...
2819
        //return '';
2820
        $is_framed = true;
2821
    }
2822
2823
    // Check whether the $_SERVER['REQUEST_URI'] contains already url parameters (thus a questionmark)
2824
    if (!$is_framed) {
2825
        if (strpos($_SERVER['REQUEST_URI'], '?') === false) {
2826
            $sourceurl = api_get_self().'?'.api_get_cidreq();
2827
        } else {
2828
            $sourceurl = $_SERVER['REQUEST_URI'];
2829
        }
2830
    }
2831
2832
    $output_string = '';
2833
    if (!empty($_SESSION['studentview'])) {
2834
        if ($_SESSION['studentview'] == 'studentview') {
2835
            // We have to remove the isStudentView=true from the $sourceurl
2836
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
2837
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
2838
            $output_string .= '<a class="btn btn-primary btn-sm" href="'.$sourceurl.'&isStudentView=false" target="_self">'.Display::returnFontAwesomeIcon('eye').' '.get_lang('SwitchToTeacherView').'</a>';
2839
        } elseif ($_SESSION['studentview'] == 'teacherview') {
2840
            // Switching to teacherview
2841
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
2842
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
2843
            $output_string .= '<a class="btn btn-default btn-sm" href="'.$sourceurl.'&isStudentView=true" target="_self">'.Display::returnFontAwesomeIcon('eye').' '.get_lang('SwitchToStudentView').'</a>';
2844
        }
2845
    } else {
2846
        $output_string .= '<a class="btn btn-default btn-sm" href="'.$sourceurl.'&isStudentView=true" target="_self">'.Display::returnFontAwesomeIcon('eye').' '.get_lang('SwitchToStudentView').'</a>';
2847
    }
2848
    $html = Display::tag('div', $output_string, array('class'=>'view-options'));
2849
    return $html;
2850
}
2851
2852
// TODO: This is for the permission section.
2853
/**
2854
 * Function that removes the need to directly use is_courseAdmin global in
2855
 * tool scripts. It returns true or false depending on the user's rights in
2856
 * this particular course.
2857
 * Optionally checking for tutor and coach roles here allows us to use the
2858
 * student_view feature altogether with these roles as well.
2859
 * @param bool  Whether to check if the user has the tutor role
2860
 * @param bool  Whether to check if the user has the coach role
2861
 * @param bool  Whether to check if the user has the session coach role
2862
 * @param bool  check the student view or not
2863
 *
2864
 * @author Roan Embrechts
2865
 * @author Patrick Cool
2866
 * @author Julio Montoya
2867
 * @version 1.1, February 2004
2868
 * @return boolean true: the user has the rights to edit, false: he does not
2869
 */
2870
2871
function api_is_allowed_to_edit(
2872
    $tutor = false,
2873
    $coach = false,
2874
    $session_coach = false,
2875
    $check_student_view = true
2876
) {
2877
    $my_session_id = api_get_session_id();
2878
    $is_allowed_coach_to_edit = api_is_coach(null, null, $check_student_view);
2879
    $session_visibility = api_get_session_visibility($my_session_id);
2880
2881
    // Admins can edit anything.
2882
    if (api_is_platform_admin(false)) {
2883
        // The student preview was on
2884
        if ($check_student_view && api_is_student_view_active()) {
2885
            return false;
2886
        } else {
2887
            return true;
2888
        }
2889
    }
2890
2891
    $is_courseAdmin = api_is_course_admin();
2892
2893
    if (!$is_courseAdmin && $tutor) {
2894
        // If we also want to check if the user is a tutor...
2895
        $is_courseAdmin = $is_courseAdmin || api_is_course_tutor();
2896
    }
2897
2898
    if (!$is_courseAdmin && $coach) {
2899
        // If we also want to check if the user is a coach...';
2900
        // Check if session visibility is read only for coaches.
2901
        if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
2902
            $is_allowed_coach_to_edit = false;
2903
        }
2904
2905
        if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
2906
            // Check if coach is allowed to edit a course.
2907
            $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
2908
        }
2909
    }
2910
2911
    if (!$is_courseAdmin && $session_coach) {
2912
        $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
2913
    }
2914
2915
    // Check if the student_view is enabled, and if so, if it is activated.
2916
    if (api_get_setting('student_view_enabled') == 'true') {
2917
        if (!empty($my_session_id)) {
2918
            // Check if session visibility is read only for coaches.
2919
            if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
2920
                $is_allowed_coach_to_edit = false;
2921
            }
2922
2923
            if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
2924
                // Check if coach is allowed to edit a course.
2925
                $is_allowed = $is_allowed_coach_to_edit;
2926
            } else {
2927
                $is_allowed = false;
2928
            }
2929
            if ($check_student_view) {
2930
                $is_allowed = $is_allowed && $_SESSION['studentview'] != 'studentview';
2931
            }
2932
        } else {
2933
            if ($check_student_view) {
2934
                $is_allowed = $is_courseAdmin && $_SESSION['studentview'] != 'studentview';
2935
            } else {
2936
                $is_allowed = $is_courseAdmin;
2937
            }
2938
        }
2939
2940
        return $is_allowed;
2941
    } else {
2942
2943
        return $is_courseAdmin;
2944
    }
2945
}
2946
2947
/**
2948
 * Returns true if user is a course coach of at least one course in session
2949
 * @param int $sessionId
2950
 * @return bool
2951
 */
2952
function api_is_coach_of_course_in_session($sessionId)
2953
{
2954
    if (api_is_platform_admin()) {
2955
        return true;
2956
    }
2957
2958
    $userId = api_get_user_id();
2959
    $courseList = UserManager::get_courses_list_by_session(
2960
        $userId,
2961
        $sessionId
2962
    );
2963
2964
    // Session visibility.
2965
    $visibility = api_get_session_visibility(
2966
        $sessionId,
2967
        null,
2968
        false
2969
    );
2970
2971 View Code Duplication
    if ($visibility != SESSION_VISIBLE && !empty($courseList)) {
2972
        // Course Coach session visibility.
2973
        $blockedCourseCount = 0;
2974
        $closedVisibilityList = array(
2975
            COURSE_VISIBILITY_CLOSED,
2976
            COURSE_VISIBILITY_HIDDEN
2977
        );
2978
2979
        foreach ($courseList as $course) {
2980
            // Checking session visibility
2981
            $sessionCourseVisibility = api_get_session_visibility(
2982
                $sessionId,
2983
                $course['real_id'],
2984
                $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...
2985
            );
2986
2987
            $courseIsVisible = !in_array(
2988
                $course['visibility'],
2989
                $closedVisibilityList
2990
            );
2991
            if ($courseIsVisible === false || $sessionCourseVisibility == SESSION_INVISIBLE) {
2992
                $blockedCourseCount++;
2993
            }
2994
        }
2995
2996
        // If all courses are blocked then no show in the list.
2997
        if ($blockedCourseCount === count($courseList)) {
2998
            $visibility = SESSION_INVISIBLE;
2999
        } else {
3000
            $visibility = SESSION_VISIBLE;
3001
        }
3002
    }
3003
3004
    switch ($visibility) {
3005
        case SESSION_VISIBLE_READ_ONLY:
3006
        case SESSION_VISIBLE:
3007
        case SESSION_AVAILABLE:
3008
            return true;
3009
            break;
3010
        case SESSION_INVISIBLE:
3011
            return false;
3012
    }
3013
3014
    return false;
3015
}
3016
3017
/**
3018
* Checks if a student can edit contents in a session depending
3019
* on the session visibility
3020
* @param bool $tutor  Whether to check if the user has the tutor role
3021
* @param bool  $coach Whether to check if the user has the coach role
3022
* @return boolean true: the user has the rights to edit, false: he does not
3023
*/
3024
function api_is_allowed_to_session_edit($tutor = false, $coach = false)
3025
{
3026
    if (api_is_allowed_to_edit($tutor, $coach)) {
3027
        // If I'm a teacher, I will return true in order to not affect the normal behaviour of Chamilo tools.
3028
        return true;
3029
    } else {
3030
        if (api_get_session_id() == 0) {
3031
            // I'm not in a session so i will return true to not affect the normal behaviour of Chamilo tools.
3032
            return true;
3033
        } else {
3034
            // I'm in a session and I'm a student
3035
            $session_id = api_get_session_id();
3036
3037
            // Get the session visibility
3038
            $session_visibility = api_get_session_visibility($session_id);
3039
            // if 5 the session is still available
3040
3041
            //@todo We could load the session_rel_course_rel_user permission to increase the level of detail.
3042
            //echo api_get_user_id();
3043
            //echo api_get_course_id();
3044
3045
            switch ($session_visibility) {
3046
                case SESSION_VISIBLE_READ_ONLY: // 1
3047
                    return false;
3048
                case SESSION_VISIBLE:           // 2
3049
                    return true;
3050
                case SESSION_INVISIBLE:         // 3
3051
                    return false;
3052
                case SESSION_AVAILABLE:         //5
3053
                    return true;
3054
            }
3055
        }
3056
    }
3057
}
3058
3059
/**
3060
* Checks whether the user is allowed in a specific tool for a specific action
3061
* @param string $tool the tool we are checking if the user has a certain permission
3062
* @param string $action the action we are checking (add, edit, delete, move, visibility)
3063
* @author Patrick Cool <[email protected]>, Ghent University
3064
* @author Julio Montoya
3065
* @version 1.0
3066
*/
3067
function api_is_allowed($tool, $action, $task_id = 0)
3068
{
3069
    $_user = api_get_user_info();
3070
    $_course = api_get_course_info();
3071
3072
    if (api_is_course_admin()) {
3073
        return true;
3074
    }
3075
    //if (!$_SESSION['total_permissions'][$_course['code']] and $_course)
3076
    if (is_array($_course) and count($_course) > 0) {
3077
        require_once api_get_path(SYS_CODE_PATH).'permissions/permissions_functions.inc.php';
3078
3079
        // Getting the permissions of this user.
3080
        if ($task_id == 0) {
3081
            $user_permissions = get_permissions('user', $_user['user_id']);
3082
            $_SESSION['total_permissions'][$_course['code']] = $user_permissions;
3083
        }
3084
3085
        // Getting the permissions of the task.
3086
        if ($task_id != 0) {
3087
            $task_permissions = get_permissions('task', $task_id);
3088
            /* !!! */$_SESSION['total_permissions'][$_course['code']] = $task_permissions;
3089
        }
3090
        //print_r($_SESSION['total_permissions']);
3091
3092
        // Getting the permissions of the groups of the user
3093
        //$groups_of_user = GroupManager::get_group_ids($_course['db_name'], $_user['user_id']);
3094
3095
        //foreach($groups_of_user as $group)
3096
        //   $this_group_permissions = get_permissions('group', $group);
3097
3098
        // Getting the permissions of the courseroles of the user
3099
        $user_courserole_permissions = get_roles_permissions('user', $_user['user_id']);
3100
3101
        // Getting the permissions of the platformroles of the user
3102
        //$user_platformrole_permissions = get_roles_permissions('user', $_user['user_id'], ', platform');
3103
3104
        // Getting the permissions of the roles of the groups of the user
3105
        //foreach($groups_of_user as $group)
3106
        //    $this_group_courserole_permissions = get_roles_permissions('group', $group);
3107
3108
        // Getting the permissions of the platformroles of the groups of the user
3109
        //foreach($groups_of_user as $group)
3110
        //    $this_group_platformrole_permissions = get_roles_permissions('group', $group, 'platform');
3111
    }
3112
3113
    // If the permissions are limited, we have to map the extended ones to the limited ones.
3114
    if (api_get_setting('permissions') == 'limited') {
3115
        if ($action == 'Visibility') {
3116
            $action = 'Edit';
3117
        }
3118
        if ($action == 'Move') {
3119
            $action = 'Edit';
3120
        }
3121
    }
3122
3123
    // The session that contains all the permissions already exists for this course
3124
    // so there is no need to requery everything.
3125
    //my_print_r($_SESSION['total_permissions'][$_course['code']][$tool]);
3126
    if (is_array($_SESSION['total_permissions'][$_course['code']][$tool])) {
3127
        if (in_array($action, $_SESSION['total_permissions'][$_course['code']][$tool])) {
3128
            return true;
3129
        } else {
3130
            return false;
3131
        }
3132
    }
3133
}
3134
3135
/**
3136
 * Tells whether this user is an anonymous user
3137
 * @param int  $user_id      User ID (optional, will take session ID if not provided)
3138
 * @param bool $db_check     Whether to check in the database (true) or simply in
3139
 * the session (false) to see if the current user is the anonymous user
3140
 * @return bool     true if this user is anonymous, false otherwise
3141
 */
3142
function api_is_anonymous($user_id = null, $db_check = false)
3143
{
3144
    if (!isset($user_id)) {
3145
        $user_id = api_get_user_id();
3146
    }
3147
3148
    if ($db_check) {
3149
        $info = api_get_user_info($user_id);
3150
3151
        if ($info['status'] == 6 || $user_id == 0 || empty($info)) {
3152
            return true;
3153
        }
3154
    }
3155
3156
    $_user = Session::read('_user');
3157
3158
    if (!isset($_user) || (isset($_user['user_id']) && $_user['user_id'] == 0)) {
3159
        // In some cases, api_set_anonymous doesn't seem to be triggered in local.inc.php. Make sure it is.
3160
        // Occurs in agenda for admin links - YW
3161
        /*global $use_anonymous;
3162
        if (isset($use_anonymous) && $use_anonymous) {*/
3163
        api_set_anonymous();
3164
        //}
3165
        return true;
3166
    }
3167
    return isset($_user['is_anonymous']) && $_user['is_anonymous'] === true;
3168
}
3169
3170
/**
3171
 * Displays message "You are not allowed here..." and exits the entire script.
3172
 * @param bool   $print_headers    Whether or not to print headers (default = false -> does not print them)
3173
 * @param string $message
3174
 */
3175
function api_not_allowed($print_headers = false, $message = null)
3176
{
3177
    if (empty($message)) {
3178
        $message = get_lang('NotAllowed');
3179
    }
3180
    throw new Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException($message);
3181
3182
    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...
3183
        global $osso;
3184
        if ($osso) {
3185
            $osso->logout();
3186
        }
3187
    }
3188
    $home_url = api_get_path(WEB_PATH);
3189
    $user_id = api_get_user_id();
3190
    $course = api_get_course_id();
3191
3192
    global $this_section;
3193
3194
    if (CustomPages::enabled() && !isset($user_id)) {
3195
3196
        if (empty($user_id)) {
3197
            // Why the CustomPages::enabled() need to be to set the request_uri
3198
            $_SESSION['request_uri'] = $_SERVER['REQUEST_URI'];
3199
        }
3200
3201
        CustomPages::display(CustomPages::INDEX_UNLOGGED);
3202
    }
3203
3204
    $origin = isset($_GET['origin']) ? $_GET['origin'] : '';
3205
3206
    $msg = null;
3207
    if (isset($message)) {
3208
        $msg = $message;
3209 View Code Duplication
    } else {
3210
        $msg = Display::return_message(
3211
            get_lang('NotAllowedClickBack').'<br/><br/><a href="'.$home_url.'">'.get_lang('ReturnToCourseHomepage').'</a>',
3212
            'error',
3213
            false
3214
        );
3215
    }
3216
3217
    $msg = Display::div($msg, array('align'=>'center'));
3218
3219
    $show_headers = 0;
3220
3221
    if ($print_headers && $origin != 'learnpath') {
3222
        $show_headers = 1;
3223
    }
3224
3225
    $tpl = new Template(null, $show_headers, $show_headers);
3226
    $tpl->assign('hide_login_link', 1);
3227
    $tpl->assign('content', $msg);
3228
3229
    if (($user_id != 0 && !api_is_anonymous()) &&
3230
        (!isset($course) || $course == -1) &&
3231
        empty($_GET['cidReq'])
3232
    ) {
3233
        // if the access is not authorized and there is some login information
3234
        // but the cidReq is not found, assume we are missing course data and send the user
3235
        // to the user_portal
3236
        $tpl->display_one_col_template();
3237
        exit;
3238
    }
3239
3240
    if (!empty($_SERVER['REQUEST_URI']) &&
3241
        (!empty($_GET['cidReq']) ||
3242
            $this_section == SECTION_MYPROFILE ||
3243
            $this_section == SECTION_PLATFORM_ADMIN
3244
        )
3245
    ) {
3246
        $courseCode = api_get_course_id();
3247
        // Only display form and return to the previous URL if there was a course ID included
3248
        if ($user_id != 0 && !api_is_anonymous()) {
3249
            //if there is a user ID, then the user is not allowed but the session is still there. Say so and exit
3250
            $tpl->assign('content', $msg);
3251
            $tpl->display_one_col_template();
3252
            exit;
3253
        }
3254
3255
        if (!is_null($courseCode)) {
3256
            api_set_firstpage_parameter($courseCode);
3257
        }
3258
3259
        // If the user has no user ID, then his session has expired
3260
        $action = api_get_self().'?'.Security::remove_XSS($_SERVER['QUERY_STRING']);
3261
        $action = str_replace('&amp;', '&', $action);
3262
        $form = new FormValidator(
3263
            'formLogin',
3264
            'post',
3265
            $action,
3266
            null,
3267
            array(),
3268
            FormValidator::LAYOUT_BOX_NO_LABEL
3269
        );
3270
        $form->addElement(
3271
            'text',
3272
            'login',
3273
            null,
3274
            array('placeholder' => get_lang('UserName'), 'autocapitalize' => 'none')
3275
        );
3276
        $form->addElement(
3277
            'password',
3278
            'password',
3279
            null,
3280
            array('placeholder' => get_lang('Password'), 'autocapitalize' => 'none')
3281
        );
3282
        $form->addButton('submitAuth', get_lang('LoginEnter'), '', 'primary');
3283
3284
        // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (above)
3285
        $content = Display::return_message(get_lang('NotAllowed'), 'error', false);
3286
3287
        if (!empty($courseCode)) {
3288
            $content .= '<h4>'.get_lang('LoginToGoToThisCourse').'</h4>';
3289
        }
3290
3291
        if (api_is_cas_activated()) {
3292
            $content .= Display::return_message(sprintf(get_lang('YouHaveAnInstitutionalAccount'), api_get_setting("Institution")), '', false);
3293
            $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'));
3294
            $content .= Display::return_message(get_lang('YouDontHaveAnInstitutionAccount'));
3295
            $content .= "<p style='text-align:center'><a href='#' onclick='$(this).parent().next().toggle()'>".get_lang('LoginWithExternalAccount')."</a></p>";
3296
            $content .= "<div style='display:none;'>";
3297
        }
3298
        $content .= '<div class="well">';
3299
        $content .= $form->returnForm();
3300
        $content .='</div>';
3301
        if (api_is_cas_activated()) {
3302
            $content .= "</div>";
3303
        }
3304
3305
        if (!empty($courseCode)) {
3306
            $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
3307
                get_lang('ReturnToCourseHomepage').'</a></p>';
3308
        } else {
3309
            $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
3310
                get_lang('BackHome').'</a></p>';
3311
        }
3312
3313
        $tpl->setLoginBodyClass();
3314
        $tpl->assign('content', $content);
3315
        $tpl->display_one_col_template();
3316
        exit;
3317
    }
3318
3319
    if ($user_id != 0 && !api_is_anonymous()) {
3320
        $tpl->display_one_col_template();
3321
        exit;
3322
    }
3323
3324
    $msg = null;
3325
3326
    // The session is over and we were not in a course,
3327
    // or we try to get directly to a private course without being logged
3328
    $courseId = api_get_course_int_id();
3329
    if (!empty($courseId)) {
3330
        api_set_firstpage_parameter(api_get_course_id());
3331
        $tpl->setLoginBodyClass();
3332
        $action = api_get_self().'?'.Security::remove_XSS($_SERVER['QUERY_STRING']);
3333
        $action = str_replace('&amp;', '&', $action);
3334
        $form = new FormValidator('formLogin', 'post', $action, null, array('class'=>'form-stacked'));
3335
        $form->addElement('text', 'login', null, array('autocapitalize' => 'none', 'placeholder' => get_lang('UserName'), 'class' => 'col-md-3'));
3336
        $form->addElement('password', 'password', null, array('placeholder' => get_lang('Password'), 'class' => 'col-md-3')); //new
3337
        $form->addButtonNext(get_lang('LoginEnter'), 'submitAuth');
3338
3339
        // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (bellow)
3340
        $msg = Display::return_message(get_lang('NotAllowed'), 'error', false);
3341
        $msg .= '<h4>'.get_lang('LoginToGoToThisCourse').'</h4>';
3342
        $casEnabled = api_is_cas_activated();
3343
        if ($casEnabled) {
3344
            $msg .= Display::return_message(sprintf(get_lang('YouHaveAnInstitutionalAccount'), api_get_setting("Institution")), '', false);
3345
            $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'));
3346
            $msg .= Display::return_message(get_lang('YouDontHaveAnInstitutionAccount'));
3347
            $msg .= "<p style='text-align:center'><a href='#' onclick='$(this).parent().next().toggle()'>".get_lang('LoginWithExternalAccount')."</a></p>";
3348
            $msg .= "<div style='display:none;'>";
3349
        }
3350
        $msg .= '<div class="well">';
3351
        $msg .= $form->returnForm();
3352
        $msg .='</div>';
3353
        if ($casEnabled) {
3354
            $msg .= "</div>";
3355
        }
3356 View Code Duplication
    } else {
3357
        // we were not in a course, return to home page
3358
        $msg = Display::return_message(
3359
            get_lang('NotAllowed').'<br/><br/><a href="'.$home_url.'">'.get_lang('BackHome').'</a><br />',
3360
            'error',
3361
            false
3362
        );
3363
    }
3364
3365
    $tpl->assign('content', $msg);
3366
    $tpl->display_one_col_template();
3367
    exit;
3368
}
3369
3370
/**
3371
 * Gets a UNIX timestamp from a database (MySQL) datetime format string
3372
 * @param $last_post_datetime standard output date in a sql query
3373
 * @return integer timestamp
3374
 * @author Toon Van Hoecke <[email protected]>
3375
 * @version October 2003
3376
 * @desc convert sql date to unix timestamp
3377
 */
3378
function convert_sql_date($last_post_datetime) {
3379
    list ($last_post_date, $last_post_time) = explode(' ', $last_post_datetime);
3380
    list ($year, $month, $day) = explode('-', $last_post_date);
3381
    list ($hour, $min, $sec) = explode(':', $last_post_time);
3382
    return mktime((int)$hour, (int)$min, (int)$sec, (int)$month, (int)$day, (int)$year);
3383
}
3384
3385
/**
3386
 * Gets item visibility from the item_property table
3387
 *
3388
 * Getting the visibility is done by getting the last updated visibility entry,
3389
 * using the largest session ID found if session 0 and another was found (meaning
3390
 * the only one that is actually from the session, in case there are results from
3391
 * session 0 *AND* session n).
3392
 * @param array     Course properties array (result of api_get_course_info())
3393
 * @param string    Tool (learnpath, document, etc)
3394
 * @param int       The item ID in the given tool
3395
 * @param int       The session ID (optional)
3396
 * @param string $tool
3397
 * @param integer $user_id
3398
 * @param string $type
3399
 * @return int      -1 on error, 0 if invisible, 1 if visible
3400
 */
3401
function api_get_item_visibility(
3402
    $_course,
3403
    $tool,
3404
    $id,
3405
    $session = 0,
3406
    $user_id = null,
3407
    $type = null,
3408
    $group_id = null
3409
) {
3410
    if (!is_array($_course) || count($_course) == 0 || empty($tool) || empty($id)) {
3411
        return -1;
3412
    }
3413
3414
    $tool = Database::escape_string($tool);
3415
    $id = intval($id);
3416
    $session = (int) $session;
3417
    $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
3418
    $course_id = intval($_course['real_id']);
3419
3420
    $userCondition = '';
3421
    if (!empty($user_id)) {
3422
        $user_id = intval($user_id);
3423
        $userCondition = " AND to_user_id = $user_id ";
3424
    }
3425
3426
    $typeCondition = '';
3427
    if (!empty($type)) {
3428
        $type = Database::escape_string($type);
3429
        $typeCondition = " AND lastedit_type = '$type' ";
3430
    }
3431
3432
    $groupCondition = '';
3433
    if (!empty($group_id)) {
3434
        $group_id = intval($group_id);
3435
        $groupCondition = " AND to_group_id = '$group_id' ";
3436
    }
3437
3438
    $sql = "SELECT visibility
3439
            FROM $TABLE_ITEMPROPERTY
3440
            WHERE
3441
                c_id = $course_id AND
3442
                tool = '$tool' AND
3443
                ref = $id AND
3444
                (session_id = $session OR session_id = 0 OR session_id IS NULL)
3445
                $userCondition $typeCondition $groupCondition
3446
            ORDER BY session_id DESC, lastedit_date DESC
3447
            LIMIT 1";
3448
3449
    $res = Database::query($sql);
3450
    if ($res === false || Database::num_rows($res) == 0) {
3451
        return -1;
3452
    }
3453
    $row = Database::fetch_array($res);
3454
3455
    return $row['visibility'];
3456
}
3457
3458
/**
3459
 * Delete a row in the c_item_property table
3460
 *
3461
 * @param array $courseInfo
3462
 * @param string $tool
3463
 * @param int $itemId
3464
 * @param int $userId
3465
 * @param int $groupId
3466
 * @param int $sessionId
3467
 * @return false|null
3468
 */
3469
function api_item_property_delete(
3470
    $courseInfo,
3471
    $tool,
3472
    $itemId,
3473
    $userId,
3474
    $groupId = 0,
3475
    $sessionId = 0
3476
) {
3477
    if (empty($courseInfo)) {
3478
        return false;
3479
    }
3480
3481
    $courseId = intval($courseInfo['real_id']);
3482
3483
    if (empty($courseId) || empty($tool) || empty($itemId)) {
3484
        return false;
3485
    }
3486
3487
    $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3488
    $tool = Database::escape_string($tool);
3489
    $itemId = intval($itemId);
3490
    $userId = intval($userId);
3491
    $groupId = intval($groupId);
3492
    $sessionId = intval($sessionId);
3493
3494
    $groupCondition = " AND to_group_id = $groupId ";
3495
    if (empty($groupId)) {
3496
        $groupCondition = " AND (to_group_id is NULL OR to_group_id = 0) ";
3497
    }
3498
3499
    $userCondition = " AND to_user_id = $userId ";
3500
    if (empty($userId)) {
3501
        $userCondition = " AND (to_user_id is NULL OR to_user_id = 0) ";
3502
    }
3503
    $sessionCondition = api_get_session_condition($sessionId, true, false, 'session_id');
3504
    $sql = "DELETE FROM $table
3505
            WHERE
3506
                c_id = $courseId AND
3507
                tool  = '$tool' AND
3508
                ref = $itemId
3509
                $sessionCondition
3510
                $userCondition
3511
                $groupCondition
3512
            ";
3513
3514
    Database::query($sql);
3515
}
3516
3517
/**
3518
 * Updates or adds item properties to the Item_propetry table
3519
 * Tool and lastedit_type are language independant strings (langvars->get_lang!)
3520
 *
3521
 * @param array $_course array with course properties
3522
 * @param string $tool tool id, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
3523
 * @param int $item_id id of the item itself, linked to key of every tool ('id', ...)
3524
 * @param string $last_edit_type add or update action
3525
 * (1) message to be translated (in trad4all) : e.g. DocumentAdded, DocumentUpdated;
3526
 * (2) "delete"
3527
 * (3) "visible"
3528
 * (4) "invisible"
3529
 * @param int $user_id id of the editing/adding user
3530
 * @param int $to_group_id group.iid
3531
 * @param int $to_user_id id of the intended user (always has priority over $to_group_id !), only relevant for $type (1)
3532
 * @param string $start_visible 0000-00-00 00:00:00 format
3533
 * @param string $end_visible 0000-00-00 00:00:00 format
3534
 * @param int $session_id The session ID, if any, otherwise will default to 0
3535
 * @return boolean False if update fails.
3536
 * @author Toon Van Hoecke <[email protected]>, Ghent University
3537
 * @version January 2005
3538
 * @desc update the item_properties table (if entry not exists, insert) of the course
3539
 */
3540
function api_item_property_update(
3541
    $_course,
3542
    $tool,
3543
    $item_id,
3544
    $last_edit_type,
3545
    $user_id,
3546
    $to_group_id = 0,
3547
    $to_user_id = null,
3548
    $start_visible = '',
3549
    $end_visible = '',
3550
    $session_id = 0
3551
) {
3552
    if (empty($_course)) {
3553
        return false;
3554
    }
3555
3556
    $course_id = $_course['real_id'];
3557
3558
    if (empty($course_id)) {
3559
        return false;
3560
    }
3561
3562
    $em = Database::getManager();
3563
3564
    // Definition of variables.
3565
    $tool = Database::escape_string($tool);
3566
    $item_id = intval($item_id);
3567
    $lastEditTypeNoFilter = $last_edit_type;
3568
    $last_edit_type = Database::escape_string($last_edit_type);
3569
    $user_id = intval($user_id);
3570
3571
    $startVisible = "NULL";
3572
    if (!empty($start_visible)) {
3573
        $start_visible = Database::escape_string($start_visible);
3574
        $startVisible = "'$start_visible'";
3575
    }
3576
3577
    $endVisible = "NULL";
3578
    if (!empty($end_visible)) {
3579
        $end_visible = Database::escape_string($end_visible);
3580
        $endVisible = "'$end_visible'";
3581
    }
3582
3583
    $to_filter = '';
3584
    $time = api_get_utc_datetime();
3585
3586
    if (!empty($session_id)) {
3587
        $session_id = intval($session_id);
3588
    } else {
3589
        $session_id = api_get_session_id();
3590
    }
3591
3592
    // Definition of tables.
3593
    $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
3594
3595
    if ($to_user_id <= 0) {
3596
        $to_user_id = null; // No to_user_id set
3597
    }
3598
3599
    if (!is_null($to_user_id)) {
3600
        // $to_user_id has more priority than $to_group_id
3601
        $to_user_id = intval($to_user_id);
3602
        $to_field = 'to_user_id';
3603
        $to_value = $to_user_id;
3604
    } else {
3605
        // $to_user_id is not set.
3606
        $to_field = 'to_group_id';
3607
        $to_value = $to_group_id;
3608
    }
3609
3610
    $toValueCondition = empty($to_value) ? "NULL" : "'$to_value'";
3611
3612
    // Set filters for $to_user_id and $to_group_id, with priority for $to_user_id
3613
    $condition_session = " AND session_id = $session_id ";
3614
    if (empty($session_id)) {
3615
        $condition_session = " AND (session_id = 0 OR session_id IS NULL) ";
3616
    }
3617
3618
    $filter = " c_id = $course_id AND tool = '$tool' AND ref = $item_id $condition_session ";
3619
3620
    // Check whether $to_user_id and $to_group_id are passed in the function call.
3621
    // If both are not passed (both are null) then it is a message for everybody and $to_group_id should be 0 !
3622
    if (is_null($to_user_id) && is_null($to_group_id)) {
3623
        $to_group_id = 0;
3624
    }
3625
3626
    if (!is_null($to_user_id)) {
3627
        // Set filter to intended user.
3628
        $to_filter = " AND to_user_id = $to_user_id $condition_session";
3629
    } else {
3630
        // Set filter to intended group.
3631
        if (($to_group_id != 0) && $to_group_id == strval(intval($to_group_id))) {
3632
            $to_filter = " AND to_group_id = $to_group_id $condition_session";
3633
        }
3634
    }
3635
3636
    // Adding filter if set.
3637
    $filter .= $to_filter;
3638
3639
    // Update if possible
3640
    $set_type = '';
3641
3642
    switch ($lastEditTypeNoFilter) {
3643 View Code Duplication
        case 'delete':
3644
            // delete = make item only visible for the platform admin.
3645
            $visibility = '2';
3646
            if (!empty($session_id)) {
3647
                // Check whether session id already exist into item_properties for updating visibility or add it.
3648
                $sql = "SELECT session_id FROM $tableItemProperty
3649
                        WHERE
3650
                            c_id = $course_id AND
3651
                            tool = '$tool' AND
3652
                            ref = $item_id AND
3653
                            session_id = $session_id";
3654
                $rs = Database::query($sql);
3655
                if (Database::num_rows($rs) > 0) {
3656
                    $sql = "UPDATE $tableItemProperty
3657
                            SET lastedit_type       = '".str_replace('_', '', ucwords($tool))."Deleted',
3658
                                lastedit_date       = '$time',
3659
                                lastedit_user_id    = $user_id,
3660
                                visibility          = $visibility,
3661
                                session_id          = $session_id $set_type
3662
                            WHERE $filter";
3663
                    $result = Database::query($sql);
3664
                } else {
3665
                    $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)
3666
                            VALUES ($course_id, '$tool',$item_id, '$time', $user_id, '$time', '$last_edit_type',$user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3667
                    $result = Database::query($sql);
3668
                    $id = Database::insert_id();
3669
                    if ($id) {
3670
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3671
                        Database::query($sql);
3672
                    }
3673
                }
3674
            } else {
3675
                $sql = "UPDATE $tableItemProperty
3676
                        SET
3677
                            lastedit_type='".str_replace('_', '', ucwords($tool))."Deleted',
3678
                            lastedit_date='$time',
3679
                            lastedit_user_id = $user_id,
3680
                            visibility = $visibility $set_type
3681
                        WHERE $filter";
3682
                $result = Database::query($sql);
3683
            }
3684
            break;
3685 View Code Duplication
        case 'visible' : // Change item to visible.
3686
            $visibility = '1';
3687
            if (!empty($session_id)) {
3688
                // Check whether session id already exist into item_properties for updating visibility or add it.
3689
                $sql = "SELECT session_id FROM $tableItemProperty
3690
                        WHERE
3691
                            c_id = $course_id AND
3692
                            tool = '$tool' AND
3693
                            ref = $item_id AND
3694
                            session_id = $session_id";
3695
                $rs = Database::query($sql);
3696
                if (Database::num_rows($rs) > 0) {
3697
                    $sql = "UPDATE $tableItemProperty
3698
                            SET
3699
                                lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
3700
                                lastedit_date='$time',
3701
                                lastedit_user_id = $user_id,
3702
                                visibility = $visibility,
3703
                                session_id = $session_id $set_type
3704
                            WHERE $filter";
3705
                    $result = Database::query($sql);
3706
                } else {
3707
                    $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)
3708
                            VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3709
                    $result = Database::query($sql);
3710
                    $id = Database::insert_id();
3711
                    if ($id) {
3712
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3713
                        Database::query($sql);
3714
                    }
3715
                }
3716
            } else {
3717
                $sql = "UPDATE $tableItemProperty
3718
                        SET
3719
                            lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
3720
                            lastedit_date='$time',
3721
                            lastedit_user_id = $user_id,
3722
                            visibility = $visibility $set_type
3723
                        WHERE $filter";
3724
                $result = Database::query($sql);
3725
            }
3726
            break;
3727 View Code Duplication
        case 'invisible' : // Change item to invisible.
3728
            $visibility = '0';
3729
            if (!empty($session_id)) {
3730
                // Check whether session id already exist into item_properties for updating visibility or add it
3731
                $sql = "SELECT session_id FROM $tableItemProperty
3732
                        WHERE
3733
                            c_id = $course_id AND
3734
                            tool = '$tool' AND
3735
                            ref = $item_id AND
3736
                            session_id = $session_id";
3737
                $rs = Database::query($sql);
3738
                if (Database::num_rows($rs) > 0) {
3739
                    $sql = "UPDATE $tableItemProperty
3740
                            SET
3741
                                lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
3742
                                lastedit_date = '$time',
3743
                                lastedit_user_id = $user_id,
3744
                                visibility = $visibility,
3745
                                session_id = $session_id $set_type
3746
                            WHERE $filter";
3747
                    $result = Database::query($sql);
3748
                } else {
3749
                    $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)
3750
                            VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
3751
                    $result = Database::query($sql);
3752
                    $id = Database::insert_id();
3753
                    if ($id) {
3754
                        $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
3755
                        Database::query($sql);
3756
                    }
3757
                }
3758
            } else {
3759
                $sql = "UPDATE $tableItemProperty
3760
                        SET
3761
                            lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
3762
                            lastedit_date = '$time',
3763
                            lastedit_user_id = $user_id,
3764
                            visibility = $visibility $set_type
3765
                        WHERE $filter";
3766
                $result = Database::query($sql);
3767
            }
3768
            break;
3769
        default: // The item will be added or updated.
3770
            $set_type = ", lastedit_type = '$last_edit_type' ";
3771
            $visibility = '1';
3772
            //$filter .= $to_filter; already added
3773
            $sql = "UPDATE $tableItemProperty
3774
                    SET
3775
                      lastedit_date = '$time',
3776
                      lastedit_user_id = $user_id $set_type
3777
                    WHERE $filter";
3778
            $result = Database::query($sql);
3779
    }
3780
3781
    // Insert if no entries are found (can only happen in case of $last_edit_type switch is 'default').
3782
    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...
3783
        $objCourse = $em->find('ChamiloCoreBundle:Course', intval($course_id));
3784
        $objTime = new DateTime('now', new DateTimeZone('UTC'));
3785
        $objUser = $em->find('ChamiloUserBundle:User', intval($user_id));
3786
        $objGroup = $em->find('ChamiloCourseBundle:CGroupInfo', intval($to_group_id));
3787
        $objToUser = $em->find('ChamiloUserBundle:User', intval($to_user_id));
3788
        $objSession = $em->find('ChamiloCoreBundle:Session', intval($session_id));
3789
3790
        $startVisibleDate = !empty($start_visible) ? new DateTime($start_visible, new DateTimeZone('UTC')) : null;
3791
        $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...
3792
3793
        $cItemProperty = new CItemProperty($objCourse);
3794
        $cItemProperty
3795
            ->setTool($tool)
3796
            ->setRef($item_id)
3797
            ->setInsertDate($objTime)
3798
            ->setInsertUser($objUser)
3799
            ->setLasteditDate($objTime)
3800
            ->setLasteditType($last_edit_type)
3801
            ->setGroup($objGroup)
3802
            ->setToUser($objToUser)
3803
            ->setVisibility($visibility)
3804
            ->setStartVisible($startVisibleDate)
3805
            ->setEndVisible($endVisibleDate)
3806
            ->setSession($objSession);
3807
3808
        $em->persist($cItemProperty);
3809
        $em->flush();
3810
3811
        $id = $cItemProperty->getIid();
3812
3813
        if ($id) {
3814
            $cItemProperty->setId($id);
3815
            $em->merge($cItemProperty);
3816
            $em->flush();
3817
3818
            return false;
3819
        }
3820
    }
3821
3822
    return true;
3823
}
3824
3825
/**
3826
 * Gets item property by tool
3827
 * @param string    course code
3828
 * @param string    tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
3829
 * @param int       id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
3830
 * @param int $session_id
3831
 * @param string $tool
3832
 * @param string $course_code
3833
 * @return array All fields from c_item_property (all rows found) or empty array
3834
 */
3835 View Code Duplication
function api_get_item_property_by_tool($tool, $course_code, $session_id = null)
3836
{
3837
    $course_info = api_get_course_info($course_code);
3838
    $tool = Database::escape_string($tool);
3839
3840
    // Definition of tables.
3841
    $item_property_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3842
    $session_id = intval($session_id);
3843
    $session_condition = ' AND session_id = '.$session_id;
3844
    if (empty($session_id)) {
3845
        $session_condition = " AND (session_id = 0 OR session_id IS NULL) ";
3846
    }
3847
    $course_id = $course_info['real_id'];
3848
3849
    $sql = "SELECT * FROM $item_property_table
3850
            WHERE
3851
                c_id = $course_id AND
3852
                tool = '$tool'
3853
                $session_condition ";
3854
    $rs  = Database::query($sql);
3855
    $list = array();
3856
    if (Database::num_rows($rs) > 0) {
3857
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
3858
            $list[] = $row;
3859
        }
3860
    }
3861
    return $list;
3862
}
3863
3864
/**
3865
 * Gets item property by tool and user
3866
 * @param int $userId
3867
 * @param int $tool
3868
 * @param int $courseId
3869
 * @param int $session_id
3870
 * @return array
3871
 */
3872 View Code Duplication
function api_get_item_property_list_by_tool_by_user(
3873
    $userId,
3874
    $tool,
3875
    $courseId,
3876
    $session_id = 0
3877
) {
3878
    $userId = intval($userId);
3879
    $tool = Database::escape_string($tool);
3880
    $session_id = intval($session_id);
3881
    $courseId = intval($courseId);
3882
3883
    // Definition of tables.
3884
    $item_property_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3885
    $session_condition = ' AND session_id = '.$session_id;
3886
    if (empty($session_id)) {
3887
        $session_condition = " AND (session_id = 0 OR session_id IS NULL) ";
3888
    }
3889
    $sql = "SELECT * FROM $item_property_table
3890
            WHERE
3891
                insert_user_id = $userId AND
3892
                c_id = $courseId AND
3893
                tool = '$tool'
3894
                $session_condition ";
3895
3896
    $rs = Database::query($sql);
3897
    $list = array();
3898
    if (Database::num_rows($rs) > 0) {
3899
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
3900
            $list[] = $row;
3901
        }
3902
    }
3903
3904
    return $list;
3905
}
3906
3907
/**
3908
 * Gets item property id from tool of a course
3909
 * @param string $course_code course code
3910
 * @param string $tool tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
3911
 * @param int $ref id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
3912
 * @param int $sessionId Session ID (optional)
3913
 * @return int
3914
 */
3915
function api_get_item_property_id($course_code, $tool, $ref, $sessionId = 0)
3916
{
3917
    $course_info = api_get_course_info($course_code);
3918
    $tool = Database::escape_string($tool);
3919
    $ref = intval($ref);
3920
3921
    // Definition of tables.
3922
    $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
3923
    $course_id = $course_info['real_id'];
3924
    $sessionId = (int) $sessionId;
3925
    $sessionCondition = " AND session_id = $sessionId ";
3926
    if (empty($sessionId)) {
3927
        $sessionCondition = " AND (session_id = 0 OR session_id IS NULL) ";
3928
    }
3929
    $sql = "SELECT id FROM $tableItemProperty
3930
            WHERE
3931
                c_id = $course_id AND
3932
                tool = '$tool' AND
3933
                ref = $ref
3934
                $sessionCondition";
3935
    $rs  = Database::query($sql);
3936
    $item_property_id = '';
3937
    if (Database::num_rows($rs) > 0) {
3938
        $row = Database::fetch_array($rs);
3939
        $item_property_id = $row['id'];
3940
    }
3941
    return $item_property_id;
3942
}
3943
3944
/**
3945
 * Inserts a record in the track_e_item_property table (No update)
3946
 * @param string $tool
3947
 * @param int $ref
3948
 * @param string $title
3949
 * @param string $content
3950
 * @param int $progress
3951
 * @return bool|int
3952
 */
3953
function api_track_item_property_update($tool, $ref, $title, $content, $progress)
3954
{
3955
    $tbl_stats_item_property = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY);
3956
    $course_id = api_get_course_int_id(); //numeric
3957
    $course_code = api_get_course_id(); //alphanumeric
3958
    $item_property_id = api_get_item_property_id($course_code, $tool, $ref);
3959
    if (!empty($item_property_id)) {
3960
        $sql = "INSERT IGNORE INTO $tbl_stats_item_property SET
3961
                course_id           = '$course_id',
3962
                item_property_id    = '$item_property_id',
3963
                title               = '".Database::escape_string($title)."',
3964
                content             = '".Database::escape_string($content)."',
3965
                progress            = '".intval($progress)."',
3966
                lastedit_date       = '".api_get_utc_datetime()."',
3967
                lastedit_user_id    = '".api_get_user_id()."',
3968
                session_id          = '".api_get_session_id()."'";
3969
        $result = Database::query($sql);
3970
        $affected_rows = Database::affected_rows($result);
3971
3972
        return $affected_rows;
3973
    }
3974
3975
    return false;
3976
}
3977
3978
/**
3979
 * @param string $tool
3980
 * @param int $ref
3981
 * @return array|resource
3982
 */
3983 View Code Duplication
function api_get_track_item_property_history($tool, $ref)
3984
{
3985
    $tbl_stats_item_property = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY);
3986
    $course_id = api_get_course_int_id(); //numeric
3987
    $course_code = api_get_course_id(); //alphanumeric
3988
    $item_property_id = api_get_item_property_id($course_code, $tool, $ref);
3989
    $sql = "SELECT * FROM $tbl_stats_item_property
3990
            WHERE item_property_id = $item_property_id AND course_id = $course_id
3991
            ORDER BY lastedit_date DESC";
3992
    $result = Database::query($sql);
3993
    if ($result == false) {
3994
        $result = array();
3995
    } else {
3996
        $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...
3997
    }
3998
3999
    return $result;
4000
}
4001
4002
/**
4003
 * Gets item property data from tool of a course id
4004
 * @param int $course_id
4005
 * @param string $tool   tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
4006
 * @param int $ref id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
4007
 * @param int $session_id
4008
 * @param int $groupId
4009
 *
4010
 * @return array Array with all fields from c_item_property, empty array if not found or false if course could not be found
4011
 */
4012
function api_get_item_property_info($course_id, $tool, $ref, $session_id = 0, $groupId = 0)
4013
{
4014
    $courseInfo = api_get_course_info_by_id($course_id);
4015
4016
    if (empty($courseInfo)) {
4017
        return false;
4018
    }
4019
4020
    $tool = Database::escape_string($tool);
4021
    $ref = intval($ref);
4022
    $course_id = $courseInfo['real_id'];
4023
    $session_id = intval($session_id);
4024
4025
    $sessionCondition = " session_id = $session_id";
4026
    if (empty($session_id)) {
4027
        $sessionCondition = " (session_id = 0 OR session_id IS NULL) ";
4028
    }
4029
4030
    // Definition of tables.
4031
    $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
4032
4033
    $sql = "SELECT * FROM $table
4034
            WHERE
4035
                c_id = $course_id AND
4036
                tool = '$tool' AND
4037
                ref = $ref AND
4038
                $sessionCondition ";
4039
4040
    if (!empty($groupId)) {
4041
        $groupId = intval($groupId);
4042
        $sql .= " AND to_group_id = $groupId ";
4043
    }
4044
4045
    $rs  = Database::query($sql);
4046
    $row = array();
4047
    if (Database::num_rows($rs) > 0) {
4048
        $row = Database::fetch_array($rs,'ASSOC');
4049
    }
4050
4051
    return $row;
4052
}
4053
4054
/**
4055
 * Displays a combo box so the user can select his/her preferred language.
4056
 * @param string The desired name= value for the select
4057
 * @param bool Whether we use the JQuery Chozen library or not
4058
 * (in some cases, like the indexing language picker, it can alter the presentation)
4059
 * @return string
4060
 */
4061
function api_get_languages_combo($name = 'language')
4062
{
4063
    $ret = '';
4064
    $platformLanguage = api_get_setting('platformLanguage');
4065
4066
    // Retrieve a complete list of all the languages.
4067
    $language_list = api_get_languages();
4068
4069
    if (count($language_list['name']) < 2) {
4070
        return $ret;
4071
    }
4072
4073
    // The the current language of the user so that his/her language occurs as selected in the dropdown menu.
4074
    if (isset($_SESSION['user_language_choice'])) {
4075
        $default = $_SESSION['user_language_choice'];
4076
    } else {
4077
        $default = $platformLanguage;
4078
    }
4079
4080
    $languages  = $language_list['name'];
4081
    $folder     = $language_list['folder'];
4082
4083
    $ret .= '<select name="' . $name . '" id="language_chosen" class="selectpicker show-tick form-control">';
4084
    foreach ($languages as $key => $value) {
4085
        if ($folder[$key] == $default) {
4086
            $selected = ' selected="selected"';
4087
        } else {
4088
            $selected = '';
4089
        }
4090
        $ret .= sprintf('<option value=%s" %s>%s</option>', $folder[$key], $selected, $value);
4091
    }
4092
    $ret .= '</select>';
4093
    return $ret;
4094
}
4095
4096
/**
4097
 * Displays a form (drop down menu) so the user can select his/her preferred language.
4098
 * The form works with or without javascript
4099
 * @param  boolean Hide form if only one language available (defaults to false = show the box anyway)
4100
 * @return null|string Display the box directly
4101
 */
4102
function api_display_language_form($hide_if_no_choice = false)
4103
{
4104
    // Retrieve a complete list of all the languages.
4105
    $language_list = api_get_languages();
4106
4107
    if (count($language_list) <= 1 && $hide_if_no_choice) {
4108
        return; //don't show any form
4109
    }
4110
4111
    // The the current language of the user so that his/her language occurs as selected in the dropdown menu.
4112
    if (isset($_SESSION['user_language_choice'])) {
4113
        $user_selected_language = $_SESSION['user_language_choice'];
4114
    }
4115
    if (empty($user_selected_language)) {
4116
        $user_selected_language = api_get_setting('platformLanguage');
4117
    }
4118
4119
    $original_languages = $language_list;
4120
    $folder = $language_list; // This line is probably no longer needed.
4121
    $html = '<script>    
4122
    $(document).ready(function() {
4123
        $("#language_list").change(function() {
4124
            jumpMenu("parent",this,0);
4125
        });
4126
    });
4127
4128
    function jumpMenu(targ,selObj,restore){ // v3.0
4129
        eval(targ+".location=\'"+selObj.options[selObj.selectedIndex].value+"\'");
4130
        if (restore) selObj.selectedIndex=0;
4131
    }
4132
    </script>';
4133
    $html .= '<form id="lang_form" name="lang_form" method="post" action="'.api_get_self().'">';
4134
    $html .= '<label style="display: none;" for="language_list">' . get_lang('Language') . '</label>';
4135
    $html .=  '<select id="language_list" class="selectpicker show-tick form-control" name="language_list" >';
4136
4137
    foreach ($original_languages as $key => $value) {
4138
        if ($folder[$key] == $user_selected_language) {
4139
            $option_end = ' selected="selected" >';
4140
        } else {
4141
            $option_end = '>';
4142
        }
4143
        $html .=  '<option value="'.api_get_self().'?language='.$folder[$key].'"'.$option_end;
4144
        //echo substr($value, 0, 16); // Cut string to keep 800x600 aspect.
4145
        $html .=  $value.'</option>';
4146
    }
4147
    $html .=  '</select>';
4148
    $html .=  '<noscript><input type="submit" name="user_select_language" value="'.get_lang('Ok').'" /></noscript>';
4149
    $html .=  '</form>';
4150
    return $html;
4151
}
4152
4153
/**
4154
 * Returns a list of all the languages that are made available by the admin.
4155
 * @return array An array with all languages. Structure of the array is
4156
 *  array['name'] = An array with the name of every language
4157
 *  array['folder'] = An array with the corresponding names of the language-folders in the filesystem
4158
 */
4159
function api_get_languages() {
4160
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4161
    $sql = "SELECT * FROM $tbl_language WHERE available='1' 
4162
            ORDER BY original_name ASC";
4163
    $result = Database::query($sql);
4164
    $language_list = array();
4165
   while ($row = Database::fetch_array($result)) {
4166
        $language_list[$row['isocode']] = $row['original_name'];
4167
    }
4168
    return $language_list;
4169
}
4170
4171
/**
4172
 * Returns a list of all the languages that are made available by the admin.
4173
 * @return array
4174
 */
4175 View Code Duplication
function api_get_languages_to_array() {
4176
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4177
    $sql = "SELECT * FROM $tbl_language WHERE available='1' ORDER BY original_name ASC";
4178
    $result = Database::query($sql);
4179
    $languages = array();
4180
    while ($row = Database::fetch_array($result)) {
4181
        $languages[$row['dokeos_folder']] = $row['original_name'];
4182
    }
4183
    return $languages;
4184
}
4185
4186
/**
4187
 * Returns the id (the database id) of a language
4188
 * @param   string  language name (the corresponding name of the language-folder in the filesystem)
4189
 * @return  int     id of the language
4190
 */
4191 View Code Duplication
function api_get_language_id($language)
4192
{
4193
    $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
4194
    if (empty($language)) {
4195
        return null;
4196
    }
4197
    $language = Database::escape_string($language);
4198
    $sql = "SELECT id FROM $tbl_language
4199
            WHERE dokeos_folder = '$language' LIMIT 1";
4200
    $result = Database::query($sql);
4201
    $row = Database::fetch_array($result);
4202
    return $row['id'];
4203
}
4204
4205
/**
4206
 * Gets language of the requested type for the current user. Types are :
4207
 * user_profil_lang : profile language of current user
4208
 * user_select_lang : language selected by user at login
4209
 * course_lang : language of the current course
4210
 * platform_lang : default platform language
4211
 * @param string $lang_type
4212
 * @return string
4213
 **/
4214
function api_get_language_from_type($lang_type)
4215
{
4216
    $return = false;
4217
    switch ($lang_type) {
4218
        case 'platform_lang':
4219
            $temp_lang = api_get_setting('platformLanguage');
4220
            if (!empty($temp_lang))
4221
                $return = $temp_lang;
4222
            break;
4223
        case 'user_profil_lang':
4224
            $_user = api_get_user_info();
4225
4226
            if (isset($_user['language']) && !empty($_user['language']))
4227
                $return = $_user['language'];
4228
            break;
4229
        case 'user_selected_lang':
4230 View Code Duplication
            if (isset($_SESSION['user_language_choice']) && !empty($_SESSION['user_language_choice']))
4231
                $return = $_SESSION['user_language_choice'];
4232
            break;
4233
        case 'course_lang':
4234
            global $_course;
4235
            $cidReq = null;
4236
            if (empty($_course)) {
4237
4238
                // Code modified because the local.inc.php file it's declarated after this work
4239
                // causing the function api_get_course_info() returns a null value
4240
                $cidReq = isset($_GET["cidReq"]) ? Database::escape_string($_GET["cidReq"]) : null;
4241
                $cDir = (!empty($_GET['cDir']) ? $_GET['cDir'] : null);
4242
                if (empty($cidReq) && !empty($cDir)) {
4243
                    $c = CourseManager::get_course_id_from_path($cDir);
4244
                    if ($c) {
4245
                        $cidReq = $c;
4246
                    }
4247
                }
4248
            }
4249
            $_course = api_get_course_info($cidReq);
4250
            if (isset($_course['language']) && !empty($_course['language'])) {
4251
                $return = $_course['language'];
4252
                $showCourseInUserLanguage = api_get_course_setting('show_course_in_user_language');
4253
                if ($showCourseInUserLanguage == 1) {
4254
                    $userInfo = api_get_user_info();
4255
                    if (isset($userInfo['language'])) {
4256
                        $return = $userInfo['language'];
4257
                    }
4258
                }
4259
            }
4260
            break;
4261
        default:
4262
            $return = false;
4263
        break;
4264
    }
4265
4266
    return $return;
4267
}
4268
4269
/**
4270
 * Get the language information by its id
4271
 * @param int $languageId
4272
 * @return array
4273
 */
4274
function api_get_language_info($languageId) {
4275
    $language = Database::getManager()
4276
        ->find('ChamiloCoreBundle:Language', intval($languageId));
4277
4278
    if (!$language) {
4279
        return [];
4280
    }
4281
4282
    return [
4283
        'id' => $language->getId(),
4284
        'original_name' => $language->getOriginalName(),
4285
        'english_name' => $language->getEnglishName(),
4286
        'isocode' => $language->getIsocode(),
4287
        'dokeos_folder' => $language->getDokeosFolder(),
4288
        'available' => $language->getAvailable(),
4289
        'parent_id' => $language->getParent() ? $language->getParent()->getId() : null
4290
    ];
4291
}
4292
4293
/**
4294
 * Returns the name of the visual (CSS) theme to be applied on the current page.
4295
 * The returned name depends on the platform, course or user -wide settings.
4296
 * @return string   The visual theme's name, it is the name of a folder inside .../chamilo/main/css/
4297
 */
4298
function api_get_visual_theme()
4299
{
4300
    static $visual_theme;
4301
    if (!isset($visual_theme)) {
4302
4303
        $platform_theme = api_get_setting('stylesheets');
4304
4305
        // Platform's theme.
4306
        $visual_theme = $platform_theme;
4307
4308
        if (api_get_setting('profile.user_selected_theme') == 'true') {
4309
            $user_info = api_get_user_info();
4310
            if (isset($user_info['theme'])) {
4311
                $user_theme = $user_info['theme'];
4312
4313
                if (!empty($user_theme)) {
4314
                    $visual_theme = $user_theme;
4315
                    // User's theme.
4316
                }
4317
            }
4318
        }
4319
4320
        $course_id = api_get_course_id();
4321
4322
        if (!empty($course_id) && $course_id != -1) {
4323
            if (api_get_setting('course.allow_course_theme') == 'true') {
4324
                $course_theme = api_get_course_setting('course_theme');
4325
4326
                if (!empty($course_theme) && $course_theme != -1) {
4327
                    if (!empty($course_theme)) {
4328
                        // Course's theme.
4329
                        $visual_theme = $course_theme;
4330
                    }
4331
                }
4332
4333
                $allow_lp_theme = api_get_course_setting('allow_learning_path_theme');
4334
                if ($allow_lp_theme == 1) {
4335
                    global $lp_theme_css, $lp_theme_config;
4336
                    // These variables come from the file lp_controller.php.
4337
                    if (!$lp_theme_config) {
4338
                        if (!empty($lp_theme_css)) {
4339
                            // LP's theme.
4340
                            $visual_theme = $lp_theme_css;
4341
                        }
4342
                    }
4343
                }
4344
            }
4345
        }
4346
4347
        if (empty($visual_theme)) {
4348
            $visual_theme = 'chamilo';
4349
        }
4350
4351
        global $lp_theme_log;
4352
        if ($lp_theme_log) {
4353
            $visual_theme = $platform_theme;
4354
        }
4355
    }
4356
4357
    return $visual_theme;
4358
}
4359
4360
/**
4361
 * Returns a list of CSS themes currently available in the CSS folder
4362
 * @return array        List of themes directories from the css folder
4363
 * Note: Directory names (names of themes) in the file system should contain ASCII-characters only.
4364
 */
4365
function api_get_themes() {
4366
    $cssdir = api_get_path(SYS_CSS_PATH) . 'themes/';
4367
    $list_dir = array();
4368
    $list_name = array();
4369
4370
    if (is_dir($cssdir)) {
4371
        $themes = @scandir($cssdir);
4372
4373
        if (is_array($themes)) {
4374
            if ($themes !== false) {
4375
                sort($themes);
4376
4377
                foreach ($themes as & $theme) {
4378
                    if (substr($theme, 0, 1) == '.') {
4379
                        continue;
4380
                    } else {
4381
                        if (is_dir($cssdir.$theme)) {
4382
                            $list_dir[] = $theme;
4383
                            $list_name[] = ucwords(str_replace('_', ' ', $theme));
4384
                        }
4385
                    }
4386
                }
4387
            }
4388
        }
4389
    }
4390
4391
    return array($list_dir, $list_name);
4392
}
4393
4394
/**
4395
 * Find the largest sort value in a given user_course_category
4396
 * This function is used when we are moving a course to a different category
4397
 * and also when a user subscribes to courses (the new course is added at the end of the main category
4398
 * @author Patrick Cool <[email protected]>, Ghent University
4399
 * @param int $user_course_category the id of the user_course_category
4400
 * @param integer $user_id
4401
 * @return int the value of the highest sort of the user_course_category
4402
 */
4403 View Code Duplication
function api_max_sort_value($user_course_category, $user_id)
4404
{
4405
    $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4406
    $sql = "SELECT max(sort) as max_sort FROM $tbl_course_user
4407
            WHERE
4408
                user_id='".intval($user_id)."' AND
4409
                relation_type<>".COURSE_RELATION_TYPE_RRHH." AND
4410
                user_course_cat='".intval($user_course_category)."'";
4411
    $result_max = Database::query($sql);
4412
    if (Database::num_rows($result_max) == 1) {
4413
        $row_max = Database::fetch_array($result_max);
4414
        return $row_max['max_sort'];
4415
    }
4416
    return 0;
4417
}
4418
4419
/**
4420
 * Determines the number of plugins installed for a given location
4421
 */
4422
function api_number_of_plugins($location) {
4423
    global $_plugins;
4424
    return isset($_plugins[$location]) && is_array($_plugins[$location]) ? count($_plugins[$location]) : 0;
4425
}
4426
4427
/**
4428
 * Transforms a number of seconds in hh:mm:ss format
4429
 * @author Julian Prud'homme
4430
 * @param integer the number of seconds
4431
 * @return string the formated time
4432
 */
4433
function api_time_to_hms($seconds)
4434
{
4435
    // $seconds = -1 means that we have wrong data in the db.
4436
    if ($seconds == -1) {
4437
        return
4438
            get_lang('Unknown').
4439
            Display::return_icon(
4440
                'info2.gif',
4441
                get_lang('WrongDatasForTimeSpentOnThePlatform'),
4442
                array('align' => 'absmiddle', 'hspace' => '3px')
4443
            );
4444
    }
4445
4446
    // How many hours ?
4447
    $hours = floor($seconds / 3600);
4448
4449
    // How many minutes ?
4450
    $min = floor(($seconds - ($hours * 3600)) / 60);
4451
4452
    // How many seconds
4453
    $sec = floor($seconds - ($hours * 3600) - ($min * 60));
4454
4455
    if ($sec < 10) {
4456
        $sec = "0$sec";
4457
    }
4458
4459
    if ($min < 10) {
4460
        $min = "0$min";
4461
    }
4462
4463
    return "$hours:$min:$sec";
4464
}
4465
4466
/* FILE SYSTEM RELATED FUNCTIONS */
4467
4468
/**
4469
 * Returns the permissions to be assigned to every newly created directory by the web-server.
4470
 * The return value is based on the platform administrator's setting
4471
 * "Administration > Configuration settings > Security > Permissions for new directories".
4472
 * @return int  Returns the permissions in the format "Owner-Group-Others, Read-Write-Execute", as an integer value.
4473
 */
4474 View Code Duplication
function api_get_permissions_for_new_directories() {
4475
    static $permissions;
4476
    if (!isset($permissions)) {
4477
        $permissions = trim(api_get_setting('permissions_for_new_directories'));
4478
        // The default value 0777 is according to that in the platform administration panel after fresh system installation.
4479
        $permissions = octdec(!empty($permissions) ? $permissions : '0777');
4480
    }
4481
    return $permissions;
4482
}
4483
4484
/**
4485
 * Returns the permissions to be assigned to every newly created directory by the web-server.
4486
 * The return value is based on the platform administrator's setting
4487
 * "Administration > Configuration settings > Security > Permissions for new files".
4488
 * @return int Returns the permissions in the format
4489
 * "Owner-Group-Others, Read-Write-Execute", as an integer value.
4490
 */
4491 View Code Duplication
function api_get_permissions_for_new_files() {
4492
    static $permissions;
4493
    if (!isset($permissions)) {
4494
        $permissions = trim(api_get_setting('permissions_for_new_files'));
4495
        // The default value 0666 is according to that in the platform
4496
        // administration panel after fresh system installation.
4497
        $permissions = octdec(!empty($permissions) ? $permissions : '0666');
4498
    }
4499
    return $permissions;
4500
}
4501
4502
/**
4503
 * Deletes a file, or a folder and its contents
4504
 *
4505
 * @author      Aidan Lister <[email protected]>
4506
 * @version     1.0.3
4507
 * @param       string   $dirname    Directory to delete
4508
 * @param       bool     Deletes only the content or not
4509
 * @param       bool     $strict if one folder/file fails stop the loop
4510
 * @return      bool     Returns TRUE on success, FALSE on failure
4511
 * @link http://aidanlister.com/2004/04/recursively-deleting-a-folder-in-php/
4512
 * @author      Yannick Warnier, adaptation for the Chamilo LMS, April, 2008
4513
 * @author      Ivan Tcholakov, a sanity check about Directory class creation has been added, September, 2009
4514
 */
4515
function rmdirr($dirname, $delete_only_content_in_folder = false, $strict = false) {
4516
    $res = true;
4517
4518
    // A sanity check.
4519
    if (!file_exists($dirname)) {
4520
        return false;
4521
    }
4522
    $php_errormsg = '';
4523
    // Simple delete for a file.
4524
    if (is_file($dirname) || is_link($dirname)) {
4525
        $res = unlink($dirname);
4526 View Code Duplication
        if ($res === false) {
4527
            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);
4528
        }
4529
        return $res;
4530
    }
4531
4532
    // Loop through the folder.
4533
    $dir = dir($dirname);
4534
    // A sanity check.
4535
    $is_object_dir = is_object($dir);
4536 View Code Duplication
    if ($is_object_dir) {
4537
        while (false !== $entry = $dir->read()) {
4538
            // Skip pointers.
4539
            if ($entry == '.' || $entry == '..') {
4540
                continue;
4541
            }
4542
4543
            // Recurse.
4544
            if ($strict) {
4545
                $result = rmdirr("$dirname/$entry");
4546
                if ($result == false) {
4547
                    $res = false;
4548
                    break;
4549
                }
4550
            } else {
4551
                rmdirr("$dirname/$entry");
4552
            }
4553
        }
4554
    }
4555
4556
    // Clean up.
4557
    if ($is_object_dir) {
4558
        $dir->close();
4559
    }
4560
4561
    if ($delete_only_content_in_folder == false) {
4562
        $res = rmdir($dirname);
4563 View Code Duplication
        if ($res === false) {
4564
            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);
4565
        }
4566
    }
4567
    return $res;
4568
}
4569
4570
// TODO: This function is to be simplified. File access modes to be implemented.
4571
/**
4572
 * function adapted from a php.net comment
4573
 * copy recursively a folder
4574
 * @param the source folder
4575
 * @param the dest folder
4576
 * @param an array of excluded file_name (without extension)
4577
 * @param copied_files the returned array of copied files
4578
 * @param string $source
4579
 * @param string $dest
4580
 */
4581
function copyr($source, $dest, $exclude = array(), $copied_files = array()) {
4582
    if (empty($dest)) { return false; }
4583
    // Simple copy for a file
4584
    if (is_file($source)) {
4585
        $path_info = pathinfo($source);
4586
        if (!in_array($path_info['filename'], $exclude)) {
4587
            copy($source, $dest);
4588
        }
4589
        return true;
4590
    } elseif (!is_dir($source)) {
4591
        //then source is not a dir nor a file, return
4592
        return false;
4593
    }
4594
4595
    // Make destination directory.
4596
    if (!is_dir($dest)) {
4597
        mkdir($dest, api_get_permissions_for_new_directories());
4598
    }
4599
4600
    // Loop through the folder.
4601
    $dir = dir($source);
4602
    while (false !== $entry = $dir->read()) {
4603
        // Skip pointers
4604
        if ($entry == '.' || $entry == '..') {
4605
            continue;
4606
        }
4607
4608
        // Deep copy directories.
4609
        if ($dest !== "$source/$entry") {
4610
            $files = copyr("$source/$entry", "$dest/$entry", $exclude, $copied_files);
4611
        }
4612
    }
4613
    // Clean up.
4614
    $dir->close();
4615
    return true;
4616
}
4617
4618
// TODO: Using DIRECTORY_SEPARATOR is not recommended, this is an obsolete approach. Documentation header to be added here.
4619
/**
4620
 * @param string $pathname
4621
 * @param string $base_path_document
4622
 * @param integer $session_id
4623
 */
4624
function copy_folder_course_session(
4625
    $pathname,
4626
    $base_path_document,
4627
    $session_id,
4628
    $course_info,
4629
    $document,
4630
    $source_course_id
4631
) {
4632
    $table = Database :: get_course_table(TABLE_DOCUMENT);
4633
    $session_id = intval($session_id);
4634
    $source_course_id = intval($source_course_id);
4635
4636
    // Check whether directory already exists.
4637
    if (is_dir($pathname) || empty($pathname)) {
4638
        return true;
4639
    }
4640
4641
    // Ensure that a file with the same name does not already exist.
4642
    if (is_file($pathname)) {
4643
        trigger_error('copy_folder_course_session(): File exists', E_USER_WARNING);
4644
        return false;
4645
    }
4646
4647
    $course_id = $course_info['real_id'];
4648
4649
    $folders = explode(DIRECTORY_SEPARATOR,str_replace($base_path_document.DIRECTORY_SEPARATOR,'',$pathname));
4650
4651
    $new_pathname = $base_path_document;
4652
    $path = '';
4653
4654
    foreach ($folders as $folder) {
4655
        $new_pathname .= DIRECTORY_SEPARATOR.$folder;
4656
        $path .= DIRECTORY_SEPARATOR.$folder;
4657
4658
        if (!file_exists($new_pathname)) {
4659
            $path = Database::escape_string($path);
4660
4661
            $sql = "SELECT * FROM $table
4662
                    WHERE
4663
                        c_id = $source_course_id AND
4664
                        path = '$path' AND
4665
                        filetype = 'folder' AND
4666
                        session_id = '$session_id'";
4667
            $rs1  = Database::query($sql);
4668
            $num_rows = Database::num_rows($rs1);
4669
4670
            if ($num_rows == 0) {
4671
                mkdir($new_pathname, api_get_permissions_for_new_directories());
4672
4673
                // Insert new folder with destination session_id.
4674
                $params = [
4675
                    'c_id' => $course_id,
4676
                    'path' => $path,
4677
                    'comment' => $document->comment,
4678
                    'title' => basename($new_pathname),
4679
                    'filetype' => 'folder',
4680
                    'size' => '0',
4681
                    'session_id' => $session_id
4682
                ];
4683
                $document_id = Database::insert($table, $params);
4684 View Code Duplication
                if ($document_id) {
4685
4686
                    $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
4687
                    Database::query($sql);
4688
4689
                    api_item_property_update(
4690
                        $course_info,
4691
                        TOOL_DOCUMENT,
4692
                        $document_id,
4693
                        'FolderCreated',
4694
                        api_get_user_id(),
4695
                        0,
4696
                        0,
4697
                        null,
4698
                        null,
4699
                        $session_id
4700
                    );
4701
                }
4702
            }
4703
        }
4704
4705
    } // en foreach
4706
}
4707
4708
// TODO: chmodr() is a better name. Some corrections are needed. Documentation header to be added here.
4709
/**
4710
 * @param string $path
4711
 */
4712
function api_chmod_R($path, $filemode) {
4713
    if (!is_dir($path)) {
4714
        return chmod($path, $filemode);
4715
    }
4716
4717
    $handler = opendir($path);
4718
    while ($file = readdir($handler)) {
4719
        if ($file != '.' && $file != '..') {
4720
            $fullpath = "$path/$file";
4721
            if (!is_dir($fullpath)) {
4722
                if (!chmod($fullpath, $filemode)) {
4723
                    return false;
4724
                }
4725
            } else {
4726
                if (!api_chmod_R($fullpath, $filemode)) {
4727
                    return false;
4728
                }
4729
            }
4730
        }
4731
    }
4732
4733
    closedir($handler);
4734
    return chmod($path, $filemode);
4735
}
4736
4737
4738
// TODO: Where the following function has been copy/pased from? There is no information about author and license. Style, coding conventions...
4739
/**
4740
 * Parse info file format. (e.g: file.info)
4741
 *
4742
 * Files should use an ini-like format to specify values.
4743
 * White-space generally doesn't matter, except inside values.
4744
 * e.g.
4745
 *
4746
 * @verbatim
4747
 *   key = value
4748
 *   key = "value"
4749
 *   key = 'value'
4750
 *   key = "multi-line
4751
 *
4752
 *   value"
4753
 *   key = 'multi-line
4754
 *
4755
 *   value'
4756
 *   key
4757
 *   =
4758
 *   'value'
4759
 * @endverbatim
4760
 *
4761
 * Arrays are created using a GET-like syntax:
4762
 *
4763
 * @verbatim
4764
 *   key[] = "numeric array"
4765
 *   key[index] = "associative array"
4766
 *   key[index][] = "nested numeric array"
4767
 *   key[index][index] = "nested associative array"
4768
 * @endverbatim
4769
 *
4770
 * PHP constants are substituted in, but only when used as the entire value:
4771
 *
4772
 * Comments should start with a semi-colon at the beginning of a line.
4773
 *
4774
 * This function is NOT for placing arbitrary module-specific settings. Use
4775
 * variable_get() and variable_set() for that.
4776
 *
4777
 * Information stored in the module.info file:
4778
 * - name: The real name of the module for display purposes.
4779
 * - description: A brief description of the module.
4780
 * - dependencies: An array of shortnames of other modules this module depends on.
4781
 * - package: The name of the package of modules this module belongs to.
4782
 *
4783
 * Example of .info file:
4784
 * <code>
4785
 * @verbatim
4786
 *   name = Forum
4787
 *   description = Enables threaded discussions about general topics.
4788
 *   dependencies[] = taxonomy
4789
 *   dependencies[] = comment
4790
 *   package = Core - optional
4791
 *   version = VERSION
4792
 * @endverbatim
4793
 * </code>
4794
 * @param string $filename
4795
 *   The file we are parsing. Accepts file with relative or absolute path.
4796
 * @return
4797
 *   The info array.
4798
 */
4799
function api_parse_info_file($filename) {
4800
    $info = array();
4801
4802
    if (!file_exists($filename)) {
4803
        return $info;
4804
    }
4805
4806
    $data = file_get_contents($filename);
4807
    if (preg_match_all('
4808
        @^\s*                           # Start at the beginning of a line, ignoring leading whitespace
4809
        ((?:
4810
          [^=;\[\]]|                    # Key names cannot contain equal signs, semi-colons or square brackets,
4811
          \[[^\[\]]*\]                  # unless they are balanced and not nested
4812
        )+?)
4813
        \s*=\s*                         # Key/value pairs are separated by equal signs (ignoring white-space)
4814
        (?:
4815
          ("(?:[^"]|(?<=\\\\)")*")|     # Double-quoted string, which may contain slash-escaped quotes/slashes
4816
          (\'(?:[^\']|(?<=\\\\)\')*\')| # Single-quoted string, which may contain slash-escaped quotes/slashes
4817
          ([^\r\n]*?)                   # Non-quoted string
4818
        )\s*$                           # Stop at the next end of a line, ignoring trailing whitespace
4819
        @msx', $data, $matches, PREG_SET_ORDER)) {
4820
        $key = $value1 = $value2 = $value3 = '';
4821
        foreach ($matches as $match) {
4822
            // Fetch the key and value string.
4823
            $i = 0;
4824
            foreach (array('key', 'value1', 'value2', 'value3') as $var) {
4825
                $$var = isset($match[++$i]) ? $match[$i] : '';
4826
            }
4827
            $value = stripslashes(substr($value1, 1, -1)) . stripslashes(substr($value2, 1, -1)) . $value3;
4828
4829
            // Parse array syntax.
4830
            $keys = preg_split('/\]?\[/', rtrim($key, ']'));
4831
            $last = array_pop($keys);
4832
            $parent = &$info;
4833
4834
            // Create nested arrays.
4835
            foreach ($keys as $key) {
4836
                if ($key == '') {
4837
                    $key = count($parent);
4838
                }
4839
                if (!isset($parent[$key]) || !is_array($parent[$key])) {
4840
                    $parent[$key] = array();
4841
                }
4842
                $parent = &$parent[$key];
4843
            }
4844
4845
            // Handle PHP constants.
4846
            if (defined($value)) {
4847
                $value = constant($value);
4848
            }
4849
4850
            // Insert actual value.
4851
            if ($last == '') {
4852
                $last = count($parent);
4853
            }
4854
            $parent[$last] = $value;
4855
        }
4856
    }
4857
    return $info;
4858
}
4859
4860
/**
4861
 * Gets Chamilo version from the configuration files
4862
 * @return string   A string of type "1.8.4", or an empty string if the version could not be found
4863
 */
4864
function api_get_version()
4865
{
4866
    return (string) api_get_configuration_value('system_version');
4867
}
4868
4869
/**
4870
 * Gets the software name (the name/brand of the Chamilo-based customized system)
4871
 * @return string
4872
 */
4873
function api_get_software_name() {
4874
    $name = api_get_configuration_value('software_name');
4875
    if (!empty($name)) {
4876
        return $name;
4877
    } else {
4878
        return 'Chamilo';
4879
    }
4880
}
4881
4882
/**
4883
 * Checks whether status given in parameter exists in the platform
4884
 * @param mixed the status (can be either int either string)
4885
 * @return boolean if the status exists, else returns false
4886
 */
4887
function api_status_exists($status_asked) {
4888
    global $_status_list;
4889
    return in_array($status_asked, $_status_list) ? true : isset($_status_list[$status_asked]);
4890
}
4891
4892
/**
4893
 * Checks whether status given in parameter exists in the platform. The function
4894
 * returns the status ID or false if it does not exist, but given the fact there
4895
 * is no "0" status, the return value can be checked against
4896
 * if(api_status_key()) to know if it exists.
4897
 * @param   mixed   The status (can be either int or string)
4898
 * @return  mixed   Status ID if exists, false otherwise
4899
 */
4900
function api_status_key($status) {
4901
    global $_status_list;
4902
    return isset($_status_list[$status]) ? $status : array_search($status, $_status_list);
4903
}
4904
4905
/**
4906
 * Gets the status langvars list
4907
 * @return string[] the list of status with their translations
4908
 */
4909
function api_get_status_langvars() {
4910
    return array(
4911
        COURSEMANAGER   => get_lang('Teacher', ''),
4912
        SESSIONADMIN    => get_lang('SessionsAdmin', ''),
4913
        DRH             => get_lang('Drh', ''),
4914
        STUDENT         => get_lang('Student', ''),
4915
        ANONYMOUS       => get_lang('Anonymous', ''),
4916
        STUDENT_BOSS    => get_lang('RoleStudentBoss', ''),
4917
        INVITEE         => get_lang('Invited'),
4918
    );
4919
}
4920
4921
/**
4922
* The function that retrieves all the possible settings for a certain config setting
4923
* @author Patrick Cool <[email protected]>, Ghent University
4924
*/
4925 View Code Duplication
function api_get_settings_options($var) {
4926
    $table_settings_options = Database :: get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
4927
    $var = Database::escape_string($var);
4928
    $sql = "SELECT * FROM $table_settings_options
4929
            WHERE variable = '$var'
4930
            ORDER BY id";
4931
    $result = Database::query($sql);
4932
    $settings_options_array = array();
4933
    while ($row = Database::fetch_array($result, 'ASSOC')) {
4934
        $settings_options_array[] = $row;
4935
    }
4936
    return $settings_options_array;
4937
}
4938
4939
/**
4940
 * @param array $params
4941
 */
4942
function api_set_setting_option($params) {
4943
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
4944 View Code Duplication
    if (empty($params['id'])) {
4945
        Database::insert($table, $params);
4946
    } else {
4947
        Database::update($table, $params, array('id = ? '=> $params['id']));
4948
    }
4949
}
4950
4951
/**
4952
 * @param array $params
4953
 */
4954
function api_set_setting_simple($params) {
4955
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
4956
    $url_id = api_get_current_access_url_id();
4957
4958 View Code Duplication
    if (empty($params['id'])) {
4959
        $params['access_url'] = $url_id;
4960
        Database::insert($table, $params);
4961
    } else {
4962
        Database::update($table, $params, array('id = ? '=> array($params['id'])));
4963
    }
4964
}
4965
4966
/**
4967
 * @param int $id
4968
 */
4969
function api_delete_setting_option($id) {
4970
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
4971
    if (!empty($id)) {
4972
        Database::delete($table, array('id = ? '=> $id));
4973
    }
4974
}
4975
4976
/**
4977
 * Sets a platform configuration setting to a given value
4978
 * @param string    The variable we want to update
4979
 * @param string    The value we want to record
4980
 * @param string    The sub-variable if any (in most cases, this will remain null)
4981
 * @param string    The category if any (in most cases, this will remain null)
4982
 * @param int       The access_url for which this parameter is valid
4983
 * @param string $cat
4984
 */
4985
function api_set_setting($var, $value, $subvar = null, $cat = null, $access_url = 1)
4986
{
4987
    if (empty($var)) {
4988
        return false;
4989
    }
4990
    $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
4991
    $var = Database::escape_string($var);
4992
    $value = Database::escape_string($value);
4993
    $access_url = (int)$access_url;
4994
    if (empty($access_url)) { $access_url = 1; }
4995
    $select = "SELECT id FROM $t_settings WHERE variable = '$var' ";
4996
    if (!empty($subvar)) {
4997
        $subvar = Database::escape_string($subvar);
4998
        $select .= " AND subkey = '$subvar'";
4999
    }
5000
    if (!empty($cat)) {
5001
        $cat = Database::escape_string($cat);
5002
        $select .= " AND category = '$cat'";
5003
    }
5004
    if ($access_url > 1) {
5005
        $select .= " AND access_url = $access_url";
5006
    } else {
5007
        $select .= " AND access_url = 1 ";
5008
    }
5009
    $res = Database::query($select);
5010
    if (Database::num_rows($res) > 0) {
5011
        // Found item for this access_url.
5012
        $row = Database::fetch_array($res);
5013
        $sql = "UPDATE $t_settings SET selected_value = '$value'
5014
                WHERE id = ".$row['id'];
5015
        Database::query($sql);
5016
    } else {
5017
        // Item not found for this access_url, we have to check if it exist with access_url = 1
5018
        $select = "SELECT * FROM $t_settings
5019
                   WHERE variable = '$var' AND access_url = 1 ";
5020
        // Just in case
5021
        if ($access_url == 1) {
5022
            if (!empty($subvar)) {
5023
                $select .= " AND subkey = '$subvar'";
5024
            }
5025
            if (!empty($cat)) {
5026
                $select .= " AND category = '$cat'";
5027
            }
5028
            $res = Database::query($select);
5029
            if (Database::num_rows($res) > 0) {
5030
                // We have a setting for access_url 1, but none for the current one, so create one.
5031
                $row = Database::fetch_array($res);
5032
                $insert = "INSERT INTO $t_settings (variable, subkey, type,category, selected_value, title, comment, scope, subkeytext, access_url)
5033
                        VALUES
5034
                        ('".$row['variable']."',".(!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL")."," .
5035
                        "'".$row['type']."','".$row['category']."'," .
5036
                        "'$value','".$row['title']."'," .
5037
                        "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".(!empty($row['scope']) ? "'".$row['scope']."'" : "NULL")."," .
5038
                        "".(!empty($row['subkeytext'])?"'".$row['subkeytext']."'":"NULL").",$access_url)";
5039
                Database::query($insert);
5040
            } 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...
5041
                // Such a setting does not exist.
5042
                //error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all', 0);
5043
            }
5044
        } else {
5045
            // Other access url.
5046
            if (!empty($subvar)) {
5047
                $select .= " AND subkey = '$subvar'";
5048
            }
5049
            if (!empty($cat)) {
5050
                $select .= " AND category = '$cat'";
5051
            }
5052
            $res = Database::query($select);
5053
5054
            if (Database::num_rows($res) > 0) {
5055
                // We have a setting for access_url 1, but none for the current one, so create one.
5056
                $row = Database::fetch_array($res);
5057
                if ($row['access_url_changeable'] == 1) {
5058
                    $insert = "INSERT INTO $t_settings (variable,subkey, type,category, selected_value,title, comment,scope, subkeytext,access_url, access_url_changeable) VALUES
5059
                            ('".$row['variable']."',".
5060
                            (!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL")."," .
5061
                            "'".$row['type']."','".$row['category']."'," .
5062
                            "'$value','".$row['title']."'," .
5063
                            "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".
5064
                            (!empty($row['scope']) ? "'".$row['scope']."'" : "NULL")."," .
5065
                            "".(!empty($row['subkeytext']) ? "'".$row['subkeytext']."'" : "NULL").",$access_url,".$row['access_url_changeable'].")";
5066
                    Database::query($insert);
5067
                }
5068
            } 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...
5069
                //error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all. The access_url is: '.$access_url.' ',0);
5070
            }
5071
        }
5072
    }
5073
}
5074
5075
/**
5076
 * Sets a whole category of settings to one specific value
5077
 * @param string    Category
5078
 * @param string    Value
5079
 * @param int       Access URL. Optional. Defaults to 1
5080
 * @param array     Optional array of filters on field type
5081
 * @param string $category
5082
 * @param string $value
5083
 */
5084
function api_set_settings_category($category, $value = null, $access_url = 1, $fieldtype = array())
5085
{
5086
    if (empty($category)) {
5087
        return false;
5088
    }
5089
    $category = Database::escape_string($category);
5090
    $t_s = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5091
    $access_url = (int) $access_url;
5092
    if (empty($access_url)) { $access_url = 1; }
5093
    if (isset($value)) {
5094
        $value = Database::escape_string($value);
5095
        $sql = "UPDATE $t_s SET selected_value = '$value'
5096
                WHERE category = '$category' AND access_url = $access_url";
5097 View Code Duplication
        if (is_array($fieldtype) && count($fieldtype)>0) {
5098
            $sql .= " AND ( ";
5099
            $i = 0;
5100
            foreach ($fieldtype as $type){
5101
                if ($i > 0) {
5102
                    $sql .= ' OR ';
5103
                }
5104
                $type = Database::escape_string($type);
5105
                $sql .= " type='".$type."' ";
5106
                $i++;
5107
            }
5108
            $sql .= ")";
5109
        }
5110
        $res = Database::query($sql);
5111
        return $res !== false;
5112
    } else {
5113
        $sql = "UPDATE $t_s SET selected_value = NULL
5114
                WHERE category = '$category' AND access_url = $access_url";
5115 View Code Duplication
        if (is_array($fieldtype) && count($fieldtype)>0) {
5116
            $sql .= " AND ( ";
5117
            $i = 0;
5118
            foreach ($fieldtype as $type){
5119
                if ($i > 0) {
5120
                    $sql .= ' OR ';
5121
                }
5122
                $type = Database::escape_string($type);
5123
                $sql .= " type='".$type."' ";
5124
                $i++;
5125
            }
5126
            $sql .= ")";
5127
        }
5128
        $res = Database::query($sql);
5129
        return $res !== false;
5130
    }
5131
}
5132
5133
/**
5134
 * Gets all available access urls in an array (as in the database)
5135
 * @return array    An array of database records
5136
 */
5137
function api_get_access_urls($from = 0, $to = 1000000, $order = 'url', $direction = 'ASC')
5138
{
5139
    $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5140
    $from = (int) $from;
5141
    $to = (int) $to;
5142
    $order = Database::escape_string($order, null, false);
5143
    $direction = Database::escape_string($direction, null, false);
5144
    $sql = "SELECT id, url, description, active, created_by, tms
5145
            FROM $table
5146
            ORDER BY $order $direction
5147
            LIMIT $to OFFSET $from";
5148
    $res = Database::query($sql);
5149
    return Database::store_result($res);
5150
}
5151
5152
/**
5153
 * Gets the access url info in an array
5154
 * @param int $id Id of the access url
5155
 * @param bool $returnDefault Set to false if you want the real URL if URL 1 is still 'http://localhost/'
5156
 * @return array All the info (url, description, active, created_by, tms)
5157
 * from the access_url table
5158
 * @author Julio Montoya
5159
 */
5160
function api_get_access_url($id, $returnDefault = true)
5161
{
5162
    $id = intval($id);
5163
    // Calling the Database:: library dont work this is handmade.
5164
    $table_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
5165
    $sql = "SELECT url, description, active, created_by, tms
5166
            FROM $table_access_url WHERE id = '$id' ";
5167
    $res = Database::query($sql);
5168
    $result = @Database::fetch_array($res);
5169
    // If the result url is 'http://localhost/' (the default) and the root_web
5170
    // (=current url) is different, and the $id is = 1 (which might mean
5171
    // api_get_current_access_url_id() returned 1 by default), then return the
5172
    // root_web setting instead of the current URL
5173
    // This is provided as an option to avoid breaking the storage of URL-specific
5174
    // homepages in home/localhost/
5175
    if ($id === 1 && $returnDefault === false) {
5176
        $currentUrl = api_get_current_access_url_id();
5177
        // only do this if we are on the main URL (=1), otherwise we could get
5178
        // information on another URL instead of the one asked as parameter
5179
        if ($currentUrl === 1) {
5180
            $rootWeb = api_get_path(WEB_PATH);
5181
            $default = 'http://localhost/';
5182
            if ($result['url'] === $default && $rootWeb != $default) {
5183
                $result['url'] = $rootWeb;
5184
            }
5185
        }
5186
    }
5187
5188
    return $result;
5189
}
5190
5191
/**
5192
 * Gets all the current settings for a specific access url
5193
 * @param string    The category, if any, that we want to get
5194
 * @param string    Whether we want a simple list (display a category) or
5195
 * a grouped list (group by variable as in settings.php default). Values: 'list' or 'group'
5196
 * @param int       Access URL's ID. Optional. Uses 1 by default, which is the unique URL
5197
 * @return array    Array of database results for the current settings of the current access URL
5198
 */
5199
function &api_get_settings($cat = null, $ordering = 'list', $access_url = 1, $url_changeable = 0)
5200
{
5201
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5202
    $access_url = (int) $access_url;
5203
    $where_condition = '';
5204
    if ($url_changeable == 1) {
5205
        $where_condition = " AND access_url_changeable= '1' ";
5206
    }
5207
    if (empty($access_url) || $access_url == -1) {
5208
        $access_url = 1;
5209
    }
5210
    $sql = "SELECT * FROM $table
5211
            WHERE access_url = $access_url  $where_condition ";
5212
5213
    if (!empty($cat)) {
5214
        $cat = Database::escape_string($cat);
5215
        $sql .= " AND category='$cat' ";
5216
    }
5217
    if ($ordering == 'group') {
5218
        $sql .= " ORDER BY id ASC";
5219
    } else {
5220
        $sql .= " ORDER BY 1,2 ASC";
5221
    }
5222
    $result = Database::query($sql);
5223
    $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...
5224
5225
    return $result;
5226
}
5227
5228
/**
5229
 * Sets a platform configuration setting to a given value
5230
 * @param string    The value we want to record
5231
 * @param string    The variable name we want to insert
5232
 * @param string    The subkey for the variable we want to insert
5233
 * @param string    The type for the variable we want to insert
5234
 * @param string    The category for the variable we want to insert
5235
 * @param string    The title
5236
 * @param string    The comment
5237
 * @param string    The scope
5238
 * @param string    The subkey text
5239
 * @param int       The access_url for which this parameter is valid
5240
 * @param int       The changeability of this setting for non-master urls
5241
 * @param string $val
5242
 * @param string $var
5243
 * @param string $sk
5244
 * @param string $c
5245
 * @return boolean  true on success, false on failure
5246
 */
5247
function api_add_setting(
5248
    $val,
5249
    $var,
5250
    $sk = null,
5251
    $type = 'textfield',
5252
    $c = null,
5253
    $title = '',
5254
    $com = '',
5255
    $sc = null,
5256
    $skt = null,
5257
    $a = 1,
5258
    $v = 0
5259
) {
5260
    if (empty($var) || !isset($val)) { return false; }
5261
    $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
5262
    $var = Database::escape_string($var);
5263
    $val = Database::escape_string($val);
5264
    $a = (int) $a;
5265
    if (empty($a)) { $a = 1; }
5266
    // Check if this variable doesn't exist already
5267
    $select = "SELECT id FROM $t_settings WHERE variable = '$var' ";
5268
    if (!empty($sk)) {
5269
        $sk = Database::escape_string($sk);
5270
        $select .= " AND subkey = '$sk'";
5271
    }
5272
    if ($a > 1) {
5273
        $select .= " AND access_url = $a";
5274
    } else {
5275
        $select .= " AND access_url = 1 ";
5276
    }
5277
    $res = Database::query($select);
5278
    if (Database::num_rows($res) > 0) { // Found item for this access_url.
5279
        $row = Database::fetch_array($res);
5280
        Database::update(
5281
            $t_settings,
5282
            array('selected_value' => $val),
5283
            array('id = ?' => array($row['id']))
5284
        );
5285
        return $row['id'];
5286
    }
5287
5288
    // Item not found for this access_url, we have to check if the whole thing is missing
5289
    // (in which case we ignore the insert) or if there *is* a record but just for access_url = 1
5290
    $insert = "INSERT INTO $t_settings " .
5291
                "(variable,selected_value," .
5292
                "type,category," .
5293
                "subkey,title," .
5294
                "comment,scope," .
5295
                "subkeytext,access_url,access_url_changeable)" .
5296
                " VALUES ('$var','$val',";
5297
    if (isset($type)) {
5298
        $type = Database::escape_string($type);
5299
        $insert .= "'$type',";
5300
    } else {
5301
        $insert .= "NULL,";
5302
    }
5303
    if (isset($c)) { // Category
5304
        $c = Database::escape_string($c);
5305
        $insert .= "'$c',";
5306
    } else {
5307
        $insert .= "NULL,";
5308
    }
5309
    if (isset($sk)) { // Subkey
5310
        $sk = Database::escape_string($sk);
5311
        $insert .= "'$sk',";
5312
    } else {
5313
        $insert .= "NULL,";
5314
    }
5315
    if (isset($title)) { // Title
5316
        $title = Database::escape_string($title);
5317
        $insert .= "'$title',";
5318
    } else {
5319
        $insert .= "NULL,";
5320
    }
5321
    if (isset($com)) { // Comment
5322
        $com = Database::escape_string($com);
5323
        $insert .= "'$com',";
5324
    } else {
5325
        $insert .= "NULL,";
5326
    }
5327
    if (isset($sc)) { // Scope
5328
        $sc = Database::escape_string($sc);
5329
        $insert .= "'$sc',";
5330
    } else {
5331
        $insert .= "NULL,";
5332
    }
5333
    if (isset($skt)) { // Subkey text
5334
        $skt = Database::escape_string($skt);
5335
        $insert .= "'$skt',";
5336
    } else {
5337
        $insert .= "NULL,";
5338
    }
5339
    $insert .= "$a,$v)";
5340
    $res = Database::query($insert);
5341
    return $res;
5342
}
5343
5344
/**
5345
 * Checks wether a user can or can't view the contents of a course.
5346
 *
5347
 * @param   int $userid     User id or NULL to get it from $_SESSION
5348
 * @param   int $cid        Course id to check whether the user is allowed.
5349
 * @return  bool
5350
 */
5351
function api_is_course_visible_for_user($userid = null, $cid = null) {
5352
    if ($userid === null) {
5353
        $userid = api_get_user_id();
5354
    }
5355
    if (empty($userid) || strval(intval($userid)) != $userid) {
5356
        if (api_is_anonymous()) {
5357
            $userid = api_get_anonymous_id();
5358
        } else {
5359
            return false;
5360
        }
5361
    }
5362
    $cid = Database::escape_string($cid);
5363
5364
    $courseInfo = api_get_course_info($cid);
5365
    $courseId = $courseInfo['real_id'];
5366
5367
    global $is_platformAdmin;
5368
5369
    $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
5370
    $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
5371
5372
    $sql = "SELECT
5373
                $course_table.category_code,
5374
                $course_table.visibility,
5375
                $course_table.code,
5376
                $course_cat_table.code
5377
            FROM $course_table
5378
            LEFT JOIN $course_cat_table
5379
                ON $course_table.category_code = $course_cat_table.code
5380
            WHERE
5381
                $course_table.code = '$cid'
5382
            LIMIT 1";
5383
5384
    $result = Database::query($sql);
5385
5386
    if (Database::num_rows($result) > 0) {
5387
        $visibility = Database::fetch_array($result);
5388
        $visibility = $visibility['visibility'];
5389
    } else {
5390
        $visibility = 0;
5391
    }
5392
    // Shortcut permissions in case the visibility is "open to the world".
5393
    if ($visibility === COURSE_VISIBILITY_OPEN_WORLD) {
5394
        return true;
5395
    }
5396
5397
    $tbl_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
5398
5399
    $sql = "SELECT
5400
                is_tutor, status
5401
            FROM $tbl_course_user
5402
            WHERE
5403
                user_id  = '$userid' AND
5404
                relation_type <> '".COURSE_RELATION_TYPE_RRHH."' AND
5405
                c_id = $courseId
5406
            LIMIT 1";
5407
5408
    $result = Database::query($sql);
5409
5410 View Code Duplication
    if (Database::num_rows($result) > 0) {
5411
        // This user has got a recorded state for this course.
5412
        $cuData = Database::fetch_array($result);
5413
        $is_courseMember = true;
5414
        $is_courseTutor = ($cuData['is_tutor'] == 1);
5415
        $is_courseAdmin = ($cuData['status'] == 1);
5416
    }
5417
5418
    if (!$is_courseAdmin) {
5419
        // This user has no status related to this course.
5420
        // Is it the session coach or the session admin?
5421
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
5422
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
5423
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
5424
5425
        $sql = "SELECT
5426
                    session.id_coach, session_admin_id, session.id
5427
                FROM
5428
                    $tbl_session as session
5429
                INNER JOIN $tbl_session_course
5430
                    ON session_rel_course.session_id = session.id
5431
                    AND session_rel_course.c_id = '$courseId'
5432
                LIMIT 1";
5433
5434
        $result = Database::query($sql);
5435
        $row = Database::store_result($result);
5436
5437
        if ($row[0]['id_coach'] == $userid) {
5438
            $is_courseMember = true;
5439
            $is_courseTutor = true;
5440
            $is_courseAdmin = false;
5441
            $is_courseCoach = true;
5442
            $is_sessionAdmin = false;
5443
        }
5444
        elseif ($row[0]['session_admin_id'] == $userid) {
5445
            $is_courseMember = false;
5446
            $is_courseTutor = false;
5447
            $is_courseAdmin = false;
5448
            $is_courseCoach = false;
5449
            $is_sessionAdmin = true;
5450
        } else {
5451
            // Check if the current user is the course coach.
5452
            $sql = "SELECT 1
5453
                    FROM $tbl_session_course
5454
                    WHERE session_rel_course.c_id = '$courseId'
5455
                    AND session_rel_course.id_coach = '$userid'
5456
                    LIMIT 1";
5457
5458
            $result = Database::query($sql);
5459
5460
            //if ($row = Database::fetch_array($result)) {
5461
            if (Database::num_rows($result) > 0 ) {
5462
                $is_courseMember = true;
5463
                $is_courseTutor = true;
5464
                $is_courseCoach = true;
5465
                $is_sessionAdmin = false;
5466
5467
                $tbl_user = Database :: get_main_table(TABLE_MAIN_USER);
5468
5469
                $sql = "SELECT status FROM $tbl_user
5470
                        WHERE user_id = $userid
5471
                        LIMIT 1";
5472
5473
                $result = Database::query($sql);
5474
5475
                if (Database::result($result, 0, 0) == 1) {
5476
                    $is_courseAdmin = true;
5477
                } else {
5478
                    $is_courseAdmin = false;
5479
                }
5480
            } else {
5481
                // Check if the user is a student is this session.
5482
                $sql = "SELECT  id
5483
                        FROM $tbl_session_course_user
5484
                        WHERE
5485
                            user_id  = '$userid' AND
5486
                            c_id = '$courseId'
5487
                        LIMIT 1";
5488
5489
                if (Database::num_rows($result) > 0) {
5490
                    // This user haa got a recorded state for this course.
5491
                    while ($row = Database::fetch_array($result)) {
5492
                        $is_courseMember = true;
5493
                        $is_courseTutor = false;
5494
                        $is_courseAdmin = false;
5495
                        $is_sessionAdmin = false;
5496
                    }
5497
                }
5498
            }
5499
        }
5500
    }
5501
5502
    switch ($visibility) {
5503
        case COURSE_VISIBILITY_OPEN_WORLD:
5504
            return true;
5505
        case COURSE_VISIBILITY_OPEN_PLATFORM:
5506
            return isset($userid);
5507
        case COURSE_VISIBILITY_REGISTERED:
5508
        case COURSE_VISIBILITY_CLOSED:
5509
            return $is_platformAdmin || $is_courseMember || $is_courseAdmin;
5510
        case COURSE_VISIBILITY_HIDDEN:
5511
            return $is_platformAdmin;
5512
    }
5513
5514
    return false;
5515
}
5516
5517
/**
5518
 * Returns whether an element (forum, message, survey ...) belongs to a session or not
5519
 * @param String the tool of the element
5520
 * @param int the element id in database
5521
 * @param int the session_id to compare with element session id
5522
 * @param string $tool
5523
 * @return boolean true if the element is in the session, false else
5524
 */
5525
function api_is_element_in_the_session($tool, $element_id, $session_id = null) {
5526
    if (is_null($session_id)) {
5527
        $session_id = api_get_session_id();
5528
    }
5529
5530
    // Get information to build query depending of the tool.
5531
    switch ($tool) {
5532
        case TOOL_SURVEY :
5533
            $table_tool = Database::get_course_table(TABLE_SURVEY);
5534
            $key_field = 'survey_id';
5535
            break;
5536
        case TOOL_ANNOUNCEMENT :
5537
            $table_tool = Database::get_course_table(TABLE_ANNOUNCEMENT);
5538
            $key_field = 'id';
5539
            break;
5540
        case TOOL_AGENDA :
5541
            $table_tool = Database::get_course_table(TABLE_AGENDA);
5542
            $key_field = 'id';
5543
            break;
5544
        case TOOL_GROUP :
5545
            $table_tool = Database::get_course_table(TABLE_GROUP);
5546
            $key_field = 'id';
5547
            break;
5548
        default:
5549
            return false;
5550
    }
5551
    $course_id = api_get_course_int_id();
5552
5553
    $sql = "SELECT session_id FROM $table_tool 
5554
            WHERE c_id = $course_id AND $key_field =  ".intval($element_id);
5555
    $rs = Database::query($sql);
5556
    if ($element_session_id = Database::result($rs, 0, 0)) {
5557
        if ($element_session_id == intval($session_id)) {
5558
            // The element belongs to the session.
5559
            return true;
5560
        }
5561
    }
5562
    return false;
5563
}
5564
5565
/**
5566
 * Replaces "forbidden" characters in a filename string.
5567
 *
5568
 * @param string $filename
5569
 * @param bool $treat_spaces_as_hyphens
5570
 *
5571
 * @return string
5572
 */
5573
function api_replace_dangerous_char($filename, $treat_spaces_as_hyphens = true)
5574
{
5575
    return URLify::filter($filename, 250, '', true, true, false, false, $treat_spaces_as_hyphens);
5576
}
5577
5578
/**
5579
 * Fixes the $_SERVER['REQUEST_URI'] that is empty in IIS6.
5580
 * @author Ivan Tcholakov, 28-JUN-2006.
5581
 */
5582
function api_request_uri() {
5583
    if (!empty($_SERVER['REQUEST_URI'])) {
5584
        return $_SERVER['REQUEST_URI'];
5585
    }
5586
    $uri = $_SERVER['SCRIPT_NAME'];
5587
    if (!empty($_SERVER['QUERY_STRING'])) {
5588
        $uri .= '?'.$_SERVER['QUERY_STRING'];
5589
    }
5590
    $_SERVER['REQUEST_URI'] = $uri;
5591
    return $uri;
5592
}
5593
5594
5595
/** Gets the current access_url id of the Chamilo Platform
5596
 * @author Julio Montoya <[email protected]>
5597
 * @return int access_url_id of the current Chamilo Installation
5598
 */
5599 View Code Duplication
function api_get_current_access_url_id() {
5600
    $access_url_table = Database :: get_main_table(TABLE_MAIN_ACCESS_URL);
5601
    $path = Database::escape_string(api_get_path(WEB_PATH));
5602
    $sql = "SELECT id FROM $access_url_table WHERE url = '".$path."'";
5603
    $result = Database::query($sql);
5604
    if (Database::num_rows($result) > 0) {
5605
        $access_url_id = Database::result($result, 0, 0);
5606
        return $access_url_id;
5607
    }
5608
    //if the url in WEB_PATH was not found, it can only mean that there is
5609
    // either a configuration problem or the first URL has not been defined yet
5610
    // (by default it is http://localhost/). Thus the more sensible thing we can
5611
    // do is return 1 (the main URL) as the user cannot hack this value anyway
5612
    return 1;
5613
}
5614
5615
/**
5616
 * Gets the registered urls from a given user id
5617
 * @author Julio Montoya <[email protected]>
5618
 * @return int user id
5619
 */
5620 View Code Duplication
function api_get_access_url_from_user($user_id) {
5621
    $user_id = intval($user_id);
5622
    $table_url_rel_user = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
5623
    $table_url          = Database :: get_main_table(TABLE_MAIN_ACCESS_URL);
5624
    $sql = "SELECT access_url_id
5625
            FROM $table_url_rel_user url_rel_user
5626
            INNER JOIN $table_url u
5627
            ON (url_rel_user.access_url_id = u.id)
5628
            WHERE user_id = ".intval($user_id);
5629
    $result = Database::query($sql);
5630
    $url_list = array();
5631
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5632
        $url_list[] = $row['access_url_id'];
5633
    }
5634
    return $url_list;
5635
}
5636
5637
/**
5638
 * Gets the status of a user in a course
5639
 * @param int       $user_id
5640
 * @param int    $courseId
5641
 * @return int      user status
5642
 */
5643
function api_get_status_of_user_in_course($user_id, $courseId)
5644
{
5645
    $tbl_rel_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
5646
    if (!empty($user_id) && !empty($courseId)) {
5647
        $user_id = intval($user_id);
5648
        $courseId = intval($courseId);
5649
        $sql = 'SELECT status
5650
                FROM '.$tbl_rel_course_user.'
5651
                WHERE user_id='.$user_id.' AND c_id = '.$courseId;
5652
        $result = Database::query($sql);
5653
        $row_status = Database::fetch_array($result, 'ASSOC');
5654
        return $row_status['status'];
5655
    } else {
5656
        return 0;
5657
    }
5658
}
5659
5660
/**
5661
 * Checks whether the curent user is in a group or not.
5662
 *
5663
 * @param string        The group id - optional (takes it from session if not given)
5664
 * @param string        The course code - optional (no additional check by course if course code is not given)
5665
 * @return boolean
5666
 * @author Ivan Tcholakov
5667
 */
5668
function api_is_in_group($groupIdParam = null, $courseCodeParam = null)
5669
{
5670
    if (!empty($courseCodeParam)) {
5671
        $courseCode = api_get_course_id();
5672
        if (!empty($courseCode)) {
5673
            if ($courseCodeParam != $courseCode) {
5674
                return false;
5675
            }
5676
        } else {
5677
            return false;
5678
        }
5679
    }
5680
5681
    $groupId = api_get_group_id();
5682
5683
    if (isset($groupId) && $groupId != '') {
5684
        if (!empty($groupIdParam)) {
5685
            return $groupIdParam == $groupId;
5686
        } else {
5687
            return true;
5688
        }
5689
    }
5690
5691
    return false;
5692
}
5693
5694
/**
5695
 * Checks whether a secret key is valid
5696
 * @param string $original_key_secret  - secret key from (webservice) client
5697
 * @param string $security_key - security key from Chamilo
5698
 * @return boolean - true if secret key is valid, false otherwise
5699
 */
5700
function api_is_valid_secret_key($original_key_secret, $security_key) {
5701
    return $original_key_secret == sha1($security_key);
5702
}
5703
5704
/**
5705
 * Checks whether a user is into course
5706
 * @param int $course_id - the course id
5707
 * @param int $user_id - the user id
5708
 */
5709
function api_is_user_of_course($course_id, $user_id) {
5710
    $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5711
    $sql = 'SELECT user_id FROM '.$tbl_course_rel_user.'
5712
            WHERE
5713
                c_id ="'.intval($course_id).'" AND
5714
                user_id = "'.intval($user_id).'" AND
5715
                relation_type <> '.COURSE_RELATION_TYPE_RRHH.' ';
5716
    $result = Database::query($sql);
5717
    return Database::num_rows($result) == 1;
5718
}
5719
5720
/**
5721
 * Checks whether the server's operating system is Windows (TM).
5722
 * @return boolean - true if the operating system is Windows, false otherwise
5723
 */
5724
function api_is_windows_os() {
5725
    if (function_exists('php_uname')) {
5726
        // php_uname() exists as of PHP 4.0.2, according to the documentation.
5727
        // We expect that this function will always work for Chamilo 1.8.x.
5728
        $os = php_uname();
5729
    }
5730
    // The following methods are not needed, but let them stay, just in case.
5731
    elseif (isset($_ENV['OS'])) {
5732
        // Sometimes $_ENV['OS'] may not be present (bugs?)
5733
        $os = $_ENV['OS'];
5734
    }
5735
    elseif (defined('PHP_OS')) {
5736
        // PHP_OS means on which OS PHP was compiled, this is why
5737
        // using PHP_OS is the last choice for detection.
5738
        $os = PHP_OS;
5739
    } else {
5740
        return false;
5741
    }
5742
    return strtolower(substr((string)$os, 0, 3 )) == 'win';
5743
}
5744
5745
/**
5746
 * This function informs whether the sent request is XMLHttpRequest
5747
 */
5748
function api_is_xml_http_request() {
5749
    return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
5750
}
5751
5752
/**
5753
 * This wrapper function has been implemented for avoiding some known problems about the function getimagesize().
5754
 * @link http://php.net/manual/en/function.getimagesize.php
5755
 * @link http://www.dokeos.com/forum/viewtopic.php?t=12345
5756
 * @link http://www.dokeos.com/forum/viewtopic.php?t=16355
5757
 * @return integer
5758
 */
5759
function api_getimagesize($path) {
5760
    $image = new Image($path);
5761
    return $image->get_image_size();
5762
}
5763
5764
/**
5765
 * This function resizes an image, with preserving its proportions (or aspect ratio).
5766
 * @author Ivan Tcholakov, MAY-2009.
5767
 * @param int $image            System path or URL of the image
5768
 * @param int $target_width     Targeted width
5769
 * @param int $target_height    Targeted height
5770
 * @return array                Calculated new width and height
5771
 */
5772
function api_resize_image($image, $target_width, $target_height) {
5773
    $image_properties = api_getimagesize($image);
5774
    return api_calculate_image_size($image_properties['width'], $image_properties['height'], $target_width, $target_height);
5775
}
5776
5777
/**
5778
 * This function calculates new image size, with preserving image's proportions (or aspect ratio).
5779
 * @author Ivan Tcholakov, MAY-2009.
5780
 * @author The initial idea has been taken from code by Patrick Cool, MAY-2004.
5781
 * @param int $image_width      Initial width
5782
 * @param int $image_height     Initial height
5783
 * @param int $target_width     Targeted width
5784
 * @param int $target_height    Targeted height
5785
 * @return array                Calculated new width and height
5786
 */
5787
function api_calculate_image_size($image_width, $image_height, $target_width, $target_height) {
5788
    // Only maths is here.
5789
    $result = array('width' => $image_width, 'height' => $image_height);
5790
    if ($image_width <= 0 || $image_height <= 0) {
5791
        return $result;
5792
    }
5793
    $resize_factor_width = $target_width / $image_width;
5794
    $resize_factor_height = $target_height / $image_height;
5795
    $delta_width = $target_width - $image_width * $resize_factor_height;
5796
    $delta_height = $target_height - $image_height * $resize_factor_width;
5797
    if ($delta_width > $delta_height) {
5798
        $result['width'] = ceil($image_width * $resize_factor_height);
5799
        $result['height'] = ceil($image_height * $resize_factor_height);
5800
    }
5801
    elseif ($delta_width < $delta_height) {
5802
        $result['width'] = ceil($image_width * $resize_factor_width);
5803
        $result['height'] = ceil($image_height * $resize_factor_width);
5804
    }
5805
    else {
5806
        $result['width'] = ceil($target_width);
5807
        $result['height'] = ceil($target_height);
5808
    }
5809
    return $result;
5810
}
5811
5812
/**
5813
 * Returns a list of Chamilo's tools or
5814
 * checks whether a given identificator is a valid Chamilo's tool.
5815
 * @author Isaac flores paz
5816
 * @param string The tool name to filter
5817
 * @return mixed Filtered string or array
5818
 */
5819
function api_get_tools_lists($my_tool = null) {
5820
    $tools_list = array(
5821
        TOOL_DOCUMENT,
5822
        TOOL_THUMBNAIL,
5823
        TOOL_HOTPOTATOES,
5824
        TOOL_CALENDAR_EVENT,
5825
        TOOL_LINK,
5826
        TOOL_COURSE_DESCRIPTION,
5827
        TOOL_SEARCH,
5828
        TOOL_LEARNPATH,
5829
        TOOL_ANNOUNCEMENT,
5830
        TOOL_FORUM,
5831
        TOOL_THREAD,
5832
        TOOL_POST,
5833
        TOOL_DROPBOX,
5834
        TOOL_QUIZ,
5835
        TOOL_USER,
5836
        TOOL_GROUP,
5837
        TOOL_BLOGS,
5838
        TOOL_CHAT,
5839
        TOOL_STUDENTPUBLICATION,
5840
        TOOL_TRACKING,
5841
        TOOL_HOMEPAGE_LINK,
5842
        TOOL_COURSE_SETTING,
5843
        TOOL_BACKUP,
5844
        TOOL_COPY_COURSE_CONTENT,
5845
        TOOL_RECYCLE_COURSE,
5846
        TOOL_COURSE_HOMEPAGE,
5847
        TOOL_COURSE_RIGHTS_OVERVIEW,
5848
        TOOL_UPLOAD,
5849
        TOOL_COURSE_MAINTENANCE,
5850
        TOOL_SURVEY,
5851
        TOOL_WIKI,
5852
        TOOL_GLOSSARY,
5853
        TOOL_GRADEBOOK,
5854
        TOOL_NOTEBOOK,
5855
        TOOL_ATTENDANCE,
5856
        TOOL_COURSE_PROGRESS,
5857
    );
5858
    if (empty($my_tool)) {
5859
        return $tools_list;
5860
    }
5861
    return in_array($my_tool, $tools_list) ? $my_tool : '';
5862
}
5863
5864
/**
5865
 * Checks whether we already approved the last version term and condition
5866
 * @param int user id
5867
 * @return bool true if we pass false otherwise
5868
 */
5869
function api_check_term_condition($user_id)
5870
{
5871
    if (api_get_setting('allow_terms_conditions') == 'true') {
5872
        //check if exists terms and conditions
5873
        if (LegalManager::count() == 0) {
5874
5875
            return true;
5876
        }
5877
5878
        $extraFieldValue = new ExtraFieldValue('user');
5879
        $data = $extraFieldValue->get_values_by_handler_and_field_variable(
5880
            $user_id,
5881
            'legal_accept'
5882
        );
5883
5884
        if (!empty($data) && isset($data['value'])) {
5885
            $rowv = $data['value'];
5886
            $user_conditions = explode(':', $rowv);
5887
            $version = $user_conditions[0];
5888
            $lang_id = $user_conditions[1];
5889
            $real_version = LegalManager::get_last_version($lang_id);
5890
5891
            return $version >= $real_version;
5892
        }
5893
        return false;
5894
    }
5895
    return false;
5896
}
5897
5898
/**
5899
 * Gets all information of a tool into course
5900
 * @param int The tool id
5901
 * @return array
5902
 */
5903
function api_get_tool_information($tool_id) {
5904
    $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
5905
    $course_id = api_get_course_int_id();
5906
    $sql = "SELECT * FROM $t_tool WHERE c_id = $course_id AND id = ".intval($tool_id);
5907
    $rs  = Database::query($sql);
5908
    return Database::fetch_array($rs);
5909
}
5910
5911
/**
5912
 * Gets all information of a tool into course
5913
 * @param int The tool id
5914
 * @return array
5915
 */
5916 View Code Duplication
function api_get_tool_information_by_name($name) {
5917
    $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
5918
    $course_id = api_get_course_int_id();
5919
    $sql = "SELECT * FROM $t_tool
5920
            WHERE c_id = $course_id  AND name = '".Database::escape_string($name)."' ";
5921
    $rs  = Database::query($sql);
5922
    return Database::fetch_array($rs, 'ASSOC');
5923
}
5924
5925
/**
5926
 * Function used to protect a "global" admin script.
5927
 * The function blocks access when the user has no global platform admin rights.
5928
 * Global admins are the admins that are registered in the main.admin table
5929
 * AND the users who have access to the "principal" portal.
5930
 * That means that there is a record in the main.access_url_rel_user table
5931
 * with his user id and the access_url_id=1
5932
 *
5933
 * @author Julio Montoya
5934
 * @param integer $user_id
5935
 */
5936
function api_is_global_platform_admin($user_id = null)
5937
{
5938
    $user_id = intval($user_id);
5939
    if (empty($user_id)) {
5940
        $user_id = api_get_user_id();
5941
    }
5942
    if (api_is_platform_admin_by_id($user_id)) {
5943
        $urlList = api_get_access_url_from_user($user_id);
5944
        // The admin is registered in the first "main" site with access_url_id = 1
5945
        if (in_array(1, $urlList)) {
5946
            return true;
5947
        } else {
5948
            return false;
5949
        }
5950
    }
5951
    return false;
5952
}
5953
5954
/**
5955
 * @param int $admin_id_to_check
5956
 * @param int  $my_user_id
5957
 * @param bool $allow_session_admin
5958
 * @return bool
5959
 */
5960
function api_global_admin_can_edit_admin($admin_id_to_check, $my_user_id = null, $allow_session_admin = false)
5961
{
5962
    if (empty($my_user_id)) {
5963
        $my_user_id = api_get_user_id();
5964
    }
5965
5966
    $iam_a_global_admin = api_is_global_platform_admin($my_user_id);
5967
    $user_is_global_admin = api_is_global_platform_admin($admin_id_to_check);
5968
5969
    if ($iam_a_global_admin) {
5970
        // Global admin can edit everything
5971
        return true;
5972
    } else {
5973
        // If i'm a simple admin
5974
        $is_platform_admin = api_is_platform_admin_by_id($my_user_id);
5975
5976
        if ($allow_session_admin) {
5977
            $is_platform_admin = api_is_platform_admin_by_id($my_user_id) || (api_get_user_status($my_user_id) == SESSIONADMIN);
5978
        }
5979
5980
        if ($is_platform_admin) {
5981
            if ($user_is_global_admin) {
5982
                return false;
5983
            } else {
5984
                return true;
5985
            }
5986
        } else {
5987
            return false;
5988
        }
5989
    }
5990
}
5991
5992
/**
5993
 * @param int $admin_id_to_check
5994
 * @param int  $my_user_id
5995
 * @param bool $allow_session_admin
5996
 * @return boolean|null
5997
 */
5998
function api_protect_super_admin($admin_id_to_check, $my_user_id = null, $allow_session_admin = false)
5999
{
6000
    if (api_global_admin_can_edit_admin($admin_id_to_check, $my_user_id, $allow_session_admin)) {
6001
        return true;
6002
    } else {
6003
        api_not_allowed();
6004
    }
6005
}
6006
6007
/**
6008
 * Function used to protect a global admin script.
6009
 * The function blocks access when the user has no global platform admin rights.
6010
 * See also the api_is_global_platform_admin() function wich defines who's a "global" admin
6011
 *
6012
 * @author Julio Montoya
6013
 */
6014
function api_protect_global_admin_script() {
6015
    if (!api_is_global_platform_admin()) {
6016
        api_not_allowed();
6017
        return false;
6018
    }
6019
    return true;
6020
}
6021
6022
/**
6023
 * Get active template
6024
 * @param string    theme type (optional: default)
6025
 * @param string    path absolute(abs) or relative(rel) (optional:rel)
6026
 * @return string   actived template path
6027
 */
6028
function api_get_template($path_type = 'rel') {
6029
    $path_types = array('rel', 'abs');
6030
    $template_path = '';
6031
    if (in_array($path_type, $path_types)) {
6032
        if ($path_type == 'rel') {
6033
            $template_path = api_get_path(SYS_TEMPLATE_PATH);
6034
        } else {
6035
            $template_path = api_get_path(WEB_TEMPLATE_PATH);
6036
        }
6037
    }
6038
    $actived_theme = 'default';
6039
    /*if (api_get_setting('active_template')) {
6040
        $actived_theme = api_get_setting('active_template');
6041
    }*/
6042
    $actived_theme_path = $template_path.$actived_theme.DIRECTORY_SEPARATOR;
6043
    return $actived_theme_path;
6044
}
6045
6046
/**
6047
 * Check browser support for type files
6048
 * This function check if the users browser support a file format or
6049
 * return the current browser and major ver when $format=check_browser
6050
 * @param string $format
6051
 *
6052
 * @return bool or return text array if $format=check_browser
6053
 * @author Juan Carlos Raña Trabado
6054
 */
6055
function api_browser_support($format = '')
6056
{
6057
    $browser = new Browser();
6058
    $current_browser = $browser->getBrowser();
6059
    $a_versiontemp = explode('.', $browser->getVersion());
6060
    $current_majorver = $a_versiontemp[0];
6061
6062
    // Native svg support
6063
    if ($format == 'svg') {
6064
        if (($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6065
            ($current_browser == 'Firefox' && $current_majorver > 1) ||
6066
            ($current_browser == 'Safari' && $current_majorver >= 4) ||
6067
            ($current_browser == 'Chrome' && $current_majorver >= 1) ||
6068
            ($current_browser == 'Opera' && $current_majorver >= 9)
6069
        ) {
6070
            return true;
6071
        } else {
6072
            return false;
6073
        }
6074
    } elseif ($format == 'pdf') {
6075
        //native pdf support
6076
        if ($current_browser == 'Chrome' && $current_majorver >= 6) {
6077
            return true;
6078
        } else {
6079
            return false;
6080
        }
6081
    } elseif ($format == 'tif' || $format == 'tiff') {
6082
        //native tif support
6083
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6084
            return true;
6085
        } else {
6086
            return false;
6087
        }
6088 View Code Duplication
    } elseif ($format == 'ogg' || $format == 'ogx' || $format == 'ogv' || $format == 'oga') {
6089
        //native ogg, ogv,oga support
6090
        if (($current_browser == 'Firefox' && $current_majorver >= 3) ||
6091
            ($current_browser == 'Chrome' && $current_majorver >= 3) ||
6092
            ($current_browser == 'Opera' && $current_majorver >= 9)) {
6093
            return true;
6094
        } else {
6095
            return false;
6096
        }
6097
    } elseif ($format == 'mpg' || $format == 'mpeg') {
6098
        //native mpg support
6099
        if (($current_browser == 'Safari' && $current_majorver >= 5)) {
6100
            return true;
6101
        } else {
6102
            return false;
6103
        }
6104
    } elseif ($format == 'mp4') {
6105
        //native mp4 support (TODO: Android, iPhone)
6106
        if ($current_browser == 'Android' || $current_browser == 'iPhone') {
6107
            return true;
6108
        } else {
6109
            return false;
6110
        }
6111
    } elseif ($format == 'mov') {
6112
        //native mov support( TODO:check iPhone)
6113
        if ($current_browser == 'Safari' && $current_majorver >= 5 || $current_browser == 'iPhone') {
6114
            return true;
6115
        } else {
6116
            return false;
6117
        }
6118
    } elseif ($format == 'avi') {
6119
        //native avi support
6120
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6121
            return true;
6122
        } else {
6123
            return false;
6124
        }
6125
    } elseif ($format == 'wmv') {
6126
        //native wmv support
6127
        if ($current_browser == 'Firefox' && $current_majorver >= 4) {
6128
            return true;
6129
        } else {
6130
            return false;
6131
        }
6132 View Code Duplication
    } elseif ($format == 'webm') {
6133
        //native webm support (TODO:check IE9, Chrome9, Android)
6134
        if (($current_browser == 'Firefox' && $current_majorver >= 4) ||
6135
            ($current_browser == 'Opera' && $current_majorver >= 9) ||
6136
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6137
            ($current_browser == 'Chrome' && $current_majorver >= 9) ||
6138
            $current_browser == 'Android'
6139
        ) {
6140
            return true;
6141
        } else {
6142
            return false;
6143
        }
6144
    } elseif ($format == 'wav') {
6145
        //native wav support (only some codecs !)
6146
        if (($current_browser == 'Firefox' && $current_majorver >= 4) ||
6147
            ($current_browser == 'Safari' && $current_majorver >= 5) ||
6148
            ($current_browser == 'Opera' && $current_majorver >= 9) ||
6149
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6150
            ($current_browser == 'Chrome' && $current_majorver > 9) ||
6151
            $current_browser == 'Android' ||
6152
            $current_browser == 'iPhone'
6153
        ) {
6154
            return true;
6155
        } else {
6156
            return false;
6157
        }
6158
    } elseif ($format == 'mid' || $format == 'kar') {
6159
        //native midi support (TODO:check Android)
6160
        if ($current_browser == 'Opera' && $current_majorver >= 9 || $current_browser == 'Android') {
6161
            return true;
6162
        } else {
6163
            return false;
6164
        }
6165
    } elseif ($format == 'wma') {
6166
        //native wma support
6167
        if ($current_browser == 'Firefox' && $current_majorver >= 4) {
6168
            return true;
6169
        } else {
6170
            return false;
6171
        }
6172
    } elseif ($format == 'au') {
6173
        //native au support
6174
        if ($current_browser == 'Safari' && $current_majorver >= 5) {
6175
            return true;
6176
        } else {
6177
            return false;
6178
        }
6179 View Code Duplication
    } elseif ($format == 'mp3') {
6180
        //native mp3 support (TODO:check Android, iPhone)
6181
        if (($current_browser == 'Safari' && $current_majorver >= 5) ||
6182
            ($current_browser == 'Chrome' && $current_majorver >= 6) ||
6183
            ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
6184
            $current_browser == 'Android' ||
6185
            $current_browser == 'iPhone' ||
6186
            $current_browser == 'Firefox'
6187
        ) {
6188
            return true;
6189
        } else {
6190
            return false;
6191
        }
6192
    } elseif ($format == "check_browser") {
6193
        $array_check_browser = array($current_browser, $current_majorver);
6194
        return $array_check_browser;
6195
    } else {
6196
        return false;
6197
    }
6198
}
6199
6200
/**
6201
 * This function checks if exist path and file browscap.ini
6202
 * In order for this to work, your browscap configuration setting in php.ini
6203
 * must point to the correct location of the browscap.ini file on your system
6204
 * http://php.net/manual/en/function.get-browser.php
6205
 *
6206
 * @return bool
6207
 *
6208
 * @author Juan Carlos Raña Trabado
6209
 */
6210
function api_check_browscap() {
6211
    $setting = ini_get('browscap');
6212
    if ($setting) {
6213
        $browser = get_browser($_SERVER['HTTP_USER_AGENT'], true);
6214
        if (strpos($setting, 'browscap.ini') && !empty($browser)) {
6215
            return true;
6216
        }
6217
    }
6218
    return false;
6219
}
6220
6221
/**
6222
 * Returns the <script> HTML tag
6223
 * @param string $file
6224
 * @param bool $getURL
6225
 * @return string
6226
 */
6227 View Code Duplication
function api_get_js($file, $getURL = false)
6228
{
6229
    $url = Container::getAsset()->getUrl($file);
6230
6231
    if ($getURL) {
6232
        return $url;
6233
    }
6234
6235
    return '<script type="text/javascript" src="'.$url.'"></script>'."\n";
6236
}
6237
6238
/**
6239
 * Returns the <script> HTML tag
6240
 *
6241
 * @param string $file
6242
 * @param bool $getURL only returns the URL without the <script> tag
6243
 * @return string
6244
 */
6245 View Code Duplication
function api_get_asset($file, $getURL = false)
6246
{
6247
    $url = Container::getAsset()->getUrl("assets/".$file);
6248
6249
    if ($getURL) {
6250
        return $url;
6251
    }
6252
6253
    return '<script type="text/javascript" src="'.$url.'"></script>'."\n";
6254
}
6255
6256
/**
6257
 * Returns the <link> HTML tag
6258
 *
6259
 * @param string $file
6260
 * @param string $media
6261
 *
6262
 * @return string
6263
 */
6264
function api_get_css($file, $media = 'screen')
6265
{
6266
    $url = Container::getAsset()->getUrl($file);
6267
6268
    return '<link href="'.$url.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
6269
}
6270
6271
/**
6272
 *
6273
 * Returns the <link> HTML tag
6274
 *
6275
 * @param $file
6276
 * @param string $media
6277
 * @return string
6278
 */
6279
function api_get_css_asset($file, $media = 'screen')
6280
{
6281
    $url = Container::getAsset()->getUrl("assets/".$file);
6282
    return '<link href="'.$url.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
6283
}
6284
6285
/**
6286
 * Get jsPlumb lib
6287
 * @return string
6288
 */
6289
function api_get_js_plumb()
6290
{
6291
    return api_get_asset('jsPlumb/build/1.3.7/js/jquery.jsPlumb-1.3.7-all.js');
6292
}
6293
6294
/**
6295
 * Return epiclock js and css
6296
 * @return string
6297
 */
6298
function api_get_js_epiclock()
6299
{
6300
    $html = api_get_css('bundles/chamilocore/js/epiclock/stylesheet/jquery.epiclock.css');
6301
    $html .= api_get_css('bundles/chamilocore/js/epiclock/renderers/minute/epiclock.minute.css');
6302
    $html .= api_get_js('bundles/chamilocore/js/epiclock/javascript/jquery.dateformat.min.js');
6303
    $html .= api_get_js('bundles/chamilocore/js/epiclock/javascript/jquery.epiclock.min.js');
6304
    $html .= api_get_js('bundles/chamilocore/js/epiclock/renderers/minute/epiclock.minute.js');
6305
6306
    return $html;
6307
}
6308
6309
/**
6310
 * Returns the js header to include the jquery library
6311
 */
6312
function api_get_jquery_js()
6313
{
6314
    return api_get_asset('jquery/dist/jquery.min.js');
6315
}
6316
6317
/**
6318
 * Returns the jquery path
6319
 * @return string
6320
 */
6321
function api_get_jquery_web_path()
6322
{
6323
    return api_get_asset('jquery/dist/jquery.min.js', true);
6324
}
6325
6326
/**
6327
 * @return string
6328
 */
6329
function api_get_jquery_ui_js_web_path()
6330
{
6331
    return api_get_asset('jquery-ui/jquery-ui.min.js', true);
6332
}
6333
6334
/**
6335
 * @return string
6336
 */
6337
function api_get_jquery_ui_css_web_path()
6338
{
6339
    return api_get_asset('jquery-ui/themes/smoothness/jquery-ui.min.css', true);
6340
}
6341
6342
/**
6343
 * Returns the jquery-ui library js headers
6344
 * @param   bool    add the jqgrid library
6345
 * @return  string  html tags
6346
 *
6347
 */
6348
function api_get_jquery_ui_js($include_jqgrid = false) {
6349
    $libraries = array();
6350
    if ($include_jqgrid) {
6351
       $libraries[]='jqgrid';
6352
    }
6353
    return api_get_jquery_libraries_js($libraries);
6354
}
6355
6356
function api_get_jqgrid_js() {
6357
    return api_get_jquery_libraries_js(array('jqgrid'));
6358
}
6359
6360
/**
6361
 * Returns the jquery library js and css headers
6362
 *
6363
 * @param   array   list of jquery libraries supported jquery-ui, jqgrid
6364
 * @param   bool    add the jquery library
6365
 * @return  string  html tags
6366
 *
6367
 */
6368
function api_get_jquery_libraries_js($libraries) {
6369
    $js = '';
6370
    //jqgrid js and css
6371
    if (in_array('jqgrid', $libraries)) {
6372
        $language = 'en';
6373
        $platform_isocode = strtolower(api_get_language_isocode());
6374
6375
        //languages supported by jqgrid see files in main/inc/lib/javascript/jqgrid/js/i18n
6376
        $jqgrid_langs = array(
6377
            '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'
6378
        );
6379
6380
        if (in_array($platform_isocode, $jqgrid_langs)) {
6381
            $language = $platform_isocode;
6382
        }
6383
        //$js .= '<link rel="stylesheet" href="'.$js_path.'jqgrid/css/ui.jqgrid.css" type="text/css">';
6384
        /*$js .= api_get_css($js_path.'jqgrid/css/ui.jqgrid.css');
6385
        $js .= api_get_js('jqgrid/js/i18n/grid.locale-'.$languaje.'.js');
6386
        $j
6387
6388
        s .= api_get_js('jqgrid/js/jquery.jqGrid.min.js');*/
6389
6390
        $js .= api_get_css_asset('jqgrid/css/ui.jqgrid.css');
6391
        $js .= api_get_asset('jqgrid/js/minified/jquery.jqGrid.min.js');
6392
        $js .= api_get_asset('jqgrid/js/i18n/grid.locale-'.$language.'.js');
6393
    }
6394
6395
    //Document multiple upload funcionality
6396
    if (in_array('jquery-upload', $libraries)) {
6397
        $js .= api_get_asset('blueimp-load-image/js/load-image.all.min.js');
6398
        $js .= api_get_asset('blueimp-canvas-to-blob/js/canvas-to-blob.min.js');
6399
        $js .= api_get_asset('jquery-file-upload/js/jquery.iframe-transport.js');
6400
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload.js');
6401
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-process.js');
6402
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-image.js');
6403
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-audio.js');
6404
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-video.js');
6405
        $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-validate.js');
6406
        $js .= api_get_css_asset('jquery-file-upload/css/jquery.fileupload.css');
6407
        $js .= api_get_css_asset('jquery-file-upload/css/jquery.fileupload-ui.css');
6408
    }
6409
6410
    // jquery datepicker
6411
    if (in_array('datepicker', $libraries)) {
6412
        $languaje   = 'en-GB';
6413
        $platform_isocode = strtolower(api_get_language_isocode());
6414
6415
        // languages supported by jqgrid see files in main/inc/lib/javascript/jqgrid/js/i18n
6416
        $datapicker_langs = array(
6417
            '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'
6418
        );
6419
        if (in_array($platform_isocode, $datapicker_langs)) {
6420
            $languaje = $platform_isocode;
6421
        }
6422
6423
        $js .= api_get_js('jquery-ui/jquery-ui-i18n.min.js');
6424
        $script = '<script>
6425
        $(function(){
6426
            $.datepicker.setDefaults($.datepicker.regional["'.$languaje.'"]);
6427
            $.datepicker.regional["local"] = $.datepicker.regional["'.$languaje.'"];
6428
        });
6429
        </script>
6430
        ';
6431
        $js .= $script;
6432
    }
6433
    return $js;
6434
}
6435
6436
/**
6437
 * Returns the course's URL
6438
 *
6439
 * This function relies on api_get_course_info()
6440
 * @param   string  The course code - optional (takes it from session if not given)
6441
 * @param   int     The session id  - optional (takes it from session if not given)
6442
 * @param integer $session_id
6443
 * @return  string|null   The URL of the course or null if something does not work
6444
 * @author  Julio Montoya <[email protected]>
6445
 */
6446
function api_get_course_url($course_code = null, $session_id = null)
6447
{
6448
    if (empty($course_code)) {
6449
        $course_info = api_get_course_info();
6450
    } else {
6451
        $course_info = api_get_course_info($course_code);
6452
    }
6453
    if (empty($session_id)) {
6454
        $session_url = '?id_session='.api_get_session_id();
6455
    } else {
6456
        $session_url = '?id_session='.intval($session_id);
6457
    }
6458
    /*
6459
    if (empty($group_id)) {
6460
        $group_url = '&gidReq='.api_get_group_id();
6461
    } else {
6462
        $group_url = '&gidReq='.intval($group_id);
6463
    }*/
6464
    if (!empty($course_info['path'])) {
6465
        return api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php'.$session_url;
6466
    }
6467
    return null;
6468
}
6469
6470
/**
6471
 *
6472
 * Check if the current portal has the $_configuration['multiple_access_urls'] parameter on
6473
 * @return bool true if multi site is enabled
6474
 *
6475
 **/
6476
function api_get_multiple_access_url()
6477
{
6478
    return api_get_configuration_value('multiple_access_urls');
6479
}
6480
6481
/**
6482
 * @return bool
6483
 */
6484
function api_is_multiple_url_enabled() {
6485
    return api_get_multiple_access_url();
6486
}
6487
6488
/**
6489
 * Returns a md5 unique id
6490
 * @todo add more parameters
6491
 */
6492
function api_get_unique_id() {
6493
    $id = md5(time().uniqid().api_get_user_id().api_get_course_id().api_get_session_id());
6494
    return $id;
6495
}
6496
6497
/**
6498
 * Get home path
6499
 * @return string
6500
 */
6501
function api_get_home_path()
6502
{
6503
    // FIX : Start the routing determination from central path definition
6504
    $home = api_get_path(SYS_HOME_PATH);
6505
    if (api_get_multiple_access_url()) {
6506
        $access_url_id = api_get_current_access_url_id();
6507
        $url_info = api_get_access_url($access_url_id);
6508
        $url = api_remove_trailing_slash(preg_replace('/https?:\/\//i', '', $url_info['url']));
6509
        $clean_url = api_replace_dangerous_char($url);
6510
        $clean_url = str_replace('/', '-', $clean_url);
6511
        $clean_url .= '/';
6512
        if ($clean_url != 'localhost/') {
6513
            // means that the multiple URL was not well configured we don't rename the $home variable
6514
            return "{$home}{$clean_url}";
6515
        }
6516
    }
6517
6518
    return $home;
6519
}
6520
6521
/**
6522
 *
6523
 * @param int Course id
6524
 * @param int tool id: TOOL_QUIZ, TOOL_FORUM, TOOL_STUDENTPUBLICATION, TOOL_LEARNPATH
6525
 * @param int the item id (tool id, exercise id, lp id)
6526
 *
6527
 */
6528
function api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code = null) {
6529
    if (api_is_platform_admin()) {
6530
        return false;
6531
    }
6532
    if (api_get_setting('gradebook_locking_enabled') == 'true') {
6533
        if (empty($course_code)) {
6534
            $course_code = api_get_course_id();
6535
        }
6536
        $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
6537
        $item_id = intval($item_id);
6538
        $link_type = intval($link_type);
6539
        $course_code = Database::escape_string($course_code);
6540
        $sql = "SELECT locked FROM $table
6541
                WHERE locked = 1 AND ref_id = $item_id AND type = $link_type AND course_code = '$course_code' ";
6542
        $result = Database::query($sql);
6543
        if (Database::num_rows($result)) {
6544
            return true;
6545
        }
6546
    }
6547
    return false;
6548
}
6549
6550
/**
6551
 * Blocks a page if the item was added in a gradebook
6552
 *
6553
 * @param int       exercise id, work id, thread id,
6554
 * @param int       LINK_EXERCISE, LINK_STUDENTPUBLICATION, LINK_LEARNPATH LINK_FORUM_THREAD, LINK_ATTENDANCE
6555
 * see gradebook/lib/be/linkfactory
6556
 * @param string    course code
6557
 * @return false|null
6558
 */
6559
function api_block_course_item_locked_by_gradebook($item_id, $link_type, $course_code = null) {
6560
    if (api_is_platform_admin()) {
6561
        return false;
6562
    }
6563
6564
    if (api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code)) {
6565
        $message = Display::return_message(get_lang('ResourceLockedByGradebook'), 'warning');
6566
        api_not_allowed(true, $message);
6567
    }
6568
}
6569
/**
6570
 * Checks the PHP version installed is enough to run Chamilo
6571
 * @param string Include path (used to load the error page)
6572
 * @return void
6573
 */
6574
function api_check_php_version($my_inc_path = null) {
6575
    if (!function_exists('version_compare') || version_compare( phpversion(), REQUIRED_PHP_VERSION, '<')) {
6576
        $global_error_code = 1;
6577
        // Incorrect PHP version
6578
        $global_page = $my_inc_path.'global_error_message.inc.php';
6579
        if (file_exists($global_page)) {
6580
            require $global_page;
6581
        }
6582
        exit;
6583
    }
6584
}
6585
/**
6586
 * Checks whether the Archive directory is present and writeable. If not,
6587
 * prints a warning message.
6588
 */
6589
function api_check_archive_dir() {
6590 View Code Duplication
    if (is_dir(api_get_path(SYS_ARCHIVE_PATH)) && !is_writable(api_get_path(SYS_ARCHIVE_PATH))) {
6591
        $message = Display::return_message(get_lang('ArchivesDirectoryNotWriteableContactAdmin'),'warning');
6592
        api_not_allowed(true, $message);
6593
    }
6594
}
6595
/**
6596
 * Returns an array of global configuration settings which should be ignored
6597
 * when printing the configuration settings screens
6598
 * @return array Array of strings, each identifying one of the excluded settings
6599
 */
6600
function api_get_locked_settings() {
6601
    return array(
6602
        'server_type',
6603
        'permanently_remove_deleted_files',
6604
        'account_valid_duration',
6605
        'service_ppt2lp',
6606
        'wcag_anysurfer_public_pages',
6607
        'upload_extensions_list_type',
6608
        'upload_extensions_blacklist',
6609
        'upload_extensions_whitelist',
6610
        'upload_extensions_skip',
6611
        'upload_extensions_replace_by',
6612
        'hide_dltt_markup',
6613
        'split_users_upload_directory',
6614
        'permissions_for_new_directories',
6615
        'permissions_for_new_files',
6616
        'platform_charset',
6617
        'ldap_description',
6618
        'cas_activate',
6619
        'cas_server',
6620
        'cas_server_uri',
6621
        'cas_port',
6622
        'cas_protocol',
6623
        'cas_add_user_activate',
6624
        'update_user_info_cas_with_ldap',
6625
        'languagePriority1',
6626
        'languagePriority2',
6627
        'languagePriority3',
6628
        'languagePriority4',
6629
        'login_is_email',
6630
        'chamilo_database_version'
6631
    );
6632
}
6633
6634
/**
6635
 * Checks if the user is corrently logged in. Returns the user ID if he is, or
6636
 * false if he isn't. If the user ID is given and is an integer, then the same
6637
 * ID is simply returned
6638
 * @param  integer User ID
6639
 * @return boolean Integer User ID is logged in, or false otherwise
6640
 */
6641
function api_user_is_login($user_id = null) {
6642
    $user_id = empty($user_id) ? api_get_user_id() : intval($user_id);
6643
    return $user_id && !api_is_anonymous();
6644
}
6645
6646
/**
6647
 * Guess the real ip for register in the database, even in reverse proxy cases.
6648
 * To be recognized, the IP has to be found in either $_SERVER['REMOTE_ADDR'] or
6649
 * in $_SERVER['HTTP_X_FORWARDED_FOR'], which is in common use with rproxies.
6650
 * @return string the user's real ip (unsafe - escape it before inserting to db)
6651
 * @author Jorge Frisancho Jibaja <[email protected]>, USIL - Some changes to allow the use of real IP using reverse proxy
6652
 * @version CEV CHANGE 24APR2012
6653
 */
6654
function api_get_real_ip(){
6655
    // Guess the IP if behind a reverse proxy
6656
    global $debug;
6657
    $ip = trim($_SERVER['REMOTE_ADDR']);
6658
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
6659
        if (preg_match('/,/', $_SERVER['HTTP_X_FORWARDED_FOR'])) {
6660
            @list($ip1, $ip2) = @explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
6661
        } else {
6662
            $ip1 = $_SERVER['HTTP_X_FORWARDED_FOR'];
6663
        }
6664
        $ip = trim($ip1);
6665
    }
6666
    if (!empty($debug)) error_log('Real IP: '.$ip);
6667
    return $ip;
6668
}
6669
6670
/**
6671
 * Checks whether an IP is included inside an IP range
6672
 * @param string IP address
6673
 * @param string IP range
6674
 * @param string $ip
6675
 * @return bool True if IP is in the range, false otherwise
6676
 * @author claudiu at cnixs dot com  on http://www.php.net/manual/fr/ref.network.php#55230
6677
 * @author Yannick Warnier for improvements and managment of multiple ranges
6678
 * @todo check for IPv6 support
6679
 */
6680
function api_check_ip_in_range($ip,$range)
6681
{
6682
    if (empty($ip) or empty($range)) {
6683
        return false;
6684
    }
6685
    $ip_ip = ip2long ($ip);
6686
    // divide range param into array of elements
6687
    if (strpos($range,',')!==false) {
6688
        $ranges = explode(',',$range);
6689
    } else {
6690
        $ranges = array($range);
6691
    }
6692
    foreach ($ranges as $range) {
6693
        $range = trim($range);
6694
        if (empty($range)) { continue; }
6695
        if (strpos($range,'/')===false) {
6696
            if (strcmp($ip,$range)===0) {
6697
                return true; // there is a direct IP match, return OK
6698
            }
6699
            continue; //otherwise, get to the next range
6700
        }
6701
        // the range contains a "/", so analyse completely
6702
        list ($net, $mask) = explode("/", $range);
6703
6704
        $ip_net = ip2long ($net);
6705
        // mask binary magic
6706
        $ip_mask = ~((1 << (32 - $mask)) - 1);
6707
6708
        $ip_ip_net = $ip_ip & $ip_mask;
6709
        if ($ip_ip_net == $ip_net) {
6710
            return true;
6711
        }
6712
    }
6713
6714
    return false;
6715
}
6716
6717
function api_check_user_access_to_legal($course_visibility) {
6718
    $course_visibility_list = array(COURSE_VISIBILITY_OPEN_WORLD, COURSE_VISIBILITY_OPEN_PLATFORM);
6719
    return in_array($course_visibility, $course_visibility_list) || api_is_drh();
6720
}
6721
6722
/**
6723
 * Checks if the global chat is enabled or not
6724
 *
6725
 * @return bool
6726
 */
6727
function api_is_global_chat_enabled()
6728
{
6729
    return
6730
        !api_is_anonymous() &&
6731
        api_get_setting('allow_global_chat') == 'true' &&
6732
        api_get_setting('allow_social_tool') == 'true';
6733
}
6734
6735
/**
6736
 * @todo Fix tool_visible_by_default_at_creation labels
6737
 * @todo Add sessionId parameter to avoid using context
6738
 *
6739
 * @param int $item_id
6740
 * @param int $tool_id
6741
 * @param int $group_id iid
6742
 * @param array $courseInfo
6743
 */
6744
function api_set_default_visibility(
6745
    $item_id,
6746
    $tool_id,
6747
    $group_id = 0,
6748
    $courseInfo = array(),
6749
    $sessionId = 0,
6750
    $userId = 0
6751
) {
6752
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
6753
    $courseId = $courseInfo['real_id'];
6754
    $courseCode = $courseInfo['code'];
6755
    $sessionId = empty($sessionId) ? api_get_session_id() : $sessionId;
6756
    $userId = empty($userId) ? api_get_user_id() : $userId;
6757
6758
    if (empty($group_id)) {
6759
        $group_id = api_get_group_id();
6760
    }
6761
6762
    $groupInfo = GroupManager::get_group_properties($group_id);
6763
    $groupIid = 0;
6764
    if ($groupInfo) {
6765
        $groupIid = $groupInfo['iid'];
6766
    }
6767
6768
    $original_tool_id = $tool_id;
6769
6770
    switch ($tool_id) {
6771
        case TOOL_LINK:
6772
        case TOOL_LINK_CATEGORY:
6773
            $tool_id = 'links';
6774
            break;
6775
        case TOOL_DOCUMENT:
6776
            $tool_id = 'documents';
6777
            break;
6778
        case TOOL_LEARNPATH:
6779
            $tool_id = 'learning';
6780
            break;
6781
        case TOOL_ANNOUNCEMENT:
6782
            $tool_id = 'announcements';
6783
            break;
6784
        case TOOL_FORUM:
6785
        case TOOL_FORUM_CATEGORY:
6786
        case TOOL_FORUM_THREAD:
6787
            $tool_id = 'forums';
6788
            break;
6789
        case TOOL_QUIZ:
6790
            $tool_id = 'quiz';
6791
            break;
6792
    }
6793
    $setting = api_get_setting('tool_visible_by_default_at_creation');
6794
6795
    if (isset($setting[$tool_id])) {
6796
        $visibility = 'invisible';
6797
        if ($setting[$tool_id] == 'true') {
6798
            $visibility = 'visible';
6799
        }
6800
6801
        // Read the portal and course default visibility
6802
        if ($tool_id == 'documents') {
6803
            $visibility = DocumentManager::getDocumentDefaultVisibility($courseCode);
6804
        }
6805
6806
        api_item_property_update(
6807
            $courseInfo,
6808
            $original_tool_id,
6809
            $item_id,
6810
            $visibility,
6811
            $userId,
6812
            $groupIid,
6813
            null,
6814
            null,
6815
            null,
6816
            api_get_session_id()
6817
        );
6818
6819
        // Fixes default visibility for tests
6820
6821
        switch ($original_tool_id) {
6822
            case TOOL_QUIZ:
6823
                if (empty($sessionId)) {
6824
                    $objExerciseTmp = new Exercise($courseId);
6825
                    $objExerciseTmp->read($item_id);
6826
                    if ($visibility == 'visible') {
6827
                        $objExerciseTmp->enable();
6828
                        $objExerciseTmp->save();
6829
                    } else {
6830
                        $objExerciseTmp->disable();
6831
                        $objExerciseTmp->save();
6832
                    }
6833
                }
6834
                break;
6835
        }
6836
    }
6837
}
6838
6839
/**
6840
 * @return string
6841
 */
6842
function api_get_security_key() {
6843
    return api_get_configuration_value('security_key');
6844
}
6845
6846
/**
6847
 * @param int $user_id
6848
 * @param int $courseId
6849
 * @param int $session_id
6850
 * @return array
6851
 */
6852
function api_detect_user_roles($user_id, $courseId, $session_id = 0)
6853
{
6854
    $user_roles = array();
6855
    /*$user_info = api_get_user_info($user_id);
6856
    $user_roles[] = $user_info['status'];*/
6857
    $courseInfo = api_get_course_info_by_id($courseId);
6858
    $course_code = $courseInfo['code'];
6859
6860
    $url_id = api_get_current_access_url_id();
6861
    if (api_is_platform_admin_by_id($user_id, $url_id)) {
6862
        $user_roles[] = PLATFORM_ADMIN;
6863
    }
6864
6865
    /*if (api_is_drh()) {
6866
        $user_roles[] = DRH;
6867
    }*/
6868
6869
    if (!empty($session_id)) {
6870
        if (SessionManager::user_is_general_coach($user_id, $session_id)) {
6871
            $user_roles[] = SESSION_GENERAL_COACH;
6872
        }
6873
    }
6874
6875
    if (!empty($course_code)) {
6876
        if (empty($session_id)) {
6877
            if (CourseManager::is_course_teacher($user_id, $course_code)) {
6878
                $user_roles[] = COURSEMANAGER;
6879
            }
6880
            if (CourseManager::get_tutor_in_course_status($user_id, $courseInfo['real_id'])) {
6881
                $user_roles[] = COURSE_TUTOR;
6882
            }
6883
6884
            if (CourseManager::is_user_subscribed_in_course($user_id, $course_code)) {
6885
                $user_roles[] = COURSE_STUDENT;
6886
            }
6887
        } else {
6888
            $user_status_in_session = SessionManager::get_user_status_in_course_session(
6889
                $user_id,
6890
                $courseId,
6891
                $session_id
6892
            );
6893
6894
            if (!empty($user_status_in_session)) {
6895
                if ($user_status_in_session == 0) {
6896
                    $user_roles[] = SESSION_STUDENT;
6897
                }
6898
                if ($user_status_in_session == 2) {
6899
                    $user_roles[] = SESSION_COURSE_COACH;
6900
                }
6901
            }
6902
6903
            /*if (api_is_course_session_coach($user_id, $course_code, $session_id)) {
6904
               $user_roles[] = SESSION_COURSE_COACH;
6905
            }*/
6906
        }
6907
    }
6908
    return $user_roles;
6909
}
6910
6911
/**
6912
 * @param int $courseId
6913
 * @param int $session_id
6914
 * @return bool
6915
 */
6916
function api_coach_can_edit_view_results($courseId = null, $session_id = null)
6917
{
6918
    $user_id = api_get_user_id();
6919
6920
    if (empty($courseId)) {
6921
        $courseId = api_get_course_int_id();
6922
    }
6923
6924
    if (empty($session_id)) {
6925
        $session_id = api_get_session_id();
6926
    }
6927
6928
    if (api_is_platform_admin()) {
6929
        return true;
6930
    }
6931
6932
    $roles = api_detect_user_roles($user_id, $courseId, $session_id);
6933
6934
    if (in_array(SESSION_COURSE_COACH, $roles)) {
6935
        //return api_get_setting('session_tutor_reports_visibility') == 'true';
6936
        return true;
6937
    } else {
6938
        if (in_array(COURSEMANAGER, $roles)) {
6939
            return true;
6940
        }
6941
        return false;
6942
    }
6943
}
6944
6945
function api_get_js_simple($file) {
6946
    return '<script type="text/javascript" src="'.$file.'"></script>'."\n";
6947
}
6948
6949
function api_set_settings_and_plugins() {
6950
    global $_configuration;
6951
    $_setting = array();
6952
    $_plugins = array();
6953
6954
    // access_url == 1 is the default chamilo location
6955
    $settings_by_access_list = array();
6956
    $access_url_id = api_get_current_access_url_id();
6957 View Code Duplication
    if ($access_url_id != 1) {
6958
        $url_info = api_get_access_url($_configuration['access_url']);
6959
        if ($url_info['active'] == 1) {
6960
            $settings_by_access = & api_get_settings(null, 'list', $_configuration['access_url'], 1);
6961
            foreach ($settings_by_access as & $row) {
6962
                if (empty($row['variable'])) {
6963
                    $row['variable'] = 0;
6964
                }
6965
                if (empty($row['subkey'])) {
6966
                    $row['subkey'] = 0;
6967
                }
6968
                if (empty($row['category'])) {
6969
                    $row['category'] = 0;
6970
                }
6971
                $settings_by_access_list[$row['variable']][$row['subkey']][$row['category']] = $row;
6972
            }
6973
        }
6974
    }
6975
6976
    $result = api_get_settings(null, 'list', 1);
6977
6978 View Code Duplication
    foreach ($result as & $row) {
6979
        if ($access_url_id != 1) {
6980
            if ($url_info['active'] == 1) {
6981
                $var = empty($row['variable']) ? 0 : $row['variable'];
6982
                $subkey = empty($row['subkey']) ? 0 : $row['subkey'];
6983
                $category = empty($row['category']) ? 0 : $row['category'];
6984
            }
6985
6986
            if ($row['access_url_changeable'] == 1 && $url_info['active'] == 1) {
6987
                if (isset($settings_by_access_list[$var]) &&
6988
                    $settings_by_access_list[$var][$subkey][$category]['selected_value'] != '') {
6989
                    if ($row['subkey'] == null) {
6990
                        $_setting[$row['variable']] = $settings_by_access_list[$var][$subkey][$category]['selected_value'];
6991
                    } else {
6992
                        $_setting[$row['variable']][$row['subkey']] = $settings_by_access_list[$var][$subkey][$category]['selected_value'];
6993
                    }
6994
                } else {
6995
                    if ($row['subkey'] == null) {
6996
                        $_setting[$row['variable']] = $row['selected_value'];
6997
                    } else {
6998
                        $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
6999
                    }
7000
                }
7001
            } else {
7002
                if ($row['subkey'] == null) {
7003
                    $_setting[$row['variable']] = $row['selected_value'];
7004
                } else {
7005
                    $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7006
                }
7007
            }
7008
        } else {
7009
            if ($row['subkey'] == null) {
7010
                $_setting[$row['variable']] = $row['selected_value'];
7011
            } else {
7012
                $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
7013
            }
7014
        }
7015
    }
7016
7017
    $result = api_get_settings('Plugins', 'list', $access_url_id);
7018
    $_plugins = array();
7019 View Code Duplication
    foreach ($result as & $row) {
7020
        $key = & $row['variable'];
7021
        if (is_string($_setting[$key])) {
7022
            $_setting[$key] = array();
7023
        }
7024
        $_setting[$key][] = $row['selected_value'];
7025
        $_plugins[$key][] = $row['selected_value'];
7026
    }
7027
7028
    $_SESSION['_setting'] = $_setting;
7029
    $_SESSION['_plugins'] = $_plugins;
7030
}
7031
7032
/**
7033
 * Tries to set memory limit, if authorized and new limit is higher than current
7034
 * @param string New memory limit
7035
 * @param string $mem
7036
 * @return bool True on success, false on failure or current is higher than suggested
7037
 * @assert (null) === false
7038
 * @assert (-1) === false
7039
 * @assert (0) === true
7040
 * @assert ('1G') === true
7041
 */
7042
function api_set_memory_limit($mem){
7043
    //if ini_set() not available, this function is useless
7044
    if (!function_exists('ini_set') || is_null($mem) || $mem == -1) {
7045
        return false;
7046
    }
7047
7048
    $memory_limit = ini_get('memory_limit');
7049
    if (api_get_bytes_memory_limit($mem) > api_get_bytes_memory_limit($memory_limit)){
7050
        ini_set('memory_limit', $mem);
7051
        return true;
7052
    }
7053
    return false;
7054
}
7055
7056
/**
7057
 * Gets memory limit in bytes
7058
 * @param string The memory size (128M, 1G, 1000K, etc)
7059
 * @return int
7060
 * @assert (null) === false
7061
 * @assert ('1t')  === 1099511627776
7062
 * @assert ('1g')  === 1073741824
7063
 * @assert ('1m')  === 1048576
7064
 * @assert ('100k') === 102400
7065
 */
7066
function api_get_bytes_memory_limit($mem){
7067
    $size = strtolower(substr($mem,-1));
7068
7069
    switch ($size) {
7070
        case 't':
7071
            $mem = intval(substr($mem,-1))*1024*1024*1024*1024;
7072
            break;
7073
        case 'g':
7074
            $mem = intval(substr($mem,0,-1))*1024*1024*1024;
7075
            break;
7076
        case 'm':
7077
            $mem = intval(substr($mem,0,-1))*1024*1024;
7078
            break;
7079
        case 'k':
7080
            $mem = intval(substr($mem,0,-1))*1024;
7081
            break;
7082
        default:
7083
            // we assume it's integer only
7084
            $mem = intval($mem);
7085
            break;
7086
    }
7087
    return $mem;
7088
}
7089
7090
/**
7091
 * Finds all the information about a user from username instead of user id
7092
 *
7093
 * @param string $officialCode
7094
 * @return array $user_info user_id, lastname, firstname, username, email, ...
7095
 * @author Yannick Warnier <[email protected]>
7096
 */
7097 View Code Duplication
function api_get_user_info_from_official_code($officialCode)
7098
{
7099
    if (empty($officialCode)) {
7100
        return false;
7101
    }
7102
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
7103
            WHERE official_code ='".Database::escape_string($officialCode)."'";
7104
    $result = Database::query($sql);
7105
    if (Database::num_rows($result) > 0) {
7106
        $result_array = Database::fetch_array($result);
7107
        return _api_format_user($result_array);
7108
    }
7109
    return false;
7110
}
7111
7112
/**
7113
 * @param string $usernameInputId
7114
 * @param string $passwordInputId
7115
 * @return null|string
7116
 */
7117
function api_get_password_checker_js($usernameInputId, $passwordInputId)
7118
{
7119
    $checkPass = api_get_setting('allow_strength_pass_checker');
7120
    $useStrengthPassChecker = $checkPass === 'true';
7121
7122
    if ($useStrengthPassChecker === false) {
7123
        return null;
7124
    }
7125
7126
    $translations = [
7127
        'wordLength' => get_lang('PasswordIsTooShort'),
7128
        'wordNotEmail' => get_lang('YourPasswordCannotBeTheSameAsYourEmail'),
7129
        'wordSimilarToUsername' => get_lang('YourPasswordCannotContainYourUsername'),
7130
        'wordTwoCharacterClasses' => get_lang('WordTwoCharacterClasses'),
7131
        'wordRepetitions' => get_lang('TooManyRepetitions'),
7132
        'wordSequences' => get_lang('YourPasswordContainsSequences'),
7133
        'errorList' => get_lang('ErrorsFound'),
7134
        'veryWeak' => get_lang('PasswordVeryWeak'),
7135
        'weak' => get_lang('PasswordWeak'),
7136
        'normal' => get_lang('PasswordNormal'),
7137
        'medium' => get_lang('PasswordMedium'),
7138
        'strong' => get_lang('PasswordStrong'),
7139
        'veryStrong' => get_lang('PasswordVeryStrong')
7140
    ];
7141
7142
    $js = api_get_asset('pwstrength-bootstrap/dist/pwstrength-bootstrap.min.js');
7143
    $js .=  "<script>    
7144
    var errorMessages = {
7145
        password_to_short : \"" . get_lang('PasswordIsTooShort')."\",
7146
        same_as_username : \"".get_lang('YourPasswordCannotBeTheSameAsYourUsername')."\"
7147
    };
7148
7149
    $(document).ready(function() {
7150
        var lang = ".json_encode($translations).";     
7151
        var options = {        
7152
            onLoad : function () {
7153
                //$('#messages').text('Start typing password');
7154
            },
7155
            onKeyUp: function (evt) {
7156
                $(evt.target).pwstrength('outputErrorList');
7157
            },
7158
            errorMessages : errorMessages,
7159
            viewports: {
7160
                progress: '#password_progress',
7161
                verdict: '#password-verdict',
7162
                errors: '#password-errors'
7163
            },
7164
            usernameField: '$usernameInputId'
7165
        };
7166
        options.i18n = {
7167
            t: function (key) {
7168
                var result = lang[key];
7169
                return result === key ? '' : result; // This assumes you return the                
7170
            }
7171
        };
7172
        $('".$passwordInputId."').pwstrength(options);
7173
    });
7174
    </script>";
7175
7176
    return $js;
7177
}
7178
7179
/**
7180
 * @param string $username
7181
 * create an user extra field called 'captcha_blocked_until_date'
7182
 */
7183
function api_block_account_captcha($username)
7184
{
7185
    $userInfo = api_get_user_info_from_username($username);
7186
    if (empty($userInfo)) {
7187
        return false;
7188
    }
7189
    $minutesToBlock = api_get_setting('captcha_time_to_block');
7190
    $time = time() + $minutesToBlock*60;
7191
    UserManager::update_extra_field_value(
7192
        $userInfo['user_id'],
7193
        'captcha_blocked_until_date',
7194
        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...
7195
    );
7196
}
7197
7198
/**
7199
 * @param string $username
7200
 */
7201
function api_clean_account_captcha($username)
7202
{
7203
    $userInfo = api_get_user_info_from_username($username);
7204
    if (empty($userInfo)) {
7205
        return false;
7206
    }
7207
    Session::erase('loginFailedCount');
7208
    UserManager::update_extra_field_value(
7209
        $userInfo['user_id'],
7210
        'captcha_blocked_until_date',
7211
        null
7212
    );
7213
}
7214
7215
/**
7216
 * @param string $username
7217
 * @return bool
7218
 */
7219
function api_get_user_blocked_by_captcha($username)
7220
{
7221
    $userInfo = api_get_user_info_from_username($username);
7222
    if (empty($userInfo)) {
7223
        return false;
7224
    }
7225
    $data = UserManager::get_extra_user_data_by_field(
7226
        $userInfo['user_id'],
7227
        'captcha_blocked_until_date'
7228
    );
7229
    if (isset($data) && isset($data['captcha_blocked_until_date'])) {
7230
        return $data['captcha_blocked_until_date'];
7231
    }
7232
    return false;
7233
}
7234
7235
/**
7236
 * Remove tags from HTML anf return the $in_number_char first non-HTML char
7237
 * Postfix the text with "..." if it has been truncated.
7238
 * @param integer $in_number_char
7239
 * @return string
7240
 * @author hubert borderiou
7241
 */
7242
function api_get_short_text_from_html($in_html, $in_number_char)
7243
{
7244
    $out_res = api_remove_tags_with_space($in_html, false);
7245
    $postfix = "...";
7246
    if (strlen($out_res) > $in_number_char) {
7247
        $out_res = substr($out_res, 0, $in_number_char).$postfix;
7248
    }
7249
    return $out_res;
7250
}
7251
7252
/**
7253
 * Replace tags with a space in a text.
7254
 * If $in_double_quote_replace, replace " with '' (for HTML attribute purpose, for exemple)
7255
 * @return string
7256
 * @author hubert borderiou
7257
 */
7258
function api_remove_tags_with_space($in_html, $in_double_quote_replace = true) {
7259
    $out_res = $in_html;
7260
    if ($in_double_quote_replace) {
7261
        $out_res = str_replace('"', "''", $out_res);
7262
    }
7263
    // avoid text stuck together when tags are removed, adding a space after >
7264
    $out_res = str_replace (">", "> ", $out_res);
7265
    $out_res = strip_tags($out_res);
7266
7267
    return $out_res;
7268
}
7269
7270
/**
7271
 * If true, the drh can access all content (courses, users) inside a session
7272
 * @return bool
7273
 */
7274
function api_drh_can_access_all_session_content()
7275
{
7276
    $value = api_get_setting('drh_can_access_all_session_content');
7277
7278
    return $value === 'true';
7279
}
7280
7281
/**
7282
 * @param string $tool
7283
 * @param string $setting
7284
 * @param integer $defaultValue
7285
 * @return string
7286
 */
7287
function api_get_default_tool_setting($tool, $setting, $defaultValue)
7288
{
7289
    global $_configuration;
7290
    if (isset($_configuration[$tool]) &&
7291
        isset($_configuration[$tool]['default_settings']) &&
7292
        isset($_configuration[$tool]['default_settings'][$setting])
7293
    ) {
7294
        return $_configuration[$tool]['default_settings'][$setting];
7295
    }
7296
7297
    return $defaultValue;
7298
}
7299
7300
/**
7301
 * Checks if user can login as another user
7302
 *
7303
 * @param int $loginAsUserId the user id to log in
7304
 * @param int $userId my user id
7305
 * @return bool
7306
 */
7307
function api_can_login_as($loginAsUserId, $userId = null)
7308
{
7309
    if (empty($userId)) {
7310
        $userId = api_get_user_id();
7311
    }
7312
    if ($loginAsUserId == $userId) {
7313
        return false;
7314
    }
7315
7316
    if (empty($loginAsUserId)) {
7317
        return false;
7318
    }
7319
7320
    if ($loginAsUserId != strval(intval($loginAsUserId))) {
7321
        return false;
7322
    }
7323
7324
    // Check if the user to login is an admin
7325
    if (api_is_platform_admin_by_id($loginAsUserId)) {
7326
        // Only super admins can login to admin accounts
7327
        if (!api_global_admin_can_edit_admin($loginAsUserId)) {
7328
            return false;
7329
        }
7330
    }
7331
7332
    $userInfo = api_get_user_info($userId);
7333
7334
    $isDrh = function() use($loginAsUserId) {
7335
        if (api_is_drh()) {
7336
            if (api_drh_can_access_all_session_content()) {
7337
                $users = SessionManager::getAllUsersFromCoursesFromAllSessionFromStatus('drh_all', api_get_user_id());
7338
                $userList = array();
7339
                if (is_array($users)) {
7340
                    foreach ($users as $user) {
7341
                        $userList[] = $user['user_id'];
7342
                    }
7343
                }
7344
                if (in_array($loginAsUserId, $userList)) {
7345
                    return true;
7346
                }
7347
            } else {
7348
                if (api_is_drh() && UserManager::is_user_followed_by_drh($loginAsUserId, api_get_user_id())) {
7349
                    return true;
7350
                }
7351
            }
7352
        }
7353
        return false;
7354
    };
7355
7356
    return api_is_platform_admin() || (api_is_session_admin() && $userInfo['status'] == 5) || $isDrh();
7357
}
7358
7359
/**
7360
 * @return bool
7361
 */
7362
function api_is_allowed_in_course()
7363
{
7364
    if (api_is_platform_admin()) {
7365
        return true;
7366
    }
7367
7368
    return Session::read('is_allowed_in_course');
7369
}
7370
7371
/**
7372
 * Set the cookie to go directly to the course code $in_firstpage
7373
 * after login
7374
 * @param string $in_firstpage is the course code of the course to go
7375
 */
7376
function api_set_firstpage_parameter($in_firstpage)
7377
{
7378
    setcookie('GotoCourse', $in_firstpage);
7379
}
7380
7381
/**
7382
 * Delete the cookie to go directly to the course code $in_firstpage
7383
 * after login
7384
 */
7385
function api_delete_firstpage_parameter()
7386
{
7387
    setcookie('GotoCourse', '', time() - 3600);
7388
}
7389
7390
/**
7391
 * @return boolean if course_code for direct course access after login is set
7392
 */
7393
function exist_firstpage_parameter()
7394
{
7395
    return (isset($_COOKIE['GotoCourse']) && $_COOKIE['GotoCourse'] != "");
7396
}
7397
7398
/**
7399
 * @return return the course_code of the course where user login
7400
 */
7401
function api_get_firstpage_parameter()
7402
{
7403
    return $_COOKIE['GotoCourse'];
7404
}
7405
7406
/**
7407
 * Return true on https install
7408
 * @return boolean
7409
 */
7410
function api_is_https()
7411
{
7412
    return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off');
7413
}
7414
7415
/**
7416
 * Return protocol (http or https)
7417
 * @return string
7418
 */
7419
function api_get_protocol()
7420
{
7421
    return api_is_https() ? 'https' : 'http';
7422
}
7423
7424
/**
7425
 * Return a string where " are replaced with 2 '
7426
 * It is useful when you pass a PHP variable in a Javascript browser dialog
7427
 * e.g. : alert("<?php get_lang('Message') ?>");
7428
 * and message contains character "
7429
 *
7430
 * @param string $in_text
7431
 * @return string
7432
 */
7433
function convert_double_quote_to_single($in_text)
7434
{
7435
    return api_preg_replace('/"/', "''", $in_text);
7436
}
7437
7438
/**
7439
 * Get origin
7440
 *
7441
 * @param string
7442
 * @return string
7443
 **/
7444
function api_get_origin()
7445
{
7446
    if (isset($_REQUEST['origin'])) {
7447
        return $_REQUEST['origin'] === 'learnpath' ? 'learnpath' : '';
7448
    }
7449
7450
    return '';
7451
}
7452
7453
/**
7454
 * Warns an user that the portal reach certain limit.
7455
 * @param string $limitName
7456
 */
7457
function api_warn_hosting_contact($limitName)
7458
{
7459
    $hostingParams = api_get_configuration_value(1);
7460
    $email = null;
7461
7462
    if (!empty($hostingParams)) {
7463
        if (isset($hostingParams['hosting_contact_mail'])) {
7464
            $email = $hostingParams['hosting_contact_mail'];
7465
        }
7466
    }
7467
7468
    if (!empty($email)) {
7469
        $subject = get_lang('HostingWarningReached');
7470
        $body = get_lang('PortalName').': '.api_get_path(WEB_PATH)." \n ";
7471
        $body .= get_lang('PortalLimitType').': '.$limitName." \n ";
7472
        if (isset($hostingParams[$limitName])) {
7473
            $body .= get_lang('Value') . ': ' . $hostingParams[$limitName];
7474
        }
7475
        api_mail_html(null, $email, $subject, $body);
7476
    }
7477
}
7478
7479
/**
7480
 * @param string $variable
7481
 * @return bool|mixed
7482
 */
7483
function api_get_configuration_value($variable)
7484
{
7485
    return Container::getParameter($variable);
7486
}
7487
7488
/**
7489
 * Returns supported image extensions in the portal
7490
 * @param   bool    $supportVectors Whether vector images should also be accepted or not
7491
 * @return  array   Supported image extensions in the portal
7492
 */
7493
function api_get_supported_image_extensions($supportVectors = true)
7494
{
7495
    // jpg can also be called jpeg, jpe, jfif and jif. See https://en.wikipedia.org/wiki/JPEG#JPEG_filename_extensions
7496
    $supportedImageExtensions = array('jpg', 'jpeg', 'png', 'gif', 'jpe', 'jfif', 'jif');
7497
    if ($supportVectors) {
7498
        array_push($supportedImageExtensions, 'svg');
7499
    }
7500
    if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
7501
        array_push($supportedImageExtensions, 'webp');
7502
    }
7503
    return $supportedImageExtensions;
7504
}
7505
7506
/**
7507
 * This setting changes the registration status for the campus
7508
 *
7509
 * @author Patrick Cool <[email protected]>, Ghent University
7510
 * @version August 2006
7511
 * @param   bool    $listCampus Whether we authorize
7512
 * @todo the $_settings should be reloaded here. => write api function for this and use this in global.inc.php also.
7513
 */
7514 View Code Duplication
function api_register_campus($listCampus = true) {
7515
    $tbl_settings = Database :: get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
7516
7517
    $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='registered'";
7518
    Database::query($sql);
7519
7520
    if (!$listCampus) {
7521
        $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='donotlistcampus'";
7522
        Database::query($sql);
7523
    }
7524
}
7525
7526
/**
7527
 * Checks whether current user is a student boss
7528
 * @global array $_user
7529
 * @return boolean
7530
 */
7531
function api_is_student_boss()
7532
{
7533
    $_user = api_get_user_info();
7534
7535
    return isset($_user['status']) && $_user['status'] == STUDENT_BOSS;
7536
}
7537
7538
/**
7539
 * Check whether the user type should be exclude.
7540
 * Such as invited or anonymous users
7541
 * @param boolean $checkDB Optional. Whether check the user status
7542
 * @param int $userId Options. The user id
7543
 *
7544
 * @return boolean
7545
 */
7546
function api_is_excluded_user_type($checkDB = false, $userId = 0)
7547
{
7548
    if ($checkDB) {
7549
        $userId = empty($userId) ? api_get_user_id() : intval($userId);
7550
7551
        if ($userId == 0) {
7552
            return true;
7553
        }
7554
7555
        $userInfo = api_get_user_info($userId);
7556
7557
        switch ($userInfo['status']) {
7558
            case INVITEE:
7559
                //no break;
7560
            case ANONYMOUS:
7561
                return true;
7562
            default:
7563
                return false;
7564
        }
7565
    }
7566
7567
    $isInvited = api_is_invitee();
7568
    $isAnonymous = api_is_anonymous();
7569
7570
    if ($isInvited || $isAnonymous) {
7571
        return true;
7572
    }
7573
7574
    return false;
7575
}
7576
7577
/**
7578
 * Get the user status to ignore in reports
7579
 * @param string $format Optional. The result type (array or string)
7580
 * @return array|string
7581
 */
7582
function api_get_users_status_ignored_in_reports($format = 'array')
7583
{
7584
    $excludedTypes = array(
7585
        INVITEE,
7586
        ANONYMOUS
7587
    );
7588
7589
    if ($format == 'string') {
7590
        return implode(', ', $excludedTypes);
7591
    }
7592
7593
    return $excludedTypes;
7594
}
7595
7596
/**
7597
 * Set the Site Use Cookie Warning for 1 year
7598
 */
7599
function api_set_site_use_cookie_warning_cookie()
7600
{
7601
    setcookie('ChamiloUsesCookies', 'ok', time()+31556926);
7602
}
7603
7604
/**
7605
 * Return true if the Site Use Cookie Warning Cookie warning exists
7606
 * @return bool
7607
 */
7608
function api_site_use_cookie_warning_cookie_exist()
7609
{
7610
    return isset($_COOKIE['ChamiloUsesCookies']);
7611
}
7612
7613
/**
7614
 * Given a number of seconds, format the time to show hours, minutes and seconds
7615
 * @param int $time The time in seconds
7616
 * @param string $originFormat Optional. PHP o JS
7617
 * @return string (00h00'00")
7618
 */
7619
function api_format_time($time, $originFormat = 'php')
7620
{
7621
    $h = get_lang('h');
7622
    $hours = $time / 3600;
7623
    $mins = ($time % 3600) / 60;
7624
    $secs = ($time % 60);
7625
7626
    if ($time < 0) {
7627
        $hours = 0;
7628
        $mins = 0;
7629
        $secs = 0;
7630
    }
7631
7632
    if ($originFormat == 'js') {
7633
        $formattedTime = trim(sprintf("%02d : %02d : %02d", $hours, $mins, $secs));
7634
    } else {
7635
        $formattedTime = trim(sprintf("%02d$h%02d'%02d\"", $hours, $mins, $secs));
7636
    }
7637
7638
    return $formattedTime;
7639
}
7640
7641
/**
7642
 * Create a new empty directory with index.html file
7643
 * @param string $name The new directory name
7644
 * @param string $parentDirectory Directory parent directory name
7645
 * @return boolean Return true if the directory was create. Otherwise return false
7646
 */
7647
function api_create_protected_dir($name, $parentDirectory)
7648
{
7649
    $isCreated = false;
7650
7651
    if (!is_writable($parentDirectory)) {
7652
        return false;
7653
    }
7654
7655
    $fullPath = $parentDirectory . api_replace_dangerous_char($name);
7656
7657
    if (mkdir($fullPath, api_get_permissions_for_new_directories(), true)) {
7658
        $fp = fopen($fullPath . '/index.html', 'w');
7659
7660
        if ($fp) {
7661
            if (fwrite($fp, '<html><head></head><body></body></html>')) {
7662
                $isCreated = true;
7663
            }
7664
        }
7665
7666
        fclose($fp);
7667
    }
7668
7669
    return $isCreated;
7670
}
7671
7672
/**
7673
 * Sends an HTML email using the phpmailer class (and multipart/alternative to downgrade gracefully)
7674
 * Sender name and email can be specified, if not specified
7675
 * name and email of the platform admin are used
7676
 *
7677
 * @author Bert Vanderkimpen ICT&O UGent
7678
 * @author Yannick Warnier <[email protected]>
7679
 *
7680
 * @param string    name of recipient
7681
 * @param string    email of recipient
7682
 * @param string    email subject
7683
 * @param string    email body
7684
 * @param string    sender name
7685
 * @param string    sender e-mail
7686
 * @param array     extra headers in form $headers = array($name => $value) to allow parsing
7687
 * @param array     data file (path and filename)
7688
 * @param bool      True for attaching a embedded file inside content html (optional)
7689
 * @param array     Additional parameters
7690
 * @return          integer true if mail was sent
7691
 * @see             class.phpmailer.php
7692
 */
7693
function api_mail_html(
7694
    $recipient_name,
7695
    $recipient_email,
7696
    $subject,
7697
    $message,
7698
    $senderName = '',
7699
    $senderEmail = '',
7700
    $extra_headers = array(),
7701
    $data_file = array(),
7702
    $embedded_image = false,
7703
    $additionalParameters = array()
7704
) {
7705
    // Default values
7706
    $notification = new Notification();
7707
    $defaultEmail = $notification->getDefaultPlatformSenderEmail();
7708
    $defaultName = $notification->getDefaultPlatformSenderName();
7709
7710
    // If the parameter is set don't use the admin.
7711
    $senderName = !empty($senderName) ? $senderName : $defaultName;
7712
    $senderEmail = !empty($senderEmail) ? $senderEmail : $defaultEmail;
7713
7714
    $link = isset($additionalParameters['link']) ? $additionalParameters['link'] : '';
7715
7716
    $swiftMessage = \Swift_Message::newInstance()
7717
        ->setSubject($subject)
7718
        ->setFrom($senderEmail, $senderName)
0 ignored issues
show
Bug introduced by
It seems like $senderName defined by !empty($senderName) ? $senderName : $defaultName on line 7711 can also be of type boolean; however, Swift_Mime_SimpleMessage::setFrom() does only seem to accept string|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
7719
        ->setTo($recipient_email, $recipient_name)
7720
        ->setBody(
7721
            Container::getTemplating()->render(
7722
                'ChamiloCoreBundle:default/mail:mail.html.twig',
7723
                array('content' => $message, 'link' => $link)
7724
            ),
7725
            'text/html'
7726
        )/*
7727
         * If you also want to include a plaintext version of the message
7728
        ->addPart(
7729
            $this->renderView(
7730
                'Emails/registration.txt.twig',
7731
                array('name' => $name)
7732
            ),
7733
            'text/plain'
7734
        )
7735
        */
7736
    ;
7737
7738 View Code Duplication
    if (!empty($additionalParameters)) {
7739
        $plugin = new AppPlugin();
7740
        $smsPlugin = $plugin->getSMSPluginLibrary();
7741
        if ($smsPlugin) {
7742
            $smsPlugin->send($additionalParameters);
7743
        }
7744
    }
7745
7746
    Container::getMailer()->send($swiftMessage);
7747
7748
    return 1;
7749
7750
    global $platform_email;
0 ignored issues
show
Unused Code introduced by
global $platform_email; does not seem to be reachable.

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

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

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

    return false;
}

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

Loading history...
7751
7752
    $mail = new PHPMailer();
7753
    $mail->Mailer = $platform_email['SMTP_MAILER'];
7754
    $mail->Host = $platform_email['SMTP_HOST'];
7755
    $mail->Port = $platform_email['SMTP_PORT'];
7756
    $mail->CharSet = $platform_email['SMTP_CHARSET'];
7757
    // Stay far below SMTP protocol 980 chars limit.
7758
    $mail->WordWrap = 200;
7759
7760
    if ($platform_email['SMTP_AUTH']) {
7761
        $mail->SMTPAuth = 1;
7762
        $mail->Username = $platform_email['SMTP_USER'];
7763
        $mail->Password = $platform_email['SMTP_PASS'];
7764
        if (isset($platform_email['SMTP_SECURE'])) {
7765
            $mail->SMTPSecure = $platform_email['SMTP_SECURE'];
7766
        }
7767
    }
7768
    $mail->SMTPDebug = isset($platform_email['SMTP_DEBUG'])?$platform_email['SMTP_DEBUG']:0;
7769
7770
    // 5 = low, 1 = high
7771
    $mail->Priority = 3;
7772
    $mail->SMTPKeepAlive = true;
7773
7774
    // Default values
7775
    $notification = new Notification();
7776
    $defaultEmail = $notification->getDefaultPlatformSenderEmail();
7777
    $defaultName = $notification->getDefaultPlatformSenderName();
7778
7779
    // If the parameter is set don't use the admin.
7780
    $senderName = !empty($senderName) ? $senderName : $defaultName;
7781
    $senderEmail = !empty($senderEmail) ? $senderEmail : $defaultEmail;
7782
7783
    // Reply to first
7784
    if (isset($extra_headers['reply_to'])) {
7785
        $mail->AddReplyTo(
7786
            $extra_headers['reply_to']['mail'],
7787
            $extra_headers['reply_to']['name']
7788
        );
7789
            // Errors to sender
7790
        $mail->AddCustomHeader('Errors-To: '.$extra_headers['reply_to']['mail']);
7791
        $mail->Sender = $extra_headers['reply_to']['mail'];
7792
        unset($extra_headers['reply_to']);
7793
    } else {
7794
        $mail->AddCustomHeader('Errors-To: '.$defaultEmail);
7795
    }
7796
7797
    //If the SMTP configuration only accept one sender
7798
    if (isset($platform_email['SMTP_UNIQUE_SENDER']) && $platform_email['SMTP_UNIQUE_SENDER']) {
7799
        $senderName = $platform_email['SMTP_FROM_NAME'];
7800
        $senderEmail = $platform_email['SMTP_FROM_EMAIL'];
7801
    }
7802
    $mail->SetFrom($defaultEmail, $defaultName);
7803
    $mail->From = $defaultEmail;
7804
    $mail->Sender = $defaultEmail;
7805
    $mail->Subject = $subject;
7806
    $mail->AltBody = strip_tags(
7807
        str_replace('<br />', "\n", api_html_entity_decode($message))
7808
    );
7809
7810
    // Send embedded image.
7811
    if ($embedded_image) {
7812
        // Get all images html inside content.
7813
        preg_match_all("/<img\s+.*?src=[\"\']?([^\"\' >]*)[\"\']?[^>]*>/i", $message, $m);
7814
        // Prepare new tag images.
7815
        $new_images_html = array();
7816
        $i = 1;
7817
        if (!empty($m[1])) {
7818
            foreach ($m[1] as $image_path) {
7819
                $real_path = realpath($image_path);
7820
                $filename  = basename($image_path);
7821
                $image_cid = $filename.'_'.$i;
7822
                $encoding = 'base64';
7823
                $image_type = mime_content_type($real_path);
7824
                $mail->AddEmbeddedImage(
7825
                    $real_path,
7826
                    $image_cid,
7827
                    $filename,
7828
                    $encoding,
7829
                    $image_type
7830
                );
7831
                $new_images_html[] = '<img src="cid:'.$image_cid.'" />';
7832
                $i++;
7833
            }
7834
        }
7835
7836
        // Replace origin image for new embedded image html.
7837
        $x = 0;
7838
        if (!empty($m[0])) {
7839
            foreach ($m[0] as $orig_img) {
7840
                $message = str_replace($orig_img, $new_images_html[$x], $message);
7841
                $x++;
7842
            }
7843
        }
7844
    }
7845
7846
    $mailView = new Template(null, false, false, false, false, false, false);
7847
    $mailView->assign('content', $message);
7848
7849
    if (isset($additionalParameters['link'])) {
7850
        $mailView->assign('link', $additionalParameters['link']);
7851
    } else {
7852
        $mailView->assign('link', '');
7853
    }
7854
7855
    $layout = $mailView->get_template('mail/mail.tpl');
7856
    $mail->Body = $mailView->fetch($layout);
7857
7858
    // Attachment ...
7859
    if (!empty($data_file)) {
7860
        $o = 0;
7861
        foreach ($data_file as $file_attach) {
7862
            if (!empty($file_attach['path']) && !empty($file_attach['filename'])) {
7863
                $mail->AddAttachment($file_attach['path'], $file_attach['filename']);
7864
            }
7865
            $o++;
7866
        }
7867
    }
7868
7869
    // Only valid addresses are accepted.
7870
    if (is_array($recipient_email)) {
7871
        foreach ($recipient_email as $dest) {
7872
            if (api_valid_email($dest)) {
7873
                $mail->AddAddress($dest, $recipient_name);
7874
            }
7875
        }
7876
    } else {
7877
        if (api_valid_email($recipient_email)) {
7878
            $mail->AddAddress($recipient_email, $recipient_name);
7879
        } else {
7880
            return 0;
7881
        }
7882
    }
7883
7884
    if (is_array($extra_headers) && count($extra_headers) > 0) {
7885
        foreach ($extra_headers as $key => $value) {
7886
            switch (strtolower($key)) {
7887
                case 'encoding':
7888
                case 'content-transfer-encoding':
7889
                    $mail->Encoding = $value;
7890
                    break;
7891
                case 'charset':
7892
                    $mail->Charset = $value;
7893
                    break;
7894
                case 'contenttype':
7895
                case 'content-type':
7896
                    $mail->ContentType = $value;
7897
                    break;
7898
                default:
7899
                    $mail->AddCustomHeader($key.':'.$value);
7900
                    break;
7901
            }
7902
        }
7903
    } else {
7904
        if (!empty($extra_headers)) {
7905
            $mail->AddCustomHeader($extra_headers);
7906
        }
7907
    }
7908
7909
    // WordWrap the html body (phpMailer only fixes AltBody) FS#2988
7910
    $mail->Body = $mail->WrapText($mail->Body, $mail->WordWrap);
7911
7912
    // Send the mail message.
7913
    if (!$mail->Send()) {
7914
        error_log('ERROR: mail not sent to '.$recipient_name.' ('.$recipient_email.') because of '.$mail->ErrorInfo.'<br />');
7915
        if ($mail->SMTPDebug) {
7916
            error_log(
7917
                "Connection details :: " .
7918
                "Protocol: " . $mail->Mailer . ' :: ' .
7919
                "Host/Port: " . $mail->Host . ':' . $mail->Port . ' :: ' .
7920
                "Authent/Open: " . ($mail->SMTPAuth?'Authent':'Open') . ' :: ' .
7921
                ($mail->SMTPAuth?"  User/Pass: " . $mail->Username . ':' . $mail->Password:'')
7922
            );
7923
        }
7924
        return 0;
7925
    }
7926
7927 View Code Duplication
    if (!empty($additionalParameters)) {
7928
        $plugin = new AppPlugin();
7929
        $smsPlugin = $plugin->getSMSPluginLibrary();
7930
        if ($smsPlugin) {
7931
            $smsPlugin->send($additionalParameters);
7932
        }
7933
    }
7934
7935
    // Clear all the addresses.
7936
    $mail->ClearAddresses();
7937
7938
    // Clear all attachments
7939
    $mail->ClearAttachments();
7940
7941
    return 1;
7942
}
7943
7944
/**
7945
 * @param string $tool Possible values:
7946
 * GroupManager::GROUP_TOOL_*
7947
 *
7948
 */
7949
function api_protect_course_group($tool, $showHeader = true)
7950
{
7951
    $userId = api_get_user_id();
7952
    $groupId = api_get_group_id();
7953
    $groupInfo = GroupManager::get_group_properties($groupId);
7954
7955
    if (!empty($groupInfo)) {
7956
        $allow = GroupManager::user_has_access(
7957
            $userId,
7958
            $groupInfo['iid'],
7959
            $tool
7960
        );
7961
7962
        if (!$allow) {
7963
            api_not_allowed($showHeader);
7964
        }
7965
    }
7966
}
7967
7968
/**
7969
 * Check if a date is in a date range
7970
 *
7971
 * @param datetime $startDate
7972
 * @param datetime $endDate
7973
 * @param datetime $currentDate
7974
 * @return bool true if date is in rage, false otherwise
7975
 */
7976
function api_is_date_in_date_range($startDate, $endDate, $currentDate = null)
7977
{
7978
    $startDate = strtotime(api_get_local_time($startDate));
7979
    $endDate = strtotime(api_get_local_time($endDate));
7980
    $currentDate = strtotime(api_get_local_time($currentDate));
7981
7982
    if ($currentDate >= $startDate && $currentDate <= $endDate) {
7983
        return true;
7984
    }
7985
7986
    return false;
7987
}
7988
7989
/**
7990
 * Eliminate the duplicates of a multidimensional array by sending the key
7991
 *
7992
 * @param array $array multidimensional array
7993
 * @param int $key key to find to compare
7994
 * @return array
7995
 *
7996
 */
7997
function api_unique_multidim_array($array, $key){
7998
    $temp_array = [];
7999
    $i = 0;
8000
    $key_array = [];
8001
8002
    foreach($array as $val){
8003
        if(!in_array($val[$key],$key_array)){
8004
            $key_array[$i] = $val[$key];
8005
            $temp_array[$i] = $val;
8006
        }
8007
        $i++;
8008
    }
8009
    return $temp_array;
8010
}
8011
8012
/**
8013
 * Limit the access to Session Admins wheen the limit_session_admin_role
8014
 * configuration variable is set to true
8015
 */
8016
function api_protect_limit_for_session_admin()
8017
{
8018
    $limitAdmin = api_get_setting('limit_session_admin_role');
8019
    if (api_is_session_admin() && $limitAdmin === 'true') {
8020
        api_not_allowed(true);
8021
    }
8022
}
8023
8024
function api_is_student_view_active() {
8025
    $studentView = Session::read('studentview');
8026
    return $studentView == 'studentview';
8027
}
8028
8029
/**
8030
 * Adds a file inside the upload/$type/id
8031
 *
8032
 * @param string $type
8033
 * @param array $file
8034
 * @param int $itemId
8035
 * @param string $cropParameters
8036
 * @return array|bool
8037
 */
8038
function api_upload_file($type, $file, $itemId, $cropParameters = '')
8039
{
8040
    $upload = process_uploaded_file($file);
8041
    if ($upload) {
8042
        $name = api_replace_dangerous_char($file['name']);
8043
8044
        // No "dangerous" files
8045
        $name = disable_dangerous_file($name);
8046
8047
        $pathId = '/'.substr((string)$itemId, 0, 1).'/'.$itemId.'/';
8048
        $path = api_get_path(SYS_UPLOAD_PATH).$type.$pathId;
8049
8050
        if (!is_dir($path)) {
8051
            mkdir($path, api_get_permissions_for_new_directories(), true);
8052
        }
8053
8054
        $pathToSave = $path.$name;
8055
8056
        $result = move_uploaded_file($file['tmp_name'], $pathToSave);
8057
        if ($result) {
8058
            if (!empty($cropParameters)) {
8059
                $image = new Image($pathToSave);
8060
                $image->crop($cropParameters);
8061
            }
8062
8063
            return ['path_to_save' => $pathId.$name];
8064
        }
8065
        return false;
8066
    }
8067
}
8068
8069
/**
8070
 * @param string $type
8071
 * @param string $file
8072
 */
8073
function api_remove_uploaded_file($type, $file)
8074
{
8075
    $path = api_get_path(SYS_UPLOAD_PATH).$type.'/'.$file;
8076
    if (file_exists($path)) {
8077
        unlink($path);
8078
    }
8079
}
8080
8081
8082