Completed
Push — master ( f5c42a...6861f5 )
by Julito
75:53 queued 27:38
created

api.lib.php ➔ api_get_user_course_entity()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 7
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
/**
623
 * Inclusion of internationalization libraries
624
 */
625
require_once __DIR__.'/internationalization.lib.php';
626
627
/**
628
 * Returns a path to a certain resource within the Chamilo area, specifyed through a parameter.
629
 * Also, this function provides conversion between path types, in this case the input path points inside the Chamilo area too.
630
 *
631
 * See $_configuration['course_folder'] in the configuration.php to alter the WEB_COURSE_PATH and SYS_COURSE_PATH parameters.
632
633
 * @param string $path (optional)   A path which type is to be converted. Also, it may be a defined constant for a path.
634
 * This parameter has meaning when $type parameter has one of the following values: TO_WEB, TO_SYS, TO_REL. Otherwise it is ignored.
635
 * @return string                   The requested path or the converted path.
636
 *
637
 *
638
 * Notes about the current behaviour model:
639
 * 1. Windows back-slashes are converted to slashes in the result.
640
 * 2. A semi-absolute web-path is detected by its leading slash. On Linux systems, absolute system paths start with
641
 * a slash too, so an additional check about presence of leading system server base is implemented. For example, the function is
642
 * able to distinguish type difference between /var/www/chamilo/courses/ (SYS) and /chamilo/courses/ (REL).
643
 * 3. The function api_get_path() returns only these three types of paths, which in some sense are absolute. The function has
644
 * no a mechanism for processing relative web/system paths, such as: lesson01.html, ./lesson01.html, ../css/my_styles.css.
645
 * It has not been identified as needed yet.
646
 * 4. Also, resolving the meta-symbols "." and ".." within paths has not been implemented, it is to be identified as needed.
647
 *
648
 * For examples go to: *
649
 * See main/admin/system_status.php?section=paths
650
 *
651
 * Vchamilo changes : allow using an alternate configuration
652
 * to get vchamilo  instance paths
653
*/
654
function api_get_path($path = '', $configuration = [])
655
{
656
    global $paths;
657
658
    // get proper configuration data if exists
659
    global $_configuration;
660
661
    if (empty($configuration)) {
662
        $configuration = (array) $_configuration;
663
    }
664
665
    $course_folder = 'courses/';
666
    $root_sys = $_configuration['root_sys'];
667
668
    // Resolve master hostname.
669
    if (!empty($configuration) && array_key_exists('root_web', $configuration)) {
670
        $root_web = $configuration['root_web'];
671
    } else {
672
        $root_web = '';
673
        // Try guess it from server.
674
        if (defined('SYSTEM_INSTALLATION') && SYSTEM_INSTALLATION) {
675
            if (($pos = strpos(($requested_page_rel = api_get_self()), 'main/install')) !== false) {
676
                $root_rel = substr($requested_page_rel, 0, $pos);
677
                // See http://www.mediawiki.org/wiki/Manual:$wgServer
678
                $server_protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
679
                $server_name =
680
                    isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME']
681
                    : (isset($_SERVER['HOSTNAME']) ? $_SERVER['HOSTNAME']
682
                    : (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST']
683
                    : (isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR']
684
                    : 'localhost')));
685
                if (isset($_SERVER['SERVER_PORT']) && !strpos($server_name, ':')
686
                    && (($server_protocol == 'http'
687
                    && $_SERVER['SERVER_PORT'] != 80 ) || ($server_protocol == 'https' && $_SERVER['SERVER_PORT'] != 443 ))) {
688
                    $server_name .= ":" . $_SERVER['SERVER_PORT'];
689
                }
690
                $root_web = $server_protocol.'://'.$server_name.$root_rel;
691
                $root_sys = str_replace('\\', '/', realpath(__DIR__.'/../../../')).'/';
692
            }
693
            // Here we give up, so we don't touch anything.
694
        }
695
    }
696
697
    if (isset($configuration['multiple_access_urls']) && $configuration['multiple_access_urls']) {
698
        // To avoid that the api_get_access_url() function fails since global.inc.php also calls the main_api.lib.php
699
        if (isset($configuration['access_url']) && !empty($configuration['access_url'])) {
700
            // We look into the DB the function api_get_access_url
701
            $url_info = api_get_access_url($configuration['access_url']);
702
            // Avoid default value
703
            $defaulValues = ['http://localhost/', 'https://localhost/'];
704
            if (!empty($url_info['url']) && !in_array($url_info['url'], $defaulValues)) {
705
                $root_web = $url_info['active'] == 1 ? $url_info['url'] : $configuration['root_web'];
706
            }
707
        }
708
    }
709
710
    if (empty($paths)) {
711
        $paths = [];
712
    }
713
714
    $paths = [];
715
    // Initialise cache with default values.
716
    if (!array_key_exists($root_web, $paths)) {
717
        $paths[$root_web] = array(
718
            WEB_PATH => '',
719
            SYS_PATH => '',
720
            REL_PATH => '',
721
            WEB_COURSE_PATH => '',
722
            SYS_COURSE_PATH => '',
723
            REL_COURSE_PATH => '',
724
            WEB_CODE_PATH => 'main/',
725
            SYS_CODE_PATH => 'main/',
726
            REL_CODE_PATH => '/main/',
727
            SYS_LANG_PATH => 'lang/',
728
            WEB_IMG_PATH => 'img/',
729
            WEB_CSS_PATH => 'web/css/',
730
            SYS_CSS_PATH => 'app/Resources/public/css/',
731
            SYS_PLUGIN_PATH => 'plugin/',
732
            WEB_PLUGIN_PATH => 'plugin/',
733
            SYS_ARCHIVE_PATH => 'app/cache/',
734
            WEB_ARCHIVE_PATH => 'app/cache/',
735
            SYS_HOME_PATH => 'app/home/',
736
            WEB_HOME_PATH => 'app/home/',
737
            REL_HOME_PATH => 'app/home/',
738
            SYS_APP_PATH => 'app/',
739
            WEB_APP_PATH => 'app/',
740
            SYS_UPLOAD_PATH => 'app/upload/',
741
            SYS_INC_PATH => 'inc/',
742
            CONFIGURATION_PATH => 'app/config/',
743
            LIBRARY_PATH => 'inc/lib/',
744
            WEB_LIBRARY_PATH => 'inc/lib/',
745
            WEB_LIBRARY_JS_PATH => 'inc/lib/javascript/',
746
            WEB_AJAX_PATH => 'inc/ajax/',
747
            SYS_TEST_PATH => 'tests/',
748
            WEB_TEMPLATE_PATH => 'template/',
749
            SYS_TEMPLATE_PATH => 'template/',
750
            WEB_UPLOAD_PATH => 'app/upload/',
751
            WEB_PUBLIC_PATH => 'web/',
752
            SYS_PUBLIC_PATH => 'web/',
753
            WEB_FONTS_PATH => 'fonts/',
754
            SYS_FONTS_PATH => 'fonts/',
755
        );
756
    }
757
758
    $isInitialized = [];
759
    $course_folder = isset($configuration['course_folder']) ? $configuration['course_folder'] : $course_folder;
760
    $root_rel = isset($configuration['url_append']) ? $configuration['url_append'] : '';
761
762
    // Web server base and system server base.
763
    if (!array_key_exists($root_web, $isInitialized)) {
764
        // process absolute global roots
765
        if (!empty($configuration)) {
766
            $code_folder = 'main';
767
        } else {
768
            $code_folder = $paths[$root_web][REL_CODE_PATH];
769
        }
770
771
        // Support for the installation process.
772
        // Developers might use the function api_get_path() directly or indirectly (this is difficult to be traced), at the moment when
773
        // configuration has not been created yet. This is why this function should be upgraded to return correct results in this case.
774
775
        // Dealing with trailing slashes.
776
        $slashed_root_web = api_add_trailing_slash($root_web);
777
        $root_sys = api_add_trailing_slash($root_sys);
778
        $root_rel = api_add_trailing_slash($root_rel);
779
        $code_folder = api_add_trailing_slash($code_folder);
780
        $course_folder = api_add_trailing_slash($course_folder);
781
782
        // Initialization of a table that contains common-purpose paths.
783
        $paths[$root_web][REL_PATH] = $root_rel;
784
        $paths[$root_web][REL_COURSE_PATH] = $root_rel.$course_folder;
785
        $paths[$root_web][REL_DEFAULT_COURSE_DOCUMENT_PATH] = $paths[$root_web][REL_PATH].'main/default_course_document/';
786
787
        $paths[$root_web][WEB_PATH] = $slashed_root_web;
788
        $paths[$root_web][WEB_CODE_PATH] = $paths[$root_web][WEB_PATH].$code_folder;
789
        $paths[$root_web][WEB_COURSE_PATH] = $paths[$root_web][WEB_PATH].$course_folder;
790
        $paths[$root_web][WEB_DEFAULT_COURSE_DOCUMENT_PATH] = $paths[$root_web][WEB_CODE_PATH].'default_course_document/';
791
        $paths[$root_web][WEB_APP_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_APP_PATH];
792
        $paths[$root_web][WEB_PLUGIN_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_PLUGIN_PATH];
793
        $paths[$root_web][WEB_ARCHIVE_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_ARCHIVE_PATH];
794
795
        $paths[$root_web][WEB_CSS_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_CSS_PATH];
796
        $paths[$root_web][WEB_IMG_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_IMG_PATH];
797
        $paths[$root_web][WEB_LIBRARY_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_LIBRARY_PATH];
798
        $paths[$root_web][WEB_LIBRARY_JS_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_LIBRARY_JS_PATH];
799
        $paths[$root_web][WEB_AJAX_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_AJAX_PATH];
800
        $paths[$root_web][WEB_FONTS_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_FONTS_PATH];
801
        $paths[$root_web][WEB_TEMPLATE_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_TEMPLATE_PATH];
802
        $paths[$root_web][WEB_UPLOAD_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_UPLOAD_PATH];
803
        $paths[$root_web][WEB_PUBLIC_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_PUBLIC_PATH];
804
        $paths[$root_web][WEB_HOME_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][REL_HOME_PATH];
805
806
        $paths[$root_web][SYS_PATH] = $root_sys;
807
        $paths[$root_web][SYS_CODE_PATH] = $root_sys.$code_folder;
808
        $paths[$root_web][SYS_TEST_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_TEST_PATH];
809
        $paths[$root_web][SYS_TEMPLATE_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_TEMPLATE_PATH];
810
        $paths[$root_web][SYS_PUBLIC_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_PUBLIC_PATH];
811
        $paths[$root_web][SYS_CSS_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_CSS_PATH];
812
        $paths[$root_web][SYS_FONTS_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_FONTS_PATH];
813
        $paths[$root_web][SYS_ARCHIVE_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_ARCHIVE_PATH];
814
        $paths[$root_web][SYS_APP_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_APP_PATH];
815
        $paths[$root_web][SYS_COURSE_PATH] = $paths[$root_web][SYS_APP_PATH].$course_folder;
816
        $paths[$root_web][SYS_UPLOAD_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_UPLOAD_PATH];
817
        $paths[$root_web][SYS_LANG_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_LANG_PATH];
818
        $paths[$root_web][SYS_HOME_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_HOME_PATH];
819
        $paths[$root_web][SYS_PLUGIN_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_PLUGIN_PATH];
820
        $paths[$root_web][SYS_INC_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_INC_PATH];
821
822
        $paths[$root_web][LIBRARY_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][LIBRARY_PATH];
823
        $paths[$root_web][CONFIGURATION_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][CONFIGURATION_PATH];
824
825
        global $virtualChamilo;
826
        if (!empty($virtualChamilo)) {
827
            $paths[$root_web][SYS_ARCHIVE_PATH] = $virtualChamilo[SYS_ARCHIVE_PATH].'/';
828
            $paths[$root_web][SYS_HOME_PATH] = $virtualChamilo[SYS_HOME_PATH].'/';
829
            $paths[$root_web][SYS_COURSE_PATH] = $virtualChamilo[SYS_COURSE_PATH].'/';
830
            $paths[$root_web][SYS_UPLOAD_PATH] = $virtualChamilo[SYS_UPLOAD_PATH].'/';
831
        }
832
833
        $isInitialized[$root_web] = true;
834
    }
835
836
    $path = trim($path);
837
838
    // Retrieving a common-purpose path.
839
    if (isset($paths[$root_web][$path])) {
840
        return $paths[$root_web][$path];
841
    }
842
843
    // Second purification.
844
845
    // Replacing Windows back slashes.
846
    $path = str_replace('\\', '/', $path);
847
    // Query strings sometimes mighth wrongly appear in non-URLs.
848
    // Let us check remove them from all types of paths.
849
    if (($pos = strpos($path, '?')) !== false) {
850
        $path = substr($path, 0, $pos);
851
    }
852
853
    // Detection of the input path type. Conversion to semi-absolute type ( /chamilo/main/inc/.... ).
854
855
    if (preg_match(VALID_WEB_PATH, $path)) {
856
        // A special case: When a URL points to the document download script directly, without
857
        // mod-rewrite translation, we have to translate it into an "ordinary" web path.
858
        // For example:
859
        // http://localhost/chamilo/main/document/download.php?doc_url=/image.png&cDir=/
860
        // becomes
861
        // http://localhost/chamilo/courses/TEST/document/image.png
862
        // TEST is a course directory name, so called "system course code".
863
        if (strpos($path, 'download.php') !== false) { // Fast detection first.
864
            $path = urldecode($path);
865
            if (preg_match('/(.*)main\/document\/download.php\?doc_url=\/(.*)&cDir=\/(.*)?/', $path, $matches)) {
866
                $sys_course_code =
867
                    isset($_SESSION['_course']['sysCode'])  // User is inside a course?
868
                        ? $_SESSION['_course']['sysCode']   // Yes, then use course's directory name.
869
                        : '{SYS_COURSE_CODE}';              // No, then use a fake code, it may be processed later.
870
                $path = $matches[1].'courses/'.$sys_course_code.'/document/'.str_replace('//', '/', $matches[3].'/'.$matches[2]);
871
            }
872
        }
873
        // Replacement of the present web server base with a slash '/'.
874
        $path = preg_replace(VALID_WEB_SERVER_BASE, '/', $path);
875
    }
876
877
    // Path now is semi-absolute. It is convenient at this moment repeated slashes to be removed.
878
    $path = preg_replace(REPEATED_SLASHES_PURIFIER, '/', $path);
879
880
    return $path;
881
}
882
883
/**
884
 * Gets a modified version of the path for the CDN, if defined in
885
 * configuration.php
886
 * @param string $web_path The path of the resource without CDN
887
 * @return string The path of the resource converted to CDN
888
 * @author Yannick Warnier <[email protected]>
889
 */
