Completed
Push — master ( 81a867...33ec7a )
by Julito
33:04
created

api.lib.php ➔ api_get_js_epiclock()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 7
nc 1
nop 0
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use ChamiloSession as Session;
5
use Chamilo\CourseBundle\Entity\CItemProperty;
6
use Symfony\Component\Validator\Constraints as Assert;
7
use Chamilo\UserBundle\Entity\User;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, User.

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

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

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

// Bar.php
namespace OtherDir;

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

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

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

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

// Bar.php
namespace OtherDir;

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