890
function api_get_cdn_path($web_path)
891
{
892
    global $_configuration;
893
    $web_root = api_get_path(WEB_PATH);
894
    $ext = substr($web_path,strrpos($web_path,'.'));
895
    if (isset($ext[2])) { // faster version of strlen to check if len>2
896
        // Check for CDN definitions
897
        if (!empty($_configuration['cdn_enable']) && !empty($ext)) {
898
            foreach ($_configuration['cdn'] as $host => $exts) {
899
                if (in_array($ext,$exts)) {
900
                    //Use host as defined in $_configuration['cdn'], without
901
                    // trailing slash
902
                    return str_replace($web_root,$host.'/',$web_path);
903
                }
904
            }
905
        }
906
    }
907
    return $web_path;
908
}
909
910
/**
911
 * @return bool Return true if CAS authentification is activated
912
 *
913
 */
914
function api_is_cas_activated() {
915
    return api_get_setting('cas_activate') == "true";
916
}
917
918
/**
919
 * @return bool     Return true if LDAP authentification is activated
920
 *
921
 */
922
function api_is_ldap_activated() {
923
    global $extAuthSource;
924
    return is_array($extAuthSource[LDAP_AUTH_SOURCE]);
925
}
926
927
/**
928
 * @return bool     Return true if Facebook authentification is activated
929
 *
930
 */
931
function api_is_facebook_auth_activated() {
932
    global $_configuration;
933
    return (isset($_configuration['facebook_auth']) && $_configuration['facebook_auth'] == 1);
934
}
935
936
/**
937
 * This function checks whether a given path points inside the system.
938
 * @param string $path      The path to be tested.
939
 * It should be full path, web-absolute (WEB), semi-absolute (REL) or system-absolyte (SYS).
940
 * @return bool             Returns true when the given path is inside the system, false otherwise.
941
 */
942
function api_is_internal_path($path) {
943
    $path = str_replace('\\', '/', trim($path));
944
    if (empty($path)) {
945
        return false;
946
    }
947
    if (strpos($path, api_remove_trailing_slash(api_get_path(WEB_PATH))) === 0) {
948
        return true;
949
    }
950
    if (strpos($path, api_remove_trailing_slash(api_get_path(SYS_PATH))) === 0) {
951
        return true;
952
    }
953
    $server_base_web = api_remove_trailing_slash(api_get_path(REL_PATH));
954
    $server_base_web = empty($server_base_web) ? '/' : $server_base_web;
955
    if (strpos($path, $server_base_web) === 0) {
956
        return true;
957
    }
958
    return false;
959
}
960
961
/**
962
 * Adds to a given path a trailing slash if it is necessary (adds "/" character at the end of the string).
963
 * @param string $path          The input path.
964
 * @return string               Returns the modified path.
965
 */
966
function api_add_trailing_slash($path) {
967
    return substr($path, -1) == '/' ? $path : $path.'/';
968
}
969
970
/**
971
 * Removes from a given path the trailing slash if it is necessary (removes "/" character from the end of the string).
972
 * @param string $path          The input path.
973
 * @return string               Returns the modified path.
974
 */
975
function api_remove_trailing_slash($path) {
976
    return substr($path, -1) == '/' ? substr($path, 0, -1) : $path;
977
}
978
979
/**
980
 * Checks the RFC 3986 syntax of a given URL.
981
 * @param string $url       The URL to be checked.
982
 * @param bool $absolute    Whether the URL is absolute (beginning with a scheme such as "http:").
983
 * @return string|false             Returns the URL if it is valid, FALSE otherwise.
984
 * This function is an adaptation from the function valid_url(), Drupal CMS.
985
 * @link http://drupal.org
986
 * Note: The built-in function filter_var($urs, FILTER_VALIDATE_URL) has a bug for some versions of PHP.
987
 * @link http://bugs.php.net/51192
988
 */
989
function api_valid_url($url, $absolute = false) {
990
    if ($absolute) {
991
        if (preg_match("
992
            /^                                                      # Start at the beginning of the text
993
            (?:ftp|https?|feed):\/\/                                # Look for ftp, http, https or feed schemes
994
            (?:                                                     # Userinfo (optional) which is typically
995
                (?:(?:[\w\.\-\+!$&'\(\)*\+,;=]|%[0-9a-f]{2})+:)*    # a username or a username and password
996
                (?:[\w\.\-\+%!$&'\(\)*\+,;=]|%[0-9a-f]{2})+@        # combination
997
            )?
998
            (?:
999
                (?:[a-z0-9\-\.]|%[0-9a-f]{2})+                      # A domain name or a IPv4 address
1000
                |(?:\[(?:[0-9a-f]{0,4}:)*(?:[0-9a-f]{0,4})\])       # or a well formed IPv6 address
1001
            )
1002
            (?::[0-9]+)?                                            # Server port number (optional)
1003
            (?:[\/|\?]
1004
                (?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2}) # The path and query (optional)
1005
            *)?
1006
            $/xi", $url)) {
1007
            return $url;
1008
        }
1009
        return false;
1010
    } else {
1011
        return preg_match("/^(?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2})+$/i", $url) ? $url : false;
1012
    }
1013
}
1014
1015
/**
1016
 * Checks whether a given string looks roughly like an email address.
1017
 *
1018
 * @param string $address   The e-mail address to be checked.
1019
 * @return mixed            Returns the e-mail if it is valid, FALSE otherwise.
1020
 */
1021
function api_valid_email($address)
1022
{
1023
    return filter_var($address, FILTER_VALIDATE_EMAIL);
1024
}
1025
1026
/* PROTECTION FUNCTIONS
1027
   Use these functions to protect your scripts. */
1028
1029
/**
1030
 * Function used to protect a course script.
1031
 * The function blocks access when
1032
 * - there is no $_SESSION["_course"] defined; or
1033
 * - $is_allowed_in_course is set to false (this depends on the course
1034
 * visibility and user status).
1035
 *
1036
 * This is only the first proposal, test and improve!
1037
 * @param boolean       Option to print headers when displaying error message. Default: false
1038
 * @param boolean       Whether session admins should be allowed or not.
1039
 * @return boolean      True if the user has access to the current course or is out of a course context, false otherwise
1040
 * @todo replace global variable
1041
 * @author Roan Embrechts
1042
 */
1043
function api_protect_course_script($print_headers = false, $allow_session_admins = false, $allow_drh = false)
1044
{
1045
    $is_allowed_in_course = api_is_allowed_in_course();
1046
1047
    $is_visible = false;
1048
    $course_info = api_get_course_info();
1049
1050
    if (empty($course_info)) {
1051
        api_not_allowed($print_headers);
1052
        return false;
1053
    }
1054
1055
    if (api_is_drh()) {
1056
        return true;
1057
    }
1058
1059
    if (api_is_platform_admin($allow_session_admins)) {
1060
        return true;
1061
    }
1062
1063
    if (isset($course_info) && isset($course_info['visibility'])) {
1064
        switch ($course_info['visibility']) {
1065
            default:
1066 View Code Duplication
            case COURSE_VISIBILITY_CLOSED:
1067
                // Completely closed: the course is only accessible to the teachers. - 0
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_REGISTERED:
1073
                // Private - access authorized to course members only - 1
1074
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1075
                    $is_visible = true;
1076
                }
1077
                break;
1078 View Code Duplication
            case COURSE_VISIBILITY_OPEN_PLATFORM:
1079
                // Open - access allowed for users registered on the platform - 2
1080
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1081
                    $is_visible = true;
1082
                }
1083
                break;
1084
            case COURSE_VISIBILITY_OPEN_WORLD:
1085
                //Open - access allowed for the whole world - 3
1086
                $is_visible = true;
1087
                break;
1088
            case COURSE_VISIBILITY_HIDDEN:
1089
                //Completely closed: the course is only accessible to the teachers. - 0
1090
                if (api_is_platform_admin()) {
1091
                    $is_visible = true;
1092
                }
1093
                break;
1094
        }
1095
1096
        //If password is set and user is not registered to the course then the course is not visible
1097
        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...
1098
            isset($course_info['registration_code']) &&
1099
            !empty($course_info['registration_code'])
1100
        ) {
1101
            $is_visible = false;
1102
        }
1103
    }
1104
1105
    // Check session visibility
1106
    $session_id = api_get_session_id();
1107
1108
    if (!empty($session_id)) {
1109
        //$is_allowed_in_course was set in local.inc.php
1110
        if (!$is_allowed_in_course) {
1111
            $is_visible = false;
1112
        }
1113
    }
1114
1115
    if (!$is_visible) {
1116
        api_not_allowed($print_headers);
1117
        return false;
1118
    }
1119
    return true;
1120
}
1121
1122
/**
1123
 * Function used to protect an admin script.
1124
 *
1125
 * The function blocks access when the user has no platform admin rights
1126
 * with an error message printed on default output
1127
 * @param bool Whether to allow session admins as well
1128
 * @param bool Whether to allow HR directors as well
1129
 * @param string An optional message (already passed through get_lang)
1130
 * @return bool True if user is allowed, false otherwise.
1131
 * The function also outputs an error message in case not allowed
1132
 * @author Roan Embrechts (original author)
1133
 */
1134
function api_protect_admin_script($allow_sessions_admins = false, $allow_drh = false, $message = null)
1135
{
1136
    if (!api_is_platform_admin($allow_sessions_admins, $allow_drh)) {
1137
        api_not_allowed(true, $message);
1138
        return false;
1139
    }
1140
    return true;
1141
}
1142
1143
/**
1144
 * Function used to protect a teacher script.
1145
 * The function blocks access when the user has no teacher rights.
1146
 *
1147
 * @author Yoselyn Castillo
1148
 */
1149
function api_protect_teacher_script($allow_sessions_admins = false)
1150
{
1151
    if (!api_is_allowed_to_edit()) {
1152
        api_not_allowed(true);
1153
        return false;
1154
    }
1155
    return true;
1156
}
1157
1158
/**
1159
 * Function used to prevent anonymous users from accessing a script.
1160
 * @param bool|true $printHeaders
1161
 * @author Roan Embrechts
1162
 *
1163
 * @return bool
1164
 */
1165
function api_block_anonymous_users($printHeaders = true)
1166
{
1167
    $user = api_get_user_info();
1168 View Code Duplication
    if (!(isset($user['user_id']) && $user['user_id']) || api_is_anonymous($user['user_id'], true)) {
1169
        api_not_allowed($printHeaders);
1170
        return false;
1171
    }
1172
1173
    return true;
1174
}
1175
1176
/**
1177
 * @return array with the navigator name and version
1178
 */
1179
function api_get_navigator() {
1180
    $navigator = 'Unknown';
1181
    $version = 0;
1182
1183
    if (!isset($_SERVER['HTTP_USER_AGENT'])) {
1184
        return array('name' => 'Unknown', 'version' => '0.0.0');
1185
    }
1186
1187
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') !== false) {
1188
        $navigator = 'Opera';
1189
        list (, $version) = explode('Opera', $_SERVER['HTTP_USER_AGENT']);
1190 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {
1191
        $navigator = 'Internet Explorer';
1192
        list (, $version) = explode('MSIE', $_SERVER['HTTP_USER_AGENT']);
1193
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome') !== false) {
1194
        $navigator = 'Chrome';
1195
        list (, $version) = explode('Chrome', $_SERVER['HTTP_USER_AGENT']);
1196 View Code Duplication
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'safari') !== false) {
1197
        $navigator = 'Safari';
1198
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1199
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Gecko') !== false) {
1200
        $navigator = 'Mozilla';
1201
        list (, $version) = explode('; rv:', $_SERVER['HTTP_USER_AGENT']);
1202 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Netscape') !== false) {
1203
        $navigator = 'Netscape';
1204
        list (, $version) = explode('Netscape', $_SERVER['HTTP_USER_AGENT']);
1205
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Konqueror') !== false) {
1206
        $navigator = 'Konqueror';
1207
        list (, $version) = explode('Konqueror', $_SERVER['HTTP_USER_AGENT']);
1208 View Code Duplication
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'applewebkit') !== false) {
1209
        $navigator = 'AppleWebKit';
1210
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1211
    }
1212
    $version = str_replace('/', '', $version);
1213
    if (strpos($version, '.') === false) {
1214
        $version = number_format(doubleval($version), 1);
1215
    }
1216
    $return = array('name' => $navigator, 'version' => $version);
1217
    return $return;
1218
}
1219
1220
/**
1221
 * @return True if user self registration is allowed, false otherwise.
1222
 */
1223
function api_is_self_registration_allowed()
1224
{
1225
    return isset($GLOBALS['allowSelfReg']) ? $GLOBALS['allowSelfReg'] : false;
1226
}
1227
1228
/**
1229
 * This function returns the id of the user which is stored in the $_user array.
1230
 *
1231
 * example: The function can be used to check if a user is logged in
1232
 *          if (api_get_user_id())
1233
 * @return integer the id of the current user, 0 if is empty
1234
 */
1235
function api_get_user_id()
1236
{
1237
    $userInfo = Session::read('_user');
1238
    if ($userInfo && isset($userInfo['user_id'])) {
1239
        return $userInfo['user_id'];
1240
    }
1241
    return 0;
1242
}
1243
1244
/**
1245
 * Gets the list of courses a specific user is subscribed to
1246
 * @param int       User ID
1247
 * @param boolean   $fetch_session Whether to get session courses or not - NOT YET IMPLEMENTED
1248
 * @return array    Array of courses in the form [0]=>('code'=>xxx,'db'=>xxx,'dir'=>xxx,'status'=>d)
1249
 */
1250
function api_get_user_courses($userid, $fetch_session = true)
1251
{
1252
    // Get out if not integer
1253
    if ($userid != strval(intval($userid))) {
1254
        return array();
1255
    }
1256
1257
    $t_course = Database::get_main_table(TABLE_MAIN_COURSE);
1258
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1259
1260
    $sql = "SELECT cc.id as real_id, cc.code code, cc.directory dir, cu.status status
1261
            FROM    $t_course       cc,
1262
                    $t_course_user   cu
1263
            WHERE
1264
                cc.id = cu.c_id AND
1265
                cu.user_id = '".$userid."' AND
1266
                cu.relation_type<>".COURSE_RELATION_TYPE_RRHH." ";
1267
    $result = Database::query($sql);
1268
    if ($result === false) {
1269
        return array();
1270
    }
1271
1272
    $courses = array();
1273
    while ($row = Database::fetch_array($result)) {
1274
        // we only need the database name of the course
1275
        $courses[] = $row;
1276
    }
1277
1278
    return $courses;
1279
}
1280
1281
/**
1282
 * Formats user information into a standard array
1283
 * This function should be only used inside api_get_user_info()
1284
 *
1285
 * @param array Non-standard user array
1286
 * @param bool $add_password
1287
 *
1288
 * @return array Standard user array
1289
 */
1290
function _api_format_user($user, $add_password = false)
1291
{
1292
    $result = array();
1293
1294
    $firstname = null;
1295
    $lastname = null;
1296
    if (isset($user['firstname']) && isset($user['lastname'])) {
1297
        $firstname = $user['firstname'];
1298
        $lastname = $user['lastname'];
1299
    } elseif (isset($user['firstName']) && isset($user['lastName'])) {
1300
        $firstname = isset($user['firstName']) ? $user['firstName'] : null;
1301
        $lastname = isset($user['lastName']) ? $user['lastName'] : null;
1302
    }
1303
1304
    $result['complete_name'] = api_get_person_name($firstname, $lastname);
1305
1306
    $result['complete_name_with_username'] = $result['complete_name'];
1307
1308
    if (!empty($user['username'])) {
1309
        $result['complete_name_with_username'] = $result['complete_name'].' ('.$user['username'].')';
1310
    }
1311
1312
    $result['firstname'] = $firstname;
1313
    $result['lastname'] = $lastname;
1314
1315
    // Kept for historical reasons
1316
    $result['firstName'] = $firstname;
1317
    $result['lastName'] = $lastname;
1318
1319
    $attributes = array(
1320
        'phone',
1321
        'address',
1322
        'picture_uri',
1323
        'official_code',
1324
        'status',
1325
        'active',
1326
        'auth_source',
1327
        'username',
1328
        'theme',
1329
        'language',
1330
        'creator_id',
1331
        'registration_date',
1332
        'hr_dept_id',
1333
        'expiration_date',
1334
        'last_login'
1335
    );
1336
    if (api_get_setting('extended_profile') === 'true') {
1337
        $attributes[] = 'competences';
1338
        $attributes[] = 'diplomas';
1339
        $attributes[] = 'teach';
1340
        $attributes[] = 'openarea';
1341
    }
1342
1343
    foreach ($attributes as $attribute) {
1344
        $result[$attribute] = isset($user[$attribute]) ? $user[$attribute] : null;
1345
    }
1346
1347
    if (isset($user['email'])) {
1348
        $result['mail'] = isset($user['email']) ? $user['email'] : null;
1349
        $result['email'] = isset($user['email'])? $user['email'] : null;
1350
    } else {
1351
        $result['mail'] = isset($user['mail']) ? $user['mail'] : null;
1352
        $result['email'] = isset($user['mail'])? $user['mail'] : null;
1353
    }
1354
    $user_id = intval($user['user_id']);
1355
    // Maintain the user_id index for backwards compatibility
1356
    $result['user_id'] = $result['id'] = $user_id;
1357
    $result['last_login'] = $user['last_login'];
1358
1359
    // Getting user avatar.
1360
    $originalFile = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_ORIGINAL, null, $result);
1361
    $smallFile = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_SMALL, null, $result);
1362
    $mediumFile = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_MEDIUM, null, $result);
1363
1364
    $result['avatar'] = $originalFile;
1365
    $avatarString = explode('?', $originalFile);
1366
    $result['avatar_no_query'] = reset($avatarString);
1367
    $result['avatar_small'] = $smallFile;
1368
    $result['avatar_medium'] = $mediumFile;
1369
1370
    if (isset($user['user_is_online'])) {
1371
        $result['user_is_online'] = $user['user_is_online'] == true ? 1 : 0;
1372
    }
1373
    if (isset($user['user_is_online_in_chat'])) {
1374
        $result['user_is_online_in_chat'] = intval($user['user_is_online_in_chat']);
1375
    }
1376
1377
    if ($add_password) {
1378
        $result['password'] = $user['password'];
1379
    }
1380
1381
    if (isset($result['profile_completed'])) {
1382
        $result['profile_completed'] = $user['profile_completed'];
1383
    }
1384
1385
    $result['profile_url'] = api_get_path(WEB_CODE_PATH).'social/profile.php?u='.$user_id;
1386
1387
    if (isset($user['extra'])) {
1388
        $result['extra'] = $user['extra'];
1389
    }
1390
1391
    return $result;
1392
}
1393
1394
/**
1395
 * Finds all the information about a user.
1396
 * If no parameter is passed you find all the information about the current user.
1397
 * @param int  $user_id
1398
 * @param bool $checkIfUserOnline
1399
 * @param bool $showPassword
1400
 * @param bool $loadExtraData
1401
 * @param bool $loadOnlyVisibleExtraData Get the user extra fields that are visible
1402
 * @return array $user_info user_id, lastname, firstname, username, email, etc
1403
 * @author Patrick Cool <[email protected]>
1404
 * @author Julio Montoya
1405
 * @version 21 September 2004
1406
 */
1407
function api_get_user_info(
1408
    $user_id = 0,
1409
    $checkIfUserOnline = false,
1410
    $showPassword = false,
1411
    $loadExtraData = false,
1412
    $loadOnlyVisibleExtraData = false
1413
) {
1414
    if (empty($user_id)) {
1415
        $userFromSession = Session::read('_user');
1416
        if (isset($userFromSession)) {
1417
            return _api_format_user($userFromSession);
1418
        }
1419
1420
        return false;
1421
    }
1422
1423
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1424
            WHERE id='".intval($user_id)."'";
1425
    $result = Database::query($sql);
1426
    if (Database::num_rows($result) > 0) {
1427
        $result_array = Database::fetch_array($result);
1428
        if ($checkIfUserOnline) {
1429
            $use_status_in_platform = user_is_online($user_id);
1430
1431
            $result_array['user_is_online'] = $use_status_in_platform;
1432
            $user_online_in_chat = 0;
1433
1434
            if ($use_status_in_platform) {
1435
                $user_status = UserManager::get_extra_user_data_by_field(
1436
                    $user_id,
1437
                    'user_chat_status',
1438
                    false,
1439
                    true
1440
                );
1441
                if (intval($user_status['user_chat_status']) == 1) {
1442
                    $user_online_in_chat = 1;
1443
                }
1444
            }
1445
            $result_array['user_is_online_in_chat'] = $user_online_in_chat;
1446
        }
1447
1448
        if ($loadExtraData) {
1449
            $fieldValue = new ExtraFieldValue('user');
1450
1451
            $result_array['extra'] = $fieldValue->getAllValuesForAnItem(
1452
                $user_id,
1453
                $loadOnlyVisibleExtraData
1454
            );
1455
        }
1456
        $user = _api_format_user($result_array, $showPassword);
1457
1458
        return $user;
1459
    }
1460
    return false;
1461
}
1462
1463
/**
1464
 * @param int $userId
1465
 * @return User
1466
 */
1467
function api_get_user_entity($userId)
1468
{
1469
    /** @var \Chamilo\UserBundle\Repository\UserRepository $repo */
1470
    $repo = Database::getManager()->getRepository('ChamiloUserBundle:User');
1471
1472
    return $repo->find($userId);
1473
}
1474
1475
/**
1476
 * @param int $courseId
1477
 *
1478
 * @return Course
1479
 */
1480
function api_get_user_course_entity($courseId = null)
1481
{
1482
    if (empty($courseId)) {
1483
        $courseId = api_get_course_int_id();
1484
    }
1485
    return CourseManager::getManager()->find($courseId);
1486
}
1487
1488
/**
1489
 * Finds all the information about a user from username instead of user id
1490
 * @param string $username
1491
 * @return array $user_info array user_id, lastname, firstname, username, email
1492
 * @author Yannick Warnier <[email protected]>
1493
 */
1494 View Code Duplication
function api_get_user_info_from_username($username = '')
1495
{
1496
    if (empty($username)) {
1497
        return false;
1498
    }
1499
    $username = trim($username);
1500
1501
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1502
            WHERE username='".Database::escape_string($username)."'";
1503
    $result = Database::query($sql);
1504
    if (Database::num_rows($result) > 0) {
1505
        $result_array = Database::fetch_array($result);
1506
        return _api_format_user($result_array);
1507
    }
1508
    return false;
1509
}
1510
1511
/**
1512
 * Get first user with an email
1513
 * @param string $email
1514
 * @return array|bool
1515
 */
1516 View Code Duplication
function api_get_user_info_from_email($email = '')
1517
{
1518
    if (empty($email)) {
1519
        return false;
1520
    }
1521
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1522
            WHERE email ='".Database::escape_string($email)."' LIMIT 1";
1523
    $result = Database::query($sql);
1524
    if (Database::num_rows($result) > 0) {
1525
        $result_array = Database::fetch_array($result);
1526
        return _api_format_user($result_array);
1527
    }
1528
1529
    return false;
1530
}
1531
1532
/**
1533
 * @return string
1534
 */
1535
function api_get_course_id()
1536
{
1537
    return Session::read('_cid', null);
1538
}
1539
1540
/**
1541
 * Returns the current course id (integer)
1542
 * @param   string  $code   Optional course code
1543
 * @return int
1544
 */
1545
function api_get_course_int_id($code = null)
1546
{
1547 View Code Duplication
    if (!empty($code)) {
1548
        $code = Database::escape_string($code);
1549
        $row = Database::select(
1550
            'id',
1551
            Database::get_main_table(TABLE_MAIN_COURSE),
1552
            array('where'=> array('code = ?' => array($code))),
1553
            'first'
1554
        );
1555
1556
        if (is_array($row) && isset($row['id'])) {
1557
            return $row['id'];
1558
        } else {
1559
            return false;
1560
        }
1561
    }
1562
    return Session::read('_real_cid', 0);
1563
}
1564
1565
/**
1566
 * Returns the current course directory
1567
 *
1568
 * This function relies on api_get_course_info()
1569
 * @param string    The course code - optional (takes it from session if not given)
1570
 * @return string   The directory where the course is located inside the Chamilo "courses" directory
1571
 * @author Yannick Warnier <[email protected]>
1572
 */
1573
function api_get_course_path($course_code = null)
1574
{
1575
    $info = !empty($course_code) ? api_get_course_info($course_code) : api_get_course_info();
1576
    return $info['path'];
1577
}
1578
1579
/**
1580
 * Gets a course setting from the current course_setting table. Try always using integer values.
1581
 * @param string    The name of the setting we want from the table
1582
 * @param string    Optional: course code
1583
 * @param string $setting_name
1584
 * @return mixed    The value of that setting in that table. Return -1 if not found.
1585
 */
1586
function api_get_course_setting($setting_name, $course_code = null)
1587
{
1588
    $course_info = api_get_course_info($course_code);
1589
    $table = Database::get_course_table(TABLE_COURSE_SETTING);
1590
    $setting_name = Database::escape_string($setting_name);
1591
    if (!empty($course_info['real_id']) && !empty($setting_name)) {
1592
        $sql = "SELECT value FROM $table
1593
                WHERE c_id = {$course_info['real_id']} AND variable = '$setting_name'";
1594
        $res = Database::query($sql);
1595
        if (Database::num_rows($res) > 0) {
1596
            $row = Database::fetch_array($res);
1597
            return $row['value'];
1598
        }
1599
    }
1600
    return -1;
1601
}
1602
1603
/**
1604
 * Gets an anonymous user ID
1605
 *
1606
 * For some tools that need tracking, like the learnpath tool, it is necessary
1607
 * to have a usable user-id to enable some kind of tracking, even if not
1608
 * perfect. An anonymous ID is taken from the users table by looking for a
1609
 * status of "6" (anonymous).
1610
 * @return int  User ID of the anonymous user, or O if no anonymous user found
1611
 */
1612 View Code Duplication
function api_get_anonymous_id()
1613
{
1614
    $table = Database::get_main_table(TABLE_MAIN_USER);
1615
    $sql = "SELECT user_id FROM $table WHERE status = ".ANONYMOUS;
1616
    $res = Database::query($sql);
1617
    if (Database::num_rows($res) > 0) {
1618
        $row = Database::fetch_array($res);
1619
        return $row['user_id'];
1620
    }
1621
1622
    // No anonymous user was found.
1623
    return 0;
1624
}
1625
1626
/**
1627
 * @param string $courseCode
1628
 * @param int $sessionId
1629
 * @param int $groupId
1630
 * @return string
1631
 */
1632
function api_get_cidreq_params($courseCode, $sessionId = 0, $groupId = 0)
1633
{
1634
    $courseCode = !empty($courseCode) ? htmlspecialchars($courseCode) : '';
1635
    $sessionId = !empty($sessionId) ? (int) $sessionId : 0;
1636
    $groupId = !empty($groupId) ? (int) $groupId : 0;
1637
1638
    $url = 'cidReq='.$courseCode;
1639
    $url .= '&id_session='.$sessionId;
1640
    $url .= '&gidReq='.$groupId;
1641
1642
    return $url;
1643
}
1644
1645
/**
1646
 * Returns the current course url part including session, group, and gradebook params
1647
 *
1648
 * @param bool $addSessionId
1649
 * @param bool $addGroupId
1650
 * @param string $origin
1651
 *
1652
 * @return  string  Course & session references to add to a URL
1653
 *
1654
 */
1655
function api_get_cidreq($addSessionId = true, $addGroupId = true, $origin = '')
1656
{
1657
    $courseCode = api_get_course_id();
1658
    $url = empty($courseCode) ? '' : 'cidReq='.htmlspecialchars($courseCode);
1659
    $origin = empty($origin) ? api_get_origin() : Security::remove_XSS($origin);
1660
1661
    if ($addSessionId) {
1662
        if (!empty($url)) {
1663
            $url .= api_get_session_id() == 0 ? '&id_session=0' : '&id_session='.api_get_session_id();
1664
        }
1665
    }
1666
1667
    if ($addGroupId) {
1668
        if (!empty($url)) {
1669
            $url .= api_get_group_id() == 0 ? '&gidReq=0' : '&gidReq='.api_get_group_id();
1670
        }
1671
    }
1672
1673
    if (!empty($url)) {
1674
        $url .= '&gradebook='.intval(api_is_in_gradebook());
1675
        $url .= '&origin='.$origin;
1676
    }
1677
1678
    return $url;
1679
}
1680
1681
/**
1682
 * get gradebook in session
1683
 */
1684
function api_is_in_gradebook()
1685
{
1686
    return Session::read('in_gradebook', false);
1687
}
1688
1689
/**
1690
 * set gradebook session
1691
 */
1692
function api_set_in_gradebook()
1693
{
1694
    Session::write('in_gradebook', true);
1695
}
1696
1697
/**
1698
 * remove gradebook session
1699
 */
1700
function api_remove_in_gradebook()
1701
{
1702
    Session::erase('in_gradebook');
1703
}
1704
1705
/**
1706
 * Returns the current course info array see api_format_course_array()
1707
 * If the course_code is given, the returned array gives info about that
1708
 * particular course, if none given it gets the course info from the session.
1709
 *
1710
 * @param string $course_code
1711
 * @param bool $strict
1712
 *
1713
 * @return array
1714
 */
1715
function api_get_course_info($course_code = null, $strict = false)
1716
{
1717
    if (!empty($course_code)) {
1718
        $course_code = Database::escape_string($course_code);
1719
        $courseId = api_get_course_int_id($course_code);
1720
1721
        if (empty($courseId)) {
1722
            return array();
1723
        }
1724
1725
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1726
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1727
        $sql = "SELECT
1728
                    course.*,
1729
                    course_category.code faCode,
1730
                    course_category.name faName
1731
                FROM $course_table
1732
                LEFT JOIN $course_cat_table
1733
                ON course.category_code = course_category.code
1734
                WHERE course.id = $courseId";
1735
        $result = Database::query($sql);
1736
        $courseInfo = array();
1737
        if (Database::num_rows($result) > 0) {
1738
            $data = Database::fetch_array($result);
1739
            $courseInfo = api_format_course_array($data);
1740
        }
1741
1742
        return $courseInfo;
1743
    }
1744
1745
    $_course = Session::read('_course');
1746
    if ($_course == '-1') {
1747
        $_course = array();
1748
    }
1749
1750
    return $_course;
1751
}
1752
1753
/**
1754
 * Returns the current course info array.
1755
1756
 * Now if the course_code is given, the returned array gives info about that
1757
 * particular course, not specially the current one.
1758
 * @param int $id Numeric ID of the course
1759
 * @return array The course info as an array formatted by api_format_course_array, including category.name
1760
 */
1761
function api_get_course_info_by_id($id = null)
1762
{
1763
    if (!empty($id)) {
1764
        $id = intval($id);
1765
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1766
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1767
        $sql = "SELECT
1768
                    course.*,
1769
                    course_category.code faCode,
1770
                    course_category.name faName
1771
                FROM $course_table
1772
                LEFT JOIN $course_cat_table
1773
                ON course.category_code =  course_category.code
1774
                WHERE course.id = $id";
1775
        $result = Database::query($sql);
1776
        $_course = array();
1777
        if (Database::num_rows($result) > 0) {
1778
            $course_data = Database::fetch_array($result);
1779
            $_course = api_format_course_array($course_data);
1780
        }
1781
        return $_course;
1782
    }
1783
1784
    global $_course;
1785
    if ($_course == '-1') $_course = array();
1786
    return $_course;
1787
}
1788
1789
/**
1790
 * Reformat the course array (output by api_get_course_info()) in order, mostly,
1791
 * to switch from 'code' to 'id' in the array. This is a legacy feature and is
1792
 * now possibly causing massive confusion as a new "id" field has been added to
1793
 * the course table in 1.9.0.
1794
 * @param $course_data
1795
 * @return array
1796
 * @todo eradicate the false "id"=code field of the $_course array and use the int id
1797
 */
1798
function api_format_course_array($course_data)
1799
{
1800
    if (empty($course_data)) {
1801
        return array();
1802
    }
1803
1804
    $_course = array();
1805
    $_course['id'] = $course_data['code'];
1806
    $_course['real_id'] = $course_data['id'];
1807
1808
    // Added
1809
    $_course['code'] = $course_data['code'];
1810
    $_course['name'] = $course_data['title'];
1811
    $_course['title'] = $course_data['title'];
1812
    $_course['official_code'] = $course_data['visual_code'];
1813
    $_course['visual_code'] = $course_data['visual_code'];
1814
    $_course['sysCode'] = $course_data['code'];
1815
    $_course['path'] = $course_data['directory']; // Use as key in path.
1816
    $_course['directory'] = $course_data['directory'];
1817
    $_course['creation_date'] = $course_data['creation_date'];
1818
    $_course['titular'] = $course_data['tutor_name'];
1819
    $_course['language'] = $course_data['course_language'];
1820
    $_course['extLink']['url'] = $course_data['department_url'];
1821
    $_course['extLink']['name'] = $course_data['department_name'];
1822
    $_course['categoryCode'] = $course_data['faCode'];
1823
    $_course['categoryName'] = $course_data['faName'];
1824
    $_course['visibility'] = $course_data['visibility'];
1825
    $_course['subscribe_allowed'] = $course_data['subscribe'];
1826
    $_course['subscribe'] = $course_data['subscribe'];
1827
    $_course['unsubscribe'] = $course_data['unsubscribe'];
1828
    $_course['course_language'] = $course_data['course_language'];
1829
    $_course['activate_legal'] = isset($course_data['activate_legal']) ? $course_data['activate_legal'] : false;
1830
    $_course['legal'] = $course_data['legal'];
1831
    $_course['show_score'] = $course_data['show_score']; //used in the work tool
1832
    $_course['department_name'] = $course_data['department_name'];
1833
    $_course['department_url'] = $course_data['department_url'];
1834
1835
    // Course password
1836
    $_course['registration_code'] = !empty($course_data['registration_code']) ? sha1($course_data['registration_code']) : null;
1837
    $_course['disk_quota'] = $course_data['disk_quota'];
1838
    $_course['course_public_url'] = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/index.php';
1839
1840
    if (array_key_exists('add_teachers_to_sessions_courses', $course_data)) {
1841
        $_course['add_teachers_to_sessions_courses'] = $course_data['add_teachers_to_sessions_courses'];
1842
    }
1843
1844
    if (file_exists(api_get_path(SYS_COURSE_PATH).$course_data['directory'].'/course-pic85x85.png')) {
1845
        $url_image = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/course-pic85x85.png';
1846
    } else {
1847
        $url_image = Display::return_icon('course.png', null, null, ICON_SIZE_BIG, null, true, false);
1848
    }
1849
    $_course['course_image'] = $url_image;
1850
1851
    if (file_exists(api_get_path(SYS_COURSE_PATH).$course_data['directory'].'/course-pic.png')) {
1852
        $url_image = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/course-pic.png';
1853
    } else {
1854
        $url_image = Display::returnIconPath('session_default.png');
1855
    }
1856
    $_course['course_image_large'] = $url_image;
1857
1858
    $_course['extra_fields'] = isset($course_data['extra_fields']) ? $course_data['extra_fields'] : array();
1859
    $_course['settings'] = isset($course_data['settings']) ? $course_data['settings'] : array();
1860
    $_course['teacher_list'] = isset($course_data['teacher_list']) ? $course_data['teacher_list'] : array();
1861
    $_course['teacher_list_formatted'] = isset($course_data['teacher_list_formatted']) ? $course_data['teacher_list_formatted'] : array();
1862
1863
    return $_course;
1864
}
1865
1866
/**
1867
 * Add a parameter to the existing URL. If this parameter already exists,
1868
 * just replace it with the new value
1869
 * @param   string  The URL
1870
 * @param   string  param=value string
1871
 * @param   boolean Whether to filter XSS or not
1872
 * @return  string  The URL with the added parameter
1873
 */
1874
function api_add_url_param($url, $param, $filter_xss = true) {
1875
    if (empty($param)) {
1876
        return $url;
1877
    }
1878
    if (strpos($url, '?') !== false) {
1879
        if ($param[0] != '&') {
1880
            $param = '&'.$param;
1881
        }
1882
        list (, $query_string) = explode('?', $url);
1883
        $param_list1 = explode('&', $param);
1884
        $param_list2 = explode('&', $query_string);
1885
        $param_list1_keys = $param_list1_vals = array();
1886
        foreach ($param_list1 as $key => $enreg) {
1887
            list ($param_list1_keys[$key], $param_list1_vals[$key]) = explode('=', $enreg);
1888
        }
1889
        $param_list1 = array ('keys' => $param_list1_keys, 'vals' => $param_list1_vals);
1890
        foreach ($param_list2 as $enreg) {
1891
            $enreg = explode('=', $enreg);
1892
            $key = array_search($enreg[0], $param_list1['keys']);
1893
            if (!is_null($key) && !is_bool($key)) {
1894
                $url = str_replace($enreg[0].'='.$enreg[1], $enreg[0].'='.$param_list1['vals'][$key], $url);
1895
                $param = str_replace('&'.$enreg[0].'='.$param_list1['vals'][$key], '', $param);
1896
            }
1897
        }
1898
        $url .= $param;
1899
    } else {
1900
        $url = $url.'?'.$param;
1901
    }
1902
    if ($filter_xss === true) {
1903
        $url = Security::remove_XSS(urldecode($url));
1904
    }
1905
    return $url;
1906
}
1907
1908
/**
1909
 * Returns a difficult to guess password.
1910
 * @param int $length the length of the password
1911
 * @return string the generated password
1912
 */
1913
function api_generate_password($length = 8)
1914
{
1915
    $characters = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
1916
    $numbers = '23456789';
1917
1918
    if ($length < 2) {
1919
        $length = 2;
1920
    }
1921
    $password = '';
1922
    for ($i = 0; $i < $length; $i ++) {
1923
        $password .= $characters[rand() % strlen($characters)];
1924
    }
1925
1926
    // At least 2 digits
1927
    for ($i = 0; $i < 2; $i ++) {
1928
        $password .= $numbers[rand() % strlen($numbers)];
1929
    }
1930
1931
    return $password;
1932
}
1933
1934
/**
1935
 * Checks a password to see wether it is OK to use.
1936
 * @param string $password
1937
 * @return boolean if the password is acceptable, false otherwise
1938
 * Notes about what a password "OK to use" is:
1939
 * 1. The password should be at least 5 characters long.
1940
 * 2. Only English letters (uppercase or lowercase, it doesn't matter) and digits are allowed.
1941
 * 3. The password should contain at least 3 letters.
1942
 * 4. It should contain at least 2 digits.
1943
 * 5. It should not contain 3 or more consequent (according to ASCII table) characters.
1944
 */
1945
function api_check_password($password) {
1946
    $password_length = api_strlen($password);
1947
    if ($password_length < 5) {
1948
        return false;
1949
    }
1950
    $password = api_strtolower($password);
1951
    $letters = 0;
1952
    $digits = 0;
1953
    $consequent_characters = 0;
1954
    $previous_character_code = 0;
1955
    for ($i = 0; $i < $password_length; $i ++) {
1956
        $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...
1957
        if ($i && abs($current_character_code - $previous_character_code) <= 1) {
1958
            $consequent_characters ++;
1959
            if ($consequent_characters == 3) {
1960
                return false;
1961
            }
1962
        } else {
1963
            $consequent_characters = 1;
1964
        }
1965
        if ($current_character_code >= 97 && $current_character_code <= 122) {
1966
            $letters ++;
1967
        } elseif ($current_character_code >= 48 && $current_character_code <= 57) {
1968
            $digits ++;
1969
        } else {
1970
            return false;
1971
        }
1972
        $previous_character_code = $current_character_code;
1973
    }
1974
    return ($letters >= 3 && $digits >= 2);
1975
}
1976
1977
/**
1978
 * Clears the user ID from the session if it was the anonymous user. Generally
1979
 * used on out-of-tools pages to remove a user ID that could otherwise be used
1980
 * in the wrong context.
1981
 * This function is to be used in conjunction with the api_set_anonymous()
1982
 * function to simulate the user existence in case of an anonymous visit.
1983
 * @param bool      database check switch - passed to api_is_anonymous()
1984
 * @return bool     true if succesfully unregistered, false if not anonymous.
1985
 */
1986
function api_clear_anonymous($db_check = false)
1987
{
1988
    global $_user;
1989
    if (api_is_anonymous($_user['user_id'], $db_check)) {
1990
        unset($_user['user_id']);
1991
        Session::erase('_uid');
1992
        return true;
1993
    }
1994
    return false;
1995
}
1996
1997
/**
1998
 * Returns the status string corresponding to the status code
1999
 * @author Noel Dieschburg
2000
 * @param the int status code
2001
 */
2002
function get_status_from_code($status_code)
2003
{
2004
    switch ($status_code) {
2005
        case STUDENT:
2006
            return get_lang('Student', '');
2007
        case TEACHER:
2008
            return get_lang('Teacher', '');
2009
        case COURSEMANAGER:
2010
            return get_lang('Manager', '');
2011
        case SESSIONADMIN:
2012
            return get_lang('SessionsAdmin', '');
2013
        case DRH:
2014
            return get_lang('Drh', '');
2015
    }
2016
}
2017
2018
/**
2019
 * Sets the current user as anonymous if it hasn't been identified yet. This
2020
 * function should be used inside a tool only. The function api_clear_anonymous()
2021
 * acts in the opposite direction by clearing the anonymous user's data every
2022
 * time we get on a course homepage or on a neutral page (index, admin, my space)
2023
 * @return bool     true if set user as anonymous, false if user was already logged in or anonymous id could not be found
2024
 */
2025
function api_set_anonymous() {
2026
    global $_user;
2027
2028
    if (!empty($_user['user_id'])) {
2029
        return false;
2030
    }
2031
    $user_id = api_get_anonymous_id();
2032
    if ($user_id == 0) {
2033
        return false;
2034
    }
2035
    Session::erase('_user');
2036
    $_user['user_id'] = $user_id;
2037
    $_user['is_anonymous'] = true;
2038
    $GLOBALS['_user'] = $_user;
2039
    Session::write('_user', $_user);
2040
    return true;
2041
}
2042
2043
/**
2044
 * Gets the current Chamilo (not PHP/cookie) session ID
2045
 * @return  int     O if no active session, the session ID otherwise
2046
 */
2047
function api_get_session_id()
2048
{
2049
    return Session::read('id_session', 0);
2050
}
2051
2052
/**
2053
 * Gets the current Chamilo (not social network) group ID
2054
 * @return  int     O if no active session, the session ID otherwise
2055
 */
2056
function api_get_group_id()
2057
{
2058
    return Session::read('_gid', 0);
2059
}
2060
2061
/**
2062
 * Gets the current or given session name
2063
 * @param   int     Session ID (optional)
2064
 * @return  string  The session name, or null if unfound
2065
 */
2066
function api_get_session_name($session_id = 0)
2067
{
2068
    if (empty($session_id)) {
2069
        $session_id = api_get_session_id();
2070
        if (empty($session_id)) {
2071
            return null;
2072
        }
2073
    }
2074
    $t = Database::get_main_table(TABLE_MAIN_SESSION);
2075
    $s = "SELECT name FROM $t WHERE id = ".(int)$session_id;
2076
    $r = Database::query($s);
2077
    $c = Database::num_rows($r);
2078
    if ($c > 0) {
2079
        //technically, there can be only one, but anyway we take the first
2080
        $rec = Database::fetch_array($r);
2081
        return $rec['name'];
2082
    }
2083
    return null;
2084
}
2085
2086
/**
2087
 * Gets the session info by id
2088
 * @param int       Session ID
2089
 * @return array    information of the session
2090
 */
2091
function api_get_session_info($session_id)
2092
{
2093
    return SessionManager::fetch($session_id);
2094
}
2095
2096
/**
2097
 * Gets the session visibility by session id
2098
 * @param int $session_id
2099
 * @param int $courseId
2100
 * @param bool $ignore_visibility_for_admins
2101
 * @return int
2102
 *  0 = session still available,
2103
 *  SESSION_VISIBLE_READ_ONLY = 1,
2104
 *  SESSION_VISIBLE = 2,
2105
 *  SESSION_INVISIBLE = 3
2106
 */
2107
function api_get_session_visibility(
2108
    $session_id,
2109
    $courseId = null,
2110
    $ignore_visibility_for_admins = true
2111
) {
2112
    // Means that the session is still available.
2113
    $visibility = 0;
2114
2115
    if (api_is_platform_admin()) {
2116
        if ($ignore_visibility_for_admins) {
2117
            return SESSION_AVAILABLE;
2118
        }
2119
    }
2120
2121
    $now = time();
2122
    if (!empty($session_id)) {
2123
        $session_id = intval($session_id);
2124
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2125
2126
        $sql = "SELECT * FROM $tbl_session
2127
                WHERE id = $session_id ";
2128
2129
        $result = Database::query($sql);
2130
2131
        if (Database::num_rows($result) > 0) {
2132
            $row = Database::fetch_array($result, 'ASSOC');
2133
            $visibility = $original_visibility = $row['visibility'];
2134
2135
            // I don't care the session visibility.
2136
            if (empty($row['access_start_date']) && empty($row['access_end_date'])) {
2137
                // Session duration per student.
2138
                if (isset($row['duration']) && !empty($row['duration'])) {
2139
                    $duration = $row['duration'] * 24 * 60 * 60;
2140
2141
                    $courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser(
2142
                        $session_id,
2143
                        api_get_user_id()
2144
                    );
2145
2146
                    // If there is a session duration but there is no previous
2147
                    // access by the user, then the session is still available
2148
                    if (count($courseAccess) == 0) {
2149
                        return SESSION_AVAILABLE;
2150
                    }
2151
2152
                    $currentTime = time();
2153
                    $firstAccess = 0;
2154
                    if (isset($courseAccess['login_course_date'])) {
2155
                        $firstAccess = api_strtotime(
2156
                            $courseAccess['login_course_date'],
2157
                            'UTC'
2158
                        );
2159
                    }
2160
                    $userDurationData = SessionManager::getUserSession(
2161
                        api_get_user_id(),
2162
                        $session_id
2163
                    );
2164
                    $userDuration = 0;
2165
                    if (isset($userDurationData['duration'])) {
2166
                        $userDuration = intval($userDurationData['duration']) * 24 * 60 * 60;
2167
                    }
2168
2169
                    $totalDuration = $firstAccess + $duration + $userDuration;
2170
                    if ($totalDuration > $currentTime) {
2171
                        return SESSION_AVAILABLE;
2172
                    } else {
2173
                        return SESSION_INVISIBLE;
2174
                    }
2175
                }
2176
2177
                return SESSION_AVAILABLE;
2178
            } else {
2179
                // If start date was set.
2180
                if (!empty($row['access_start_date'])) {
2181
                    if ($now > api_strtotime($row['access_start_date'], 'UTC')) {
2182
                        $visibility = SESSION_AVAILABLE;
2183
                    } else {
2184
                        $visibility = SESSION_INVISIBLE;
2185
                    }
2186
                }
2187
2188
                // If the end date was set.
2189
                if (!empty($row['access_end_date'])) {
2190
                    // Only if date_start said that it was ok
2191
                    if ($visibility === SESSION_AVAILABLE) {
2192
                        if ($now < api_strtotime($row['access_end_date'], 'UTC')) {
2193
                            // Date still available
2194
                            $visibility = SESSION_AVAILABLE;
2195
                        } else {
2196
                            // Session ends
2197
                            $visibility = $row['visibility'];
2198
                        }
2199
                    }
2200
                }
2201
            }
2202
2203
            /* If I'm a coach the visibility can change in my favor depending in
2204
             the coach dates */
2205
            $isCoach = api_is_coach($session_id, $courseId);
2206
2207
            if ($isCoach) {
2208
                // Test end date.
2209
                if (!empty($row['coach_access_end_date'])) {
2210
                    $endDateCoach = api_strtotime($row['coach_access_end_date'], 'UTC');
2211
2212
                    if ($endDateCoach >= $now) {
2213
                        $visibility = SESSION_AVAILABLE;
2214
                    } else {
2215
                        $visibility = SESSION_INVISIBLE;
2216
                    }
2217
                }
2218
2219
                // Test start date.
2220
                if (!empty($row['coach_access_start_date'])) {
2221
                    $start = api_strtotime($row['coach_access_start_date'], 'UTC');
2222
                    if ($start < $now) {
2223
                        $visibility = SESSION_AVAILABLE;
2224
                    } else {
2225
                        $visibility = SESSION_INVISIBLE;
2226
                    }
2227
                }
2228
            }
2229
        } else {
2230
            $visibility = SESSION_INVISIBLE;
2231
        }
2232
    }
2233
    return $visibility;
2234
}
2235
2236
/**
2237
 * This function returns a (star) session icon if the session is not null and
2238
 * the user is not a student
2239
 * @param int   $session_id
2240
 * @param int   $status_id User status id - if 5 (student), will return empty
2241
 * @return string   Session icon
2242
 */
2243
function api_get_session_image($session_id, $status_id)
2244
{
2245
    $session_id = (int)$session_id;
2246
    $session_img = '';
2247
    if ((int)$status_id != 5) { //check whether is not a student
2248
        if ($session_id > 0) {
2249
            $session_img = "&nbsp;&nbsp;".Display::return_icon(
2250
                'star.png',
2251
                get_lang('SessionSpecificResource'),
2252
                array('align' => 'absmiddle'),
2253
                ICON_SIZE_SMALL
2254
            );
2255
        }
2256
    }
2257
    return $session_img;
2258
}
2259
2260
/**
2261
 * This function add an additional condition according to the session of the course
2262
 * @param int       $session_id session id
2263
 * @param bool      $and optional, true if more than one condition false if the only condition in the query
2264
 * @param bool      $with_base_content optional, true to accept content with session=0 as well, false for strict session condition
2265
 * @return string   condition of the session
2266
 */
2267
function api_get_session_condition(
2268
    $session_id,
2269
    $and = true,
2270
    $with_base_content = false,
2271
    $session_field = "session_id"
2272
) {
2273
    $session_id = intval($session_id);
2274
2275
    if (empty($session_field)) {
2276
        $session_field = "session_id";
2277
    }
2278
    // Condition to show resources by session
2279
    $condition_add = $and ? " AND " : " WHERE ";
2280
2281
    if ($with_base_content) {
2282
        $condition_session = $condition_add." ( $session_field = $session_id OR $session_field = 0 OR $session_field IS NULL) ";
2283
    } else {
2284
        if (empty($session_id)) {
2285
            $condition_session = $condition_add." ($session_field = $session_id OR $session_field IS NULL)";
2286
        } else {
2287
            $condition_session = $condition_add." $session_field = $session_id ";
2288
        }
2289
    }
2290
    return $condition_session;
2291
}
2292
2293
/**
2294
 * Returns the value of a setting from the web-adjustable admin config settings.
2295
 *
2296
 * WARNING true/false are stored as string, so when comparing you need to check e.g.
2297
 * if (api_get_setting('course.show_navigation_menu') == 'true') //CORRECT
2298
 * instead of
2299
 * if (api_get_setting('course.show_navigation_menu') == true) //INCORRECT
2300
 * @param string    $variable The variable name
2301
 * @return string
2302
 *
2303
 * @author Julio Montoya
2304
 */
2305
function api_get_setting($variable)
2306
{
2307
    $variable = trim($variable);
2308
2309
    switch ($variable) {
2310 View Code Duplication
        case 'header_extra_content':
2311
            $filename = api_get_path(SYS_PATH).api_get_home_path().'header_extra_content.txt';
2312
            if (file_exists($filename)) {
2313
                $value = file_get_contents($filename);
2314
                    return $value ;
2315
            } else {
2316
                return '';
2317
            }
2318
            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...
2319 View Code Duplication
        case 'footer_extra_content':
2320
            $filename = api_get_path(SYS_PATH).api_get_home_path().'footer_extra_content.txt';
2321
            if (file_exists($filename)) {
2322
                $value = file_get_contents($filename);
2323
                    return $value ;
2324
            } else {
2325
                return '';
2326
            }
2327
            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...
2328
        case 'server_type':
2329
            $test = ['dev', 'test'];
2330
            $environment = Container::getEnvironment();
2331
            if (in_array($environment, $test)) {
2332
                return 'test';
2333
            }
2334
            return 'prod';
2335
        case 'stylesheets':
2336
            $variable = 'platform.theme';
2337
            break;
2338
        default:
2339
            return Container::getSettingsManager()->getSetting($variable);
2340
    }
2341
}
2342
2343
/**
2344
 * @param string $plugin
2345
 * @param string $variable
2346
 * @return string
2347
 */
2348
function api_get_plugin_setting($plugin, $variable)
2349
{
2350
    $variableName = $plugin.'_'.$variable;
2351
    $result = api_get_setting($variableName);
2352
    if (isset($result[$plugin])) {
2353
        return $result[$plugin];
2354
    }
2355
2356
    return null;
2357
}
2358
2359
/**
2360
 * Returns the value of a setting from the web-adjustable admin config settings.
2361
 **/
2362
function api_get_settings_params($params) {
2363
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2364
    $result = Database::select('*', $table, array('where' => $params));
2365
    return $result;
2366
}
2367
2368
function api_get_settings_params_simple($params) {
2369
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2370
    $result = Database::select('*', $table, array('where' => $params), 'one');
2371
    return $result;
2372
}
2373
2374
/**
2375
 * Returns the value of a setting from the web-adjustable admin config settings.
2376
 **/
2377
function api_delete_settings_params($params) {
2378
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2379
    $result = Database::delete($table, $params);
2380
    return $result;
2381
}
2382
2383
/**
2384
 * Returns an escaped version of $_SERVER['PHP_SELF'] to avoid XSS injection
2385
 * @return string   Escaped version of $_SERVER['PHP_SELF']
2386
 */
2387
function api_get_self() {
2388
    return htmlentities($_SERVER['PHP_SELF']);
2389
}
2390
2391
/**
2392
 * Checks whether current user is a platform administrator
2393
 * @param boolean $allowSessionAdmins Whether session admins should be considered admins or not
2394
 * @param boolean $allowDrh Whether HR directors should be considered admins or not
2395
 * @return boolean True if the user has platform admin rights,
2396
 * false otherwise.
2397
 * @see usermanager::is_admin(user_id) for a user-id specific function
2398
 */
2399
function api_is_platform_admin($allowSessionAdmins = false, $allowDrh = false)
2400
{
2401
    $checker = Container::getAuthorizationChecker();
2402
    if ($checker) {
2403
        if ($checker->isGranted('ROLE_ADMIN')) {
2404
        return true;
2405
    }
2406
        if ($allow_sessions_admins) {
0 ignored issues
show
Bug introduced by
The variable $allow_sessions_admins does not exist. Did you forget to declare it?

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

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