Completed
Push — master ( 1ab056...1759c8 )
by Julito
55:42 queued 24:21
created

api.lib.php ➔ api_get_js_plumb()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

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

// Bar.php
namespace OtherDir;

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

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

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

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

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
8
use Chamilo\CoreBundle\Entity\Course;
9
use Chamilo\CoreBundle\Framework\Container;
10
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
11
12
/**
13
 * This is a code library for Chamilo.
14
 * It is included by default in every Chamilo file (through including the global.inc.php)
15
 * This library is in process of being transferred to src/Chamilo/CoreBundle/Component/Utils/ChamiloApi.
16
 * Whenever a function is transferred to the ChamiloApi class, the places where it is used should include
17
 * the "use Chamilo\CoreBundle\Component\Utils\ChamiloApi;" statement.
18
 * @package chamilo.library
19
 */
20
21
/**
22
 * Constants declaration
23
 */
24
25
// PHP version requirement.
26
define('REQUIRED_PHP_VERSION', '7.0');
27
define('REQUIRED_MIN_MEMORY_LIMIT', '128');
28
define('REQUIRED_MIN_UPLOAD_MAX_FILESIZE', '10');
29
define('REQUIRED_MIN_POST_MAX_SIZE', '10');
30
31
// USER STATUS CONSTANTS
32
/** global status of a user: student */
33
define('STUDENT', 5);
34
/** global status of a user: course manager */
35
define('COURSEMANAGER', 1);
36
/** global status of a user: session admin */
37
define('SESSIONADMIN', 3);
38
/** global status of a user: human ressource manager */
39
define('DRH', 4);
40
/** global status of a user: human ressource manager */
41
define('ANONYMOUS', 6);
42
/** global status of a user: low security, necessary for inserting data from
43
 * the teacher through HTMLPurifier */
44
define('COURSEMANAGERLOWSECURITY', 10);
45
// Soft user status
46
define('PLATFORM_ADMIN', 11);
47
define('SESSION_COURSE_COACH', 12);
48
define('SESSION_GENERAL_COACH', 13);
49
define('COURSE_STUDENT', 14);   //student subscribed in a course
50
define('SESSION_STUDENT', 15);  //student subscribed in a session course
51
define('COURSE_TUTOR', 16); // student is tutor of a course (NOT in session)
52
define('STUDENT_BOSS', 17); // student is boss
53
define('INVITEE', 20);
54
55
// Table of status
56
$_status_list[COURSEMANAGER] = 'teacher';        // 1
57
$_status_list[SESSIONADMIN] = 'session_admin';  // 3
58
$_status_list[DRH] = 'drh';            // 4
59
$_status_list[STUDENT] = 'user';           // 5
60
$_status_list[ANONYMOUS] = 'anonymous';      // 6
61
$_status_list[INVITEE] = 'invited';        // 20
62
63
// COURSE VISIBILITY CONSTANTS
64
/** only visible for course admin */
65
define('COURSE_VISIBILITY_CLOSED', 0);
66
/** only visible for users registered in the course */
67
define('COURSE_VISIBILITY_REGISTERED', 1);
68
/** Open for all registered users on the platform */
69
define('COURSE_VISIBILITY_OPEN_PLATFORM', 2);
70
/** Open for the whole world */
71
define('COURSE_VISIBILITY_OPEN_WORLD', 3);
72
/** Invisible to all except admin */
73
define('COURSE_VISIBILITY_HIDDEN', 4);
74
75
define('COURSE_REQUEST_PENDING', 0);
76
define('COURSE_REQUEST_ACCEPTED', 1);
77
define('COURSE_REQUEST_REJECTED', 2);
78
define('DELETE_ACTION_ENABLED', false);
79
80
// EMAIL SENDING RECIPIENT CONSTANTS
81
define('SEND_EMAIL_EVERYONE', 1);
82
define('SEND_EMAIL_STUDENTS', 2);
83
define('SEND_EMAIL_TEACHERS', 3);
84
85
// SESSION VISIBILITY CONSTANTS
86
define('SESSION_VISIBLE_READ_ONLY', 1);
87
define('SESSION_VISIBLE', 2);
88
define('SESSION_INVISIBLE', 3); // not available
89
define('SESSION_AVAILABLE', 4);
90
91
define('SESSION_LINK_TARGET', '_self');
92
93
define('SUBSCRIBE_ALLOWED', 1);
94
define('SUBSCRIBE_NOT_ALLOWED', 0);
95
define('UNSUBSCRIBE_ALLOWED', 1);
96
define('UNSUBSCRIBE_NOT_ALLOWED', 0);
97
98
// SURVEY VISIBILITY CONSTANTS
99
define('SURVEY_VISIBLE_TUTOR', 0);
100
define('SURVEY_VISIBLE_TUTOR_STUDENT', 1);
101
define('SURVEY_VISIBLE_PUBLIC', 2);
102
103
// CONSTANTS defining all tools, using the english version
104
/* When you add a new tool you must add it into function api_get_tools_lists() too */
105
define('TOOL_DOCUMENT', 'document');
106
define('TOOL_LP_FINAL_ITEM', 'final_item');
107
define('TOOL_THUMBNAIL', 'thumbnail');
108
define('TOOL_HOTPOTATOES', 'hotpotatoes');
109
define('TOOL_CALENDAR_EVENT', 'calendar_event');
110
define('TOOL_LINK', 'link');
111
define('TOOL_LINK_CATEGORY', 'link_category');
112
define('TOOL_COURSE_DESCRIPTION', 'course_description');
113
define('TOOL_SEARCH', 'search');
114
define('TOOL_LEARNPATH', 'learnpath');
115
define('TOOL_AGENDA', 'agenda');
116
define('TOOL_ANNOUNCEMENT', 'announcement');
117
define('TOOL_FORUM', 'forum');
118
define('TOOL_FORUM_CATEGORY', 'forum_category');
119
define('TOOL_FORUM_THREAD', 'forum_thread');
120
define('TOOL_FORUM_POST', 'forum_post');
121
define('TOOL_FORUM_ATTACH', 'forum_attachment');
122
define('TOOL_FORUM_THREAD_QUALIFY', 'forum_thread_qualify');
123
define('TOOL_THREAD', 'thread');
124
define('TOOL_POST', 'post');
125
define('TOOL_DROPBOX', 'dropbox');
126
define('TOOL_QUIZ', 'quiz');
127
define('TOOL_TEST_CATEGORY', 'test_category');
128
define('TOOL_USER', 'user');
129
define('TOOL_GROUP', 'group');
130
define('TOOL_BLOGS', 'blog_management');
131
define('TOOL_CHAT', 'chat');
132
define('TOOL_STUDENTPUBLICATION', 'student_publication');
133
define('TOOL_TRACKING', 'tracking');
134
define('TOOL_HOMEPAGE_LINK', 'homepage_link');
135
define('TOOL_COURSE_SETTING', 'course_setting');
136
define('TOOL_BACKUP', 'backup');
137
define('TOOL_COPY_COURSE_CONTENT', 'copy_course_content');
138
define('TOOL_RECYCLE_COURSE', 'recycle_course');
139
define('TOOL_COURSE_HOMEPAGE', 'course_homepage');
140
define('TOOL_COURSE_RIGHTS_OVERVIEW', 'course_rights');
141
define('TOOL_UPLOAD', 'file_upload');
142
define('TOOL_COURSE_MAINTENANCE', 'course_maintenance');
143
define('TOOL_SURVEY', 'survey');
144
define('TOOL_WIKI', 'wiki');
145
define('TOOL_GLOSSARY', 'glossary');
146
define('TOOL_GRADEBOOK', 'gradebook');
147
define('TOOL_NOTEBOOK', 'notebook');
148
define('TOOL_ATTENDANCE', 'attendance');
149
define('TOOL_COURSE_PROGRESS', 'course_progress');
150
151
// CONSTANTS defining Chamilo interface sections
152
define('SECTION_CAMPUS', 'mycampus');
153
define('SECTION_COURSES', 'mycourses');
154
define('SECTION_CATALOG', 'catalog');
155
define('SECTION_MYPROFILE', 'myprofile');
156
define('SECTION_MYAGENDA', 'myagenda');
157
define('SECTION_COURSE_ADMIN', 'course_admin');
158
define('SECTION_PLATFORM_ADMIN', 'platform_admin');
159
define('SECTION_MYGRADEBOOK', 'mygradebook');
160
define('SECTION_TRACKING', 'session_my_space');
161
define('SECTION_SOCIAL', 'social-network');
162
define('SECTION_DASHBOARD', 'dashboard');
163
define('SECTION_REPORTS', 'reports');
164
define('SECTION_GLOBAL', 'global');
165
166
// CONSTANT name for local authentication source
167
define('PLATFORM_AUTH_SOURCE', 'platform');
168
define('CAS_AUTH_SOURCE', 'cas');
169
define('LDAP_AUTH_SOURCE', 'extldap');
170
171
// CONSTANT defining the default HotPotatoes files directory
172
define('DIR_HOTPOTATOES', '/HotPotatoes_files');
173
174
// event logs types
175
define('LOG_COURSE_DELETE', 'course_deleted');
176
define('LOG_COURSE_CREATE', 'course_created');
177
178
// @todo replace 'soc_gr' with social_group
179
define('LOG_GROUP_PORTAL_CREATED', 'soc_gr_created');
180
define('LOG_GROUP_PORTAL_UPDATED', 'soc_gr_updated');
181
define('LOG_GROUP_PORTAL_DELETED', 'soc_gr_deleted');
182
define('LOG_GROUP_PORTAL_USER_DELETE_ALL', 'soc_gr_delete_users');
183
184
define('LOG_GROUP_PORTAL_ID', 'soc_gr_portal_id');
185
define('LOG_GROUP_PORTAL_REL_USER_ARRAY', 'soc_gr_user_array');
186
187
define('LOG_GROUP_PORTAL_USER_SUBSCRIBED', 'soc_gr_u_subs');
188
define('LOG_GROUP_PORTAL_USER_UNSUBSCRIBED', 'soc_gr_u_unsubs');
189
define('LOG_GROUP_PORTAL_USER_UPDATE_ROLE', 'soc_gr_update_role');
190
191
define('LOG_USER_DELETE', 'user_deleted');
192
define('LOG_USER_CREATE', 'user_created');
193
define('LOG_USER_ENABLE', 'user_enable');
194
define('LOG_USER_DISABLE', 'user_disable');
195
define('LOG_USER_FIELD_CREATE', 'user_field_created');
196
define('LOG_USER_FIELD_DELETE', 'user_field_deleted');
197
define('LOG_SESSION_CREATE', 'session_created');
198
define('LOG_SESSION_DELETE', 'session_deleted');
199
define('LOG_SESSION_ADD_USER_COURSE', 'session_add_user_course');
200
define('LOG_SESSION_DELETE_USER_COURSE', 'session_delete_user_course');
201
define('LOG_SESSION_DELETE_USER', 'session_delete_user');
202
define('LOG_SESSION_ADD_COURSE', 'session_add_course');
203
define('LOG_SESSION_DELETE_COURSE', 'session_delete_course');
204
205
define('LOG_SESSION_CATEGORY_CREATE', 'session_cat_created'); //changed in 1.9.8
206
define('LOG_SESSION_CATEGORY_DELETE', 'session_cat_deleted'); //changed in 1.9.8
207
define('LOG_CONFIGURATION_SETTINGS_CHANGE', 'settings_changed');
208
define('LOG_PLATFORM_LANGUAGE_CHANGE', 'platform_lng_changed'); //changed in 1.9.8
209
define('LOG_SUBSCRIBE_USER_TO_COURSE', 'user_subscribed');
210
define('LOG_UNSUBSCRIBE_USER_FROM_COURSE', 'user_unsubscribed');
211
define('LOG_ATTEMPTED_FORCED_LOGIN', 'attempted_forced_login');
212
213
define('LOG_HOMEPAGE_CHANGED', 'homepage_changed');
214
215
define('LOG_PROMOTION_CREATE', 'promotion_created');
216
define('LOG_PROMOTION_DELETE', 'promotion_deleted');
217
define('LOG_CAREER_CREATE', 'career_created');
218
define('LOG_CAREER_DELETE', 'career_deleted');
219
220
define('LOG_USER_PERSONAL_DOC_DELETED', 'user_doc_deleted');
221
define('LOG_WIKI_ACCESS', 'wiki_page_view');
222
223
define('LOG_EXERCISE_RESULT_DELETE', 'exe_result_deleted');
224
define('LOG_LP_ATTEMPT_DELETE', 'lp_attempt_deleted');
225
define('LOG_QUESTION_RESULT_DELETE', 'qst_attempt_deleted');
226
227
define('LOG_MY_FOLDER_CREATE', 'my_folder_created');
228
define('LOG_MY_FOLDER_CHANGE', 'my_folder_changed');
229
define('LOG_MY_FOLDER_DELETE', 'my_folder_deleted');
230
define('LOG_MY_FOLDER_COPY', 'my_folder_copied');
231
define('LOG_MY_FOLDER_CUT', 'my_folder_cut');
232
define('LOG_MY_FOLDER_PASTE', 'my_folder_pasted');
233
define('LOG_MY_FOLDER_UPLOAD', 'my_folder_uploaded');
234
235
// Event logs data types (max 20 chars)
236
define('LOG_COURSE_CODE', 'course_code');
237
define('LOG_COURSE_ID', 'course_id');
238
define('LOG_USER_ID', 'user_id');
239
define('LOG_USER_OBJECT', 'user_object');
240
define('LOG_USER_FIELD_VARIABLE', 'user_field_variable');
241
define('LOG_SESSION_ID', 'session_id');
242
define('LOG_SESSION_CATEGORY_ID', 'session_category_id');
243
define('LOG_CONFIGURATION_SETTINGS_CATEGORY', 'settings_category');
244
define('LOG_CONFIGURATION_SETTINGS_VARIABLE', 'settings_variable');
245
define('LOG_PLATFORM_LANGUAGE', 'default_platform_language');
246
define('LOG_CAREER_ID', 'career_id');
247
define('LOG_PROMOTION_ID', 'promotion_id');
248
define('LOG_GRADEBOOK_LOCKED', 'gradebook_locked');
249
define('LOG_GRADEBOOK_UNLOCKED', 'gradebook_unlocked');
250
define('LOG_GRADEBOOK_ID', 'gradebook_id');
251
define('LOG_WIKI_PAGE_ID', 'wiki_page_id');
252
define('LOG_EXERCISE_ID', 'exercise_id');
253
define('LOG_EXERCISE_AND_USER_ID', 'exercise_and_user_id');
254
define('LOG_LP_ID', 'lp_id');
255
define('LOG_EXERCISE_ATTEMPT_QUESTION_ID', 'exercise_a_q_id');
256
257
define('LOG_WORK_DIR_DELETE', 'work_dir_delete');
258
define('LOG_WORK_FILE_DELETE', 'work_file_delete');
259
define('LOG_WORK_DATA', 'work_data_array');
260
261
define('LOG_MY_FOLDER_PATH', 'path');
262
define('LOG_MY_FOLDER_NEW_PATH', 'new_path');
263
264
define('USERNAME_PURIFIER', '/[^0-9A-Za-z_\.]/');
265
266
//used when login_is_email setting is true
267
define('USERNAME_PURIFIER_MAIL', '/[^0-9A-Za-z_\.@]/');
268
define('USERNAME_PURIFIER_SHALLOW', '/\s/');
269
270
// This constant is a result of Windows OS detection, it has a boolean value:
271
// true whether the server runs on Windows OS, false otherwise.
272
define('IS_WINDOWS_OS', api_is_windows_os());
273
274
// Checks for installed optional php-extensions.
275
define('INTL_INSTALLED', function_exists('intl_get_error_code'));   // intl extension (from PECL), it is installed by default as of PHP 5.3.0
276
define('ICONV_INSTALLED', function_exists('iconv'));                // iconv extension, for PHP5 on Windows it is installed by default.
277
define('MBSTRING_INSTALLED', function_exists('mb_strlen'));         // mbstring extension.
278
279
// Patterns for processing paths.                                   // Examples:
280
define('REPEATED_SLASHES_PURIFIER', '/\/{2,}/');                    // $path = preg_replace(REPEATED_SLASHES_PURIFIER, '/', $path);
281
define('VALID_WEB_PATH', '/https?:\/\/[^\/]*(\/.*)?/i');            // $is_valid_path = preg_match(VALID_WEB_PATH, $path);
282
define('VALID_WEB_SERVER_BASE', '/https?:\/\/[^\/]*/i');            // $new_path = preg_replace(VALID_WEB_SERVER_BASE, $new_base, $path);
283
284
// Constants for api_get_path() and api_get_path_type(), etc. - registered path types.
285
// basic (leaf elements)
286
define('REL_CODE_PATH', 'REL_CODE_PATH');
287
define('REL_COURSE_PATH', 'REL_COURSE_PATH');
288
define('REL_HOME_PATH', 'REL_HOME_PATH');
289
290
// Constants for api_get_path() and api_get_path_type(), etc. - registered path types.
291
define('WEB_PATH', 'WEB_PATH');
292
define('WEB_APP_PATH', 'WEB_APP_PATH');
293
define('SYS_PATH', 'SYS_PATH');
294
define('SYS_APP_PATH', 'SYS_APP_PATH');
295
define('SYS_UPLOAD_PATH', 'SYS_UPLOAD_PATH');
296
define('WEB_UPLOAD_PATH', 'WEB_UPLOAD_PATH');
297
298
define('REL_PATH', 'REL_PATH');
299
define('WEB_COURSE_PATH', 'WEB_COURSE_PATH');
300
define('SYS_COURSE_PATH', 'SYS_COURSE_PATH');
301
define('WEB_CODE_PATH', 'WEB_CODE_PATH');
302
define('SYS_CODE_PATH', 'SYS_CODE_PATH');
303
define('SYS_LANG_PATH', 'SYS_LANG_PATH');
304
define('WEB_IMG_PATH', 'WEB_IMG_PATH');
305
define('WEB_CSS_PATH', 'WEB_CSS_PATH');
306
define('WEB_PUBLIC_PATH', 'WEB_PUBLIC_PATH');
307
define('SYS_CSS_PATH', 'SYS_CSS_PATH');
308
define('SYS_PLUGIN_PATH', 'SYS_PLUGIN_PATH');
309
define('WEB_PLUGIN_PATH', 'WEB_PLUGIN_PATH');
310
define('SYS_ARCHIVE_PATH', 'SYS_ARCHIVE_PATH');
311
define('WEB_ARCHIVE_PATH', 'WEB_ARCHIVE_PATH');
312
define('SYS_INC_PATH', 'SYS_INC_PATH');
313
define('LIBRARY_PATH', 'LIBRARY_PATH');
314
define('CONFIGURATION_PATH', 'CONFIGURATION_PATH');
315
define('WEB_LIBRARY_PATH', 'WEB_LIBRARY_PATH');
316
define('WEB_LIBRARY_JS_PATH', 'WEB_LIBRARY_JS_PATH');
317
define('WEB_AJAX_PATH', 'WEB_AJAX_PATH');
318
define('SYS_TEST_PATH', 'SYS_TEST_PATH');
319
define('WEB_TEMPLATE_PATH', 'WEB_TEMPLATE_PATH');
320
define('SYS_TEMPLATE_PATH', 'SYS_TEMPLATE_PATH');
321
define('SYS_PUBLIC_PATH', 'SYS_PUBLIC_PATH');
322
define('SYS_HOME_PATH', 'SYS_HOME_PATH');
323
define('WEB_HOME_PATH', 'WEB_HOME_PATH');
324
define('WEB_FONTS_PATH', 'WEB_FONTS_PATH');
325
define('SYS_FONTS_PATH', 'SYS_FONTS_PATH');
326
327
define('SYS_DEFAULT_COURSE_DOCUMENT_PATH', 'SYS_DEFAULT_COURSE_DOCUMENT_PATH');
328
define('REL_DEFAULT_COURSE_DOCUMENT_PATH', 'REL_DEFAULT_COURSE_DOCUMENT_PATH');
329
define('WEB_DEFAULT_COURSE_DOCUMENT_PATH', 'WEB_DEFAULT_COURSE_DOCUMENT_PATH');
330
331
// Relations type with Course manager
332
define('COURSE_RELATION_TYPE_COURSE_MANAGER', 1);
333
define('SESSION_RELATION_TYPE_COURSE_MANAGER', 1);
334
335
// Relations type with Human resources manager
336
define('COURSE_RELATION_TYPE_RRHH', 1);
337
define('SESSION_RELATION_TYPE_RRHH', 1);
338
339
//User image sizes
340
define('USER_IMAGE_SIZE_ORIGINAL', 1);
341
define('USER_IMAGE_SIZE_BIG', 2);
342
define('USER_IMAGE_SIZE_MEDIUM', 3);
343
define('USER_IMAGE_SIZE_SMALL', 4);
344
345
// Relation type between users
346
define('USER_UNKNOW', 0);
347
define('USER_RELATION_TYPE_UNKNOW', 1);
348
define('USER_RELATION_TYPE_PARENT', 2); // should be deprecated is useless
349
define('USER_RELATION_TYPE_FRIEND', 3);
350
define('USER_RELATION_TYPE_GOODFRIEND', 4); // should be deprecated is useless
351
define('USER_RELATION_TYPE_ENEMY', 5); // should be deprecated is useless
352
define('USER_RELATION_TYPE_DELETED', 6);
353
define('USER_RELATION_TYPE_RRHH', 7);
354
define('USER_RELATION_TYPE_BOSS', 8);
355
356
// Gradebook link constants
357
// Please do not change existing values, they are used in the database !
358
define('GRADEBOOK_ITEM_LIMIT', 1000);
359
360
define('LINK_EXERCISE', 1);
361
define('LINK_DROPBOX', 2);
362
define('LINK_STUDENTPUBLICATION', 3);
363
define('LINK_LEARNPATH', 4);
364
define('LINK_FORUM_THREAD', 5);
365
//define('LINK_WORK',6);
366
define('LINK_ATTENDANCE', 7);
367
define('LINK_SURVEY', 8);
368
define('LINK_HOTPOTATOES', 9);
369
370
// Score display types constants
371
define('SCORE_DIV', 1);    // X / Y
372
define('SCORE_PERCENT', 2);    // XX %
373
define('SCORE_DIV_PERCENT', 3);    // X / Y (XX %)
374
define('SCORE_AVERAGE', 4);    // XX %
375
define('SCORE_DECIMAL', 5);    // 0.50  (X/Y)
376
define('SCORE_BAR', 6);    // Uses the Display::bar_progress function
377
define('SCORE_SIMPLE', 7);    // X
378
define('SCORE_IGNORE_SPLIT', 8);    //  ??
379
define('SCORE_DIV_PERCENT_WITH_CUSTOM', 9);    // X / Y (XX %) - Good!
380
define('SCORE_CUSTOM', 10);    // Good!
381
define('SCORE_DIV_SIMPLE_WITH_CUSTOM', 11);    // X - Good!
382
define('SCORE_DIV_SIMPLE_WITH_CUSTOM_LETTERS', 12);    // X - Good!
383
define('SCORE_ONLY_SCORE', 13);    // X - Good!
384
385
define('SCORE_BOTH', 1);
386
define('SCORE_ONLY_DEFAULT', 2);
387
define('SCORE_ONLY_CUSTOM', 3);
388
389
// From display.lib.php
390
391
define('MAX_LENGTH_BREADCRUMB', 100);
392
define('ICON_SIZE_ATOM', 8);
393
define('ICON_SIZE_TINY', 16);
394
define('ICON_SIZE_SMALL', 22);
395
define('ICON_SIZE_MEDIUM', 32);
396
define('ICON_SIZE_LARGE', 48);
397
define('ICON_SIZE_BIG', 64);
398
define('ICON_SIZE_HUGE', 128);
399
define('SHOW_TEXT_NEAR_ICONS', false);
400
401
// Session catalog
402
define('CATALOG_COURSES', 0);
403
define('CATALOG_SESSIONS', 1);
404
define('CATALOG_COURSES_SESSIONS', 2);
405
406
// Hook type events, pre-process and post-process.
407
// All means to be executed for both hook event types
408
define('HOOK_EVENT_TYPE_PRE', 0);
409
define('HOOK_EVENT_TYPE_POST', 1);
410
define('HOOK_EVENT_TYPE_ALL', 10);
411
412
define('CAREER_STATUS_ACTIVE', 1);
413
define('CAREER_STATUS_INACTIVE', 0);
414
415
define('PROMOTION_STATUS_ACTIVE', 1);
416
define('PROMOTION_STATUS_INACTIVE', 0);
417
418
// Group permissions
419
define('GROUP_PERMISSION_OPEN', '1');
420
define('GROUP_PERMISSION_CLOSED', '2');
421
422
// Group user permissions
423
define('GROUP_USER_PERMISSION_ADMIN', '1'); // the admin of a group
424
define('GROUP_USER_PERMISSION_READER', '2'); // a normal user
425
define('GROUP_USER_PERMISSION_PENDING_INVITATION', '3'); // When an admin/moderator invites a user
426
define('GROUP_USER_PERMISSION_PENDING_INVITATION_SENT_BY_USER', '4'); // an user joins a group
427
define('GROUP_USER_PERMISSION_MODERATOR', '5'); // a moderator
428
define('GROUP_USER_PERMISSION_ANONYMOUS', '6'); // an anonymous user
429
define('GROUP_USER_PERMISSION_HRM', '7'); // a human resources manager
430
431
define('GROUP_IMAGE_SIZE_ORIGINAL', 1);
432
define('GROUP_IMAGE_SIZE_BIG', 2);
433
define('GROUP_IMAGE_SIZE_MEDIUM', 3);
434
define('GROUP_IMAGE_SIZE_SMALL', 4);
435
define('GROUP_TITLE_LENGTH', 50);
436
437
// Exercise
438
// @todo move into a class
439
define('ALL_ON_ONE_PAGE', 1);
440
define('ONE_PER_PAGE', 2);
441
442
define('EXERCISE_FEEDBACK_TYPE_END', 0); //Feedback 		 - show score and expected answers
443
define('EXERCISE_FEEDBACK_TYPE_DIRECT', 1); //DirectFeedback - Do not show score nor answers
444
define('EXERCISE_FEEDBACK_TYPE_EXAM', 2); //NoFeedback 	 - Show score only
445
446
define('RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS', 0); //show score and expected answers
447
define('RESULT_DISABLE_NO_SCORE_AND_EXPECTED_ANSWERS', 1); //Do not show score nor answers
448
define('RESULT_DISABLE_SHOW_SCORE_ONLY', 2); //Show score only
449
define('RESULT_DISABLE_SHOW_FINAL_SCORE_ONLY_WITH_CATEGORIES', 3); //Show final score only with categories
450
define('RESULT_DISABLE_SHOW_SCORE_ATTEMPT_SHOW_ANSWERS_LAST_ATTEMPT', 4); //Show final score only with categories
451
452
define('EXERCISE_MAX_NAME_SIZE', 80);
453
454
// Question types (edit next array as well when adding values)
455
// @todo move into a class
456
define('UNIQUE_ANSWER', 1);
457
define('MULTIPLE_ANSWER', 2);
458
define('FILL_IN_BLANKS', 3);
459
define('MATCHING', 4);
460
define('FREE_ANSWER', 5);
461
define('HOT_SPOT', 6);
462
define('HOT_SPOT_ORDER', 7);
463
define('HOT_SPOT_DELINEATION', 8);
464
define('MULTIPLE_ANSWER_COMBINATION', 9);
465
define('UNIQUE_ANSWER_NO_OPTION', 10);
466
define('MULTIPLE_ANSWER_TRUE_FALSE', 11);
467
define('MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE', 12);
468
define('ORAL_EXPRESSION', 13);
469
define('GLOBAL_MULTIPLE_ANSWER', 14);
470
define('MEDIA_QUESTION', 15);
471
define('CALCULATED_ANSWER', 16);
472
define('UNIQUE_ANSWER_IMAGE', 17);
473
define('DRAGGABLE', 18);
474
define('MATCHING_DRAGGABLE', 19);
475
476
define('EXERCISE_CATEGORY_RANDOM_SHUFFLED', 1);
477
define('EXERCISE_CATEGORY_RANDOM_ORDERED', 2);
478
define('EXERCISE_CATEGORY_RANDOM_DISABLED', 0);
479
480
// Question selection type
481
define('EX_Q_SELECTION_ORDERED', 1);
482
define('EX_Q_SELECTION_RANDOM', 2);
483
define('EX_Q_SELECTION_CATEGORIES_ORDERED_QUESTIONS_ORDERED', 3);
484
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_ORDERED', 4);
485
define('EX_Q_SELECTION_CATEGORIES_ORDERED_QUESTIONS_RANDOM', 5);
486
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_RANDOM', 6);
487
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_ORDERED_NO_GROUPED', 7);
488
define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_RANDOM_NO_GROUPED', 8);
489
define('EX_Q_SELECTION_CATEGORIES_ORDERED_BY_PARENT_QUESTIONS_ORDERED', 9);
490
define('EX_Q_SELECTION_CATEGORIES_ORDERED_BY_PARENT_QUESTIONS_RANDOM', 10);
491
492
// one big string with all question types, for the validator in pear/HTML/QuickForm/Rule/QuestionType
493
define('QUESTION_TYPES',
494
    UNIQUE_ANSWER.':'.
495
    MULTIPLE_ANSWER.':'.
496
    FILL_IN_BLANKS.':'.
497
    MATCHING.':'.
498
    FREE_ANSWER.':'.
499
    HOT_SPOT.':'.
500
    HOT_SPOT_ORDER.':'.
501
    HOT_SPOT_DELINEATION.':'.
502
    MULTIPLE_ANSWER_COMBINATION.':'.
503
    UNIQUE_ANSWER_NO_OPTION.':'.
504
    MULTIPLE_ANSWER_TRUE_FALSE.':'.
505
    MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE.':'.
506
    ORAL_EXPRESSION.':'.
507
    GLOBAL_MULTIPLE_ANSWER.':'.
508
    MEDIA_QUESTION.':'.
509
    CALCULATED_ANSWER.':'.
510
    UNIQUE_ANSWER_IMAGE.':'.
511
    DRAGGABLE.':'.
512
    MATCHING_DRAGGABLE
513
);
514
515
//Some alias used in the QTI exports
516
define('MCUA', 1);
517
define('TF', 1);
518
define('MCMA', 2);
519
define('FIB', 3);
520
521
// Skills
522
define('SKILL_TYPE_REQUIREMENT', 'required');
523
define('SKILL_TYPE_ACQUIRED', 'acquired');
524
define('SKILL_TYPE_BOTH', 'both');
525
526
// Message
527
define('MESSAGE_STATUS_NEW', '0');
528
define('MESSAGE_STATUS_UNREAD', '1');
529
//2 ??
530
define('MESSAGE_STATUS_DELETED', '3');
531
define('MESSAGE_STATUS_OUTBOX', '4');
532
define('MESSAGE_STATUS_INVITATION_PENDING', '5');
533
define('MESSAGE_STATUS_INVITATION_ACCEPTED', '6');
534
define('MESSAGE_STATUS_INVITATION_DENIED', '7');
535
define('MESSAGE_STATUS_WALL', '8');
536
define('MESSAGE_STATUS_WALL_DELETE', '9');
537
define('MESSAGE_STATUS_WALL_POST', '10');
538
// Images
539
define('IMAGE_WALL_SMALL_SIZE', 200);
540
define('IMAGE_WALL_MEDIUM_SIZE', 500);
541
define('IMAGE_WALL_BIG_SIZE', 2000);
542
define('IMAGE_WALL_SMALL', 'small');
543
define('IMAGE_WALL_MEDIUM', 'medium');
544
define('IMAGE_WALL_BIG', 'big');
545
546
// Social PLUGIN PLACES
547
define('SOCIAL_LEFT_PLUGIN', 1);
548
define('SOCIAL_CENTER_PLUGIN', 2);
549
define('SOCIAL_RIGHT_PLUGIN', 3);
550
define('CUT_GROUP_NAME', 50);
551
552
/**
553
 * FormValidator Filter
554
 */
555
define('NO_HTML', 1);
556
define('STUDENT_HTML', 2);
557
define('TEACHER_HTML', 3);
558
define('STUDENT_HTML_FULLPAGE', 4);
559
define('TEACHER_HTML_FULLPAGE', 5);
560
561
// Timeline
562
define('TIMELINE_STATUS_ACTIVE', '1');
563
define('TIMELINE_STATUS_INACTIVE', '2');
564
565
// Event email template class
566
define('EVENT_EMAIL_TEMPLATE_ACTIVE',  1);
567
define('EVENT_EMAIL_TEMPLATE_INACTIVE', 0);
568
569
// Course home
570
define('SHORTCUTS_HORIZONTAL', 0);
571
define('SHORTCUTS_VERTICAL', 1);
572
573
// Image class
574
define('IMAGE_PROCESSOR', 'gd'); // 'imagick' or 'gd' strings
575
576
// Course copy
577
define('FILE_SKIP', 1);
578
define('FILE_RENAME', 2);
579
define('FILE_OVERWRITE', 3);
580
define('UTF8_CONVERT', false); //false by default
581
582
define('DOCUMENT','file');
583
define('FOLDER','folder');
584
585
define('RESOURCE_DOCUMENT', 'document');
586
define('RESOURCE_GLOSSARY', 'glossary');
587
define('RESOURCE_EVENT', 'calendar_event');
588
define('RESOURCE_LINK', 'link');
589
define('RESOURCE_COURSEDESCRIPTION', 'course_description');
590
define('RESOURCE_LEARNPATH', 'learnpath');
591
define('RESOURCE_ANNOUNCEMENT', 'announcement');
592
define('RESOURCE_FORUM', 'forum');
593
define('RESOURCE_FORUMTOPIC', 'thread');
594
define('RESOURCE_FORUMPOST', 'post');
595
define('RESOURCE_QUIZ', 'quiz');
596
define('RESOURCE_TEST_CATEGORY', 'test_category');
597
define('RESOURCE_QUIZQUESTION', 'Exercise_Question');
598
define('RESOURCE_TOOL_INTRO', 'Tool introduction');
599
define('RESOURCE_LINKCATEGORY', 'Link_Category');
600
define('RESOURCE_FORUMCATEGORY', 'Forum_Category');
601
define('RESOURCE_SCORM', 'Scorm');
602
define('RESOURCE_SURVEY', 'survey');
603
define('RESOURCE_SURVEYQUESTION', 'survey_question');
604
define('RESOURCE_SURVEYINVITATION', 'survey_invitation');
605
define('RESOURCE_WIKI', 'wiki');
606
define('RESOURCE_THEMATIC', 'thematic');
607
define('RESOURCE_ATTENDANCE', 'attendance');
608
define('RESOURCE_WORK', 'work');
609
define('RESOURCE_SESSION_COURSE', 'session_course');
610
define('RESOURCE_GRADEBOOK', 'gradebook');
611
define('ADD_THEMATIC_PLAN', 6);
612
613
// Max online users to show per page (whoisonline)
614
define('MAX_ONLINE_USERS', 12);
615
616
// Make sure the CHAMILO_LOAD_WYSIWYG constant is defined
617
// To remove CKeditor libs from HTML, set this constant to true before loading
618
if (!defined('CHAMILO_LOAD_WYSIWYG')) {
619
    define('CHAMILO_LOAD_WYSIWYG', true);
620
}
621
622
define('TOOL_PUBLIC', 'Public');
623
define('TOOL_PUBLIC_BUT_HIDDEN', 'PublicButHide');
624
define('TOOL_COURSE_ADMIN', 'courseAdmin');
625
define('TOOL_PLATFORM_ADMIN', 'platformAdmin');
626
define('TOOL_AUTHORING', 'toolauthoring');
627
define('TOOL_INTERACTION', 'toolinteraction');
628
define('TOOL_COURSE_PLUGIN', 'toolcourseplugin'); //all plugins that can be enabled in courses
629
define('TOOL_ADMIN', 'tooladmin');
630
define('TOOL_ADMIN_PLATFORM', 'tooladminplatform');
631
define('TOOL_DRH', 'tool_drh');
632
define('TOOL_STUDENT_VIEW', 'toolstudentview');
633
define('TOOL_ADMIN_VISIBLE', 'tooladminvisible');
634
635
/**
636
 * Inclusion of internationalization libraries
637
 */
638
require_once __DIR__.'/internationalization.lib.php';
639
640
/**
641
 * Returns a path to a certain resource within the Chamilo area, specifyed through a parameter.
642
 * Also, this function provides conversion between path types, in this case the input path points inside the Chamilo area too.
643
 *
644
 * See $_configuration['course_folder'] in the configuration.php to alter the WEB_COURSE_PATH and SYS_COURSE_PATH parameters.
645
646
 * @param string $path (optional)   A path which type is to be converted. Also, it may be a defined constant for a path.
647
 * This parameter has meaning when $type parameter has one of the following values: TO_WEB, TO_SYS, TO_REL. Otherwise it is ignored.
648
 * @return string                   The requested path or the converted path.
649
 *
650
 *
651
 * Notes about the current behaviour model:
652
 * 1. Windows back-slashes are converted to slashes in the result.
653
 * 2. A semi-absolute web-path is detected by its leading slash. On Linux systems, absolute system paths start with
654
 * a slash too, so an additional check about presence of leading system server base is implemented. For example, the function is
655
 * able to distinguish type difference between /var/www/chamilo/courses/ (SYS) and /chamilo/courses/ (REL).
656
 * 3. The function api_get_path() returns only these three types of paths, which in some sense are absolute. The function has
657
 * no a mechanism for processing relative web/system paths, such as: lesson01.html, ./lesson01.html, ../css/my_styles.css.
658
 * It has not been identified as needed yet.
659
 * 4. Also, resolving the meta-symbols "." and ".." within paths has not been implemented, it is to be identified as needed.
660
 *
661
 * For examples go to: *
662
 * See main/admin/system_status.php?section=paths
663
 *
664
 * Vchamilo changes : allow using an alternate configuration
665
 * to get vchamilo  instance paths
666
*/
667
function api_get_path($path = '', $configuration = [])
668
{
669
    global $paths;
670
671
    // get proper configuration data if exists
672
    global $_configuration;
673
674
    if (empty($configuration)) {
675
        $configuration = (array) $_configuration;
676
    }
677
678
    $course_folder = 'courses/';
679
    $root_sys = Container::getRootDir();
680
681
    // Resolve master hostname.
682
    if (!empty($configuration) && array_key_exists('root_web', $configuration)) {
683
        $root_web = $configuration['root_web'];
684
    } else {
685
        $root_web = Container::getUrlGenerator()->generate(
686
            'home',
687
            []
688
        );
689
    }
690
691
    if (isset($configuration['multiple_access_urls']) && $configuration['multiple_access_urls']) {
692
        // To avoid that the api_get_access_url() function fails since global.inc.php also calls the main_api.lib.php
693
        if (isset($configuration['access_url']) && !empty($configuration['access_url'])) {
694
            // We look into the DB the function api_get_access_url
695
            $url_info = api_get_access_url($configuration['access_url']);
696
            // Avoid default value
697
            $defaulValues = ['http://localhost/', 'https://localhost/'];
698
            if (!empty($url_info['url']) && !in_array($url_info['url'], $defaulValues)) {
699
                $root_web = $url_info['active'] == 1 ? $url_info['url'] : $configuration['root_web'];
700
            }
701
        }
702
    }
703
704
    if (empty($paths)) {
705
        $paths = [];
706
    }
707
708
    $paths = [];
709
    // Initialise cache with default values.
710
    if (!array_key_exists($root_web, $paths)) {
711
        $paths[$root_web] = array(
712
            WEB_PATH => '',
713
            SYS_PATH => '',
714
            REL_PATH => '',
715
            WEB_COURSE_PATH => '',
716
            SYS_COURSE_PATH => '',
717
            REL_COURSE_PATH => '',
718
            WEB_CODE_PATH => 'main/',
719
            SYS_CODE_PATH => 'main/',
720
            REL_CODE_PATH => '/main/',
721
            SYS_LANG_PATH => 'lang/',
722
            WEB_IMG_PATH => 'img/',
723
            WEB_CSS_PATH => 'web/css/',
724
            SYS_CSS_PATH => 'app/Resources/public/css/',
725
            SYS_PLUGIN_PATH => 'plugin/',
726
            WEB_PLUGIN_PATH => 'plugin/',
727
            SYS_ARCHIVE_PATH => 'app/cache/',
728
            WEB_ARCHIVE_PATH => 'app/cache/',
729
            SYS_HOME_PATH => 'app/home/',
730
            WEB_HOME_PATH => 'app/home/',
731
            REL_HOME_PATH => 'app/home/',
732
            SYS_APP_PATH => 'app/',
733
            WEB_APP_PATH => 'app/',
734
            SYS_UPLOAD_PATH => 'app/upload/',
735
            SYS_INC_PATH => 'inc/',
736
            CONFIGURATION_PATH => 'app/config/',
737
            LIBRARY_PATH => 'inc/lib/',
738
            WEB_LIBRARY_PATH => 'inc/lib/',
739
            WEB_LIBRARY_JS_PATH => 'inc/lib/javascript/',
740
            WEB_AJAX_PATH => 'inc/ajax/',
741
            SYS_TEST_PATH => 'tests/',
742
            WEB_TEMPLATE_PATH => 'template/',
743
            SYS_TEMPLATE_PATH => 'template/',
744
            WEB_UPLOAD_PATH => 'app/upload/',
745
            WEB_PUBLIC_PATH => 'web/',
746
            SYS_PUBLIC_PATH => 'web/',
747
            WEB_FONTS_PATH => 'fonts/',
748
            SYS_FONTS_PATH => 'fonts/',
749
        );
750
    }
751
752
    $isInitialized = [];
753
    $course_folder = isset($configuration['course_folder']) ? $configuration['course_folder'] : $course_folder;
754
    $root_rel = isset($configuration['url_append']) ? $configuration['url_append'] : '';
755
756
    // Web server base and system server base.
757
    if (!array_key_exists($root_web, $isInitialized)) {
758
        // process absolute global roots
759
        $code_folder = 'main';
760
        // Support for the installation process.
761
        // Developers might use the function api_get_path() directly or indirectly (this is difficult to be traced), at the moment when
762
        // configuration has not been created yet. This is why this function should be upgraded to return correct results in this case.
763
764
        // Dealing with trailing slashes.
765
        $slashed_root_web = api_add_trailing_slash($root_web);
766
767
        $root_sys = api_add_trailing_slash($root_sys);
768
        $root_rel = api_add_trailing_slash($root_rel);
769
        $code_folder = api_add_trailing_slash($code_folder);
770
        $course_folder = api_add_trailing_slash($course_folder);
771
772
        // Initialization of a table that contains common-purpose paths.
773
        $paths[$root_web][REL_PATH] = $root_rel;
774
        $paths[$root_web][REL_COURSE_PATH] = $root_rel.$course_folder;
775
        $paths[$root_web][REL_DEFAULT_COURSE_DOCUMENT_PATH] = $paths[$root_web][REL_PATH].'main/default_course_document/';
776
777
        $paths[$root_web][WEB_PATH] = $slashed_root_web;
778
        $paths[$root_web][WEB_CODE_PATH] = $paths[$root_web][WEB_PATH].$code_folder;
779
        $paths[$root_web][WEB_COURSE_PATH] = $paths[$root_web][WEB_PATH].$course_folder;
780
        $paths[$root_web][WEB_DEFAULT_COURSE_DOCUMENT_PATH] = $paths[$root_web][WEB_CODE_PATH].'default_course_document/';
781
        $paths[$root_web][WEB_APP_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_APP_PATH];
782
        $paths[$root_web][WEB_PLUGIN_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_PLUGIN_PATH];
783
        $paths[$root_web][WEB_ARCHIVE_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_ARCHIVE_PATH];
784
785
        $paths[$root_web][WEB_CSS_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_CSS_PATH];
786
        $paths[$root_web][WEB_IMG_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_IMG_PATH];
787
        $paths[$root_web][WEB_LIBRARY_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_LIBRARY_PATH];
788
        $paths[$root_web][WEB_LIBRARY_JS_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_LIBRARY_JS_PATH];
789
        $paths[$root_web][WEB_AJAX_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_AJAX_PATH];
790
        $paths[$root_web][WEB_FONTS_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_FONTS_PATH];
791
        $paths[$root_web][WEB_TEMPLATE_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_TEMPLATE_PATH];
792
        $paths[$root_web][WEB_UPLOAD_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_UPLOAD_PATH];
793
        $paths[$root_web][WEB_PUBLIC_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][WEB_PUBLIC_PATH];
794
        $paths[$root_web][WEB_HOME_PATH] = $paths[$root_web][WEB_PATH].$paths[$root_web][REL_HOME_PATH];
795
796
        $paths[$root_web][SYS_PATH] = $root_sys;
797
        $paths[$root_web][SYS_CODE_PATH] = $root_sys.$code_folder;
798
        $paths[$root_web][SYS_TEST_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_TEST_PATH];
799
        $paths[$root_web][SYS_TEMPLATE_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_TEMPLATE_PATH];
800
        $paths[$root_web][SYS_PUBLIC_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_PUBLIC_PATH];
801
        $paths[$root_web][SYS_CSS_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_CSS_PATH];
802
        $paths[$root_web][SYS_FONTS_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_FONTS_PATH];
803
        $paths[$root_web][SYS_ARCHIVE_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_ARCHIVE_PATH];
804
        $paths[$root_web][SYS_APP_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_APP_PATH];
805
        $paths[$root_web][SYS_COURSE_PATH] = $paths[$root_web][SYS_APP_PATH].$course_folder;
806
        $paths[$root_web][SYS_UPLOAD_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_UPLOAD_PATH];
807
        $paths[$root_web][SYS_LANG_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_LANG_PATH];
808
        $paths[$root_web][SYS_HOME_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_HOME_PATH];
809
        $paths[$root_web][SYS_PLUGIN_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_PLUGIN_PATH];
810
        $paths[$root_web][SYS_INC_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_INC_PATH];
811
812
        $paths[$root_web][LIBRARY_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][LIBRARY_PATH];
813
        $paths[$root_web][CONFIGURATION_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][CONFIGURATION_PATH];
814
815
        global $virtualChamilo;
816
        if (!empty($virtualChamilo)) {
817
            $paths[$root_web][SYS_ARCHIVE_PATH] = api_add_trailing_slash($virtualChamilo[SYS_ARCHIVE_PATH]);
818
            $paths[$root_web][SYS_HOME_PATH] = api_add_trailing_slash($virtualChamilo[SYS_HOME_PATH]);
819
            $paths[$root_web][SYS_COURSE_PATH] = api_add_trailing_slash($virtualChamilo[SYS_COURSE_PATH]);
820
            $paths[$root_web][SYS_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[SYS_UPLOAD_PATH]);
821
            //$paths[$root_web][REL_PATH] = $virtualChamilo[REL_PATH];
822
            //$paths[$root_web][REL_COURSE_PATH] = $virtualChamilo[REL_COURSE_PATH];
823
        }
824
825
        $isInitialized[$root_web] = true;
826
    }
827
828
    $path = trim($path);
829
830
    // Retrieving a common-purpose path.
831
    if (isset($paths[$root_web][$path])) {
832
        return $paths[$root_web][$path];
833
    }
834
835
    // Second purification.
836
837
    // Replacing Windows back slashes.
838
    $path = str_replace('\\', '/', $path);
839
    // Query strings sometimes mighth wrongly appear in non-URLs.
840
    // Let us check remove them from all types of paths.
841
    if (($pos = strpos($path, '?')) !== false) {
842
        $path = substr($path, 0, $pos);
843
    }
844
845
    // Detection of the input path type. Conversion to semi-absolute type ( /chamilo/main/inc/.... ).
846
847
    if (preg_match(VALID_WEB_PATH, $path)) {
848
        // A special case: When a URL points to the document download script directly, without
849
        // mod-rewrite translation, we have to translate it into an "ordinary" web path.
850
        // For example:
851
        // http://localhost/chamilo/main/document/download.php?doc_url=/image.png&cDir=/
852
        // becomes
853
        // http://localhost/chamilo/courses/TEST/document/image.png
854
        // TEST is a course directory name, so called "system course code".
855
        if (strpos($path, 'download.php') !== false) { // Fast detection first.
856
            $path = urldecode($path);
857
            if (preg_match('/(.*)main\/document\/download.php\?doc_url=\/(.*)&cDir=\/(.*)?/', $path, $matches)) {
858
                $sys_course_code =
859
                    isset($_SESSION['_course']['sysCode'])  // User is inside a course?
860
                        ? $_SESSION['_course']['sysCode']   // Yes, then use course's directory name.
861
                        : '{SYS_COURSE_CODE}';              // No, then use a fake code, it may be processed later.
862
                $path = $matches[1].'courses/'.$sys_course_code.'/document/'.str_replace('//', '/', $matches[3].'/'.$matches[2]);
863
            }
864
        }
865
        // Replacement of the present web server base with a slash '/'.
866
        $path = preg_replace(VALID_WEB_SERVER_BASE, '/', $path);
867
    }
868
869
    // Path now is semi-absolute. It is convenient at this moment repeated slashes to be removed.
870
    $path = preg_replace(REPEATED_SLASHES_PURIFIER, '/', $path);
871
872
    return $path;
873
}
874
875
/**
876
 * Gets a modified version of the path for the CDN, if defined in
877
 * configuration.php
878
 * @param string $web_path The path of the resource without CDN
879
 * @return string The path of the resource converted to CDN
880
 * @author Yannick Warnier <[email protected]>
881
 */
882
function api_get_cdn_path($web_path)
883
{
884
    global $_configuration;
885
    $web_root = api_get_path(WEB_PATH);
886
    $ext = substr($web_path,strrpos($web_path,'.'));
887
    if (isset($ext[2])) { // faster version of strlen to check if len>2
888
        // Check for CDN definitions
889
        if (!empty($_configuration['cdn_enable']) && !empty($ext)) {
890
            foreach ($_configuration['cdn'] as $host => $exts) {
891
                if (in_array($ext,$exts)) {
892
                    //Use host as defined in $_configuration['cdn'], without
893
                    // trailing slash
894
                    return str_replace($web_root,$host.'/',$web_path);
895
                }
896
            }
897
        }
898
    }
899
    return $web_path;
900
}
901
902
/**
903
 * @return bool Return true if CAS authentification is activated
904
 *
905
 */
906
function api_is_cas_activated() {
907
    return api_get_setting('cas_activate') == "true";
908
}
909
910
/**
911
 * @return bool     Return true if LDAP authentification is activated
912
 *
913
 */
914
function api_is_ldap_activated() {
915
    global $extAuthSource;
916
    return is_array($extAuthSource[LDAP_AUTH_SOURCE]);
917
}
918
919
/**
920
 * @return bool     Return true if Facebook authentification is activated
921
 *
922
 */
923
function api_is_facebook_auth_activated() {
924
    global $_configuration;
925
    return (isset($_configuration['facebook_auth']) && $_configuration['facebook_auth'] == 1);
926
}
927
928
/**
929
 * This function checks whether a given path points inside the system.
930
 * @param string $path      The path to be tested.
931
 * It should be full path, web-absolute (WEB), semi-absolute (REL) or system-absolyte (SYS).
932
 * @return bool             Returns true when the given path is inside the system, false otherwise.
933
 */
934
function api_is_internal_path($path) {
935
    $path = str_replace('\\', '/', trim($path));
936
    if (empty($path)) {
937
        return false;
938
    }
939
    if (strpos($path, api_remove_trailing_slash(api_get_path(WEB_PATH))) === 0) {
940
        return true;
941
    }
942
    if (strpos($path, api_remove_trailing_slash(api_get_path(SYS_PATH))) === 0) {
943
        return true;
944
    }
945
    $server_base_web = api_remove_trailing_slash(api_get_path(REL_PATH));
946
    $server_base_web = empty($server_base_web) ? '/' : $server_base_web;
947
    if (strpos($path, $server_base_web) === 0) {
948
        return true;
949
    }
950
    return false;
951
}
952
953
/**
954
 * Adds to a given path a trailing slash if it is necessary (adds "/" character at the end of the string).
955
 * @param string $path          The input path.
956
 * @return string               Returns the modified path.
957
 */
958
function api_add_trailing_slash($path) {
959
    return substr($path, -1) == '/' ? $path : $path.'/';
960
}
961
962
/**
963
 * Removes from a given path the trailing slash if it is necessary (removes "/" character from the end of the string).
964
 * @param string $path          The input path.
965
 * @return string               Returns the modified path.
966
 */
967
function api_remove_trailing_slash($path) {
968
    return substr($path, -1) == '/' ? substr($path, 0, -1) : $path;
969
}
970
971
/**
972
 * Checks the RFC 3986 syntax of a given URL.
973
 * @param string $url       The URL to be checked.
974
 * @param bool $absolute    Whether the URL is absolute (beginning with a scheme such as "http:").
975
 * @return string|false             Returns the URL if it is valid, FALSE otherwise.
976
 * This function is an adaptation from the function valid_url(), Drupal CMS.
977
 * @link http://drupal.org
978
 * Note: The built-in function filter_var($urs, FILTER_VALIDATE_URL) has a bug for some versions of PHP.
979
 * @link http://bugs.php.net/51192
980
 */
981
function api_valid_url($url, $absolute = false) {
982
    if ($absolute) {
983
        if (preg_match("
984
            /^                                                      # Start at the beginning of the text
985
            (?:ftp|https?|feed):\/\/                                # Look for ftp, http, https or feed schemes
986
            (?:                                                     # Userinfo (optional) which is typically
987
                (?:(?:[\w\.\-\+!$&'\(\)*\+,;=]|%[0-9a-f]{2})+:)*    # a username or a username and password
988
                (?:[\w\.\-\+%!$&'\(\)*\+,;=]|%[0-9a-f]{2})+@        # combination
989
            )?
990
            (?:
991
                (?:[a-z0-9\-\.]|%[0-9a-f]{2})+                      # A domain name or a IPv4 address
992
                |(?:\[(?:[0-9a-f]{0,4}:)*(?:[0-9a-f]{0,4})\])       # or a well formed IPv6 address
993
            )
994
            (?::[0-9]+)?                                            # Server port number (optional)
995
            (?:[\/|\?]
996
                (?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2}) # The path and query (optional)
997
            *)?
998
            $/xi", $url)) {
999
            return $url;
1000
        }
1001
        return false;
1002
    } else {
1003
        return preg_match("/^(?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2})+$/i", $url) ? $url : false;
1004
    }
1005
}
1006
1007
/**
1008
 * Checks whether a given string looks roughly like an email address.
1009
 *
1010
 * @param string $address   The e-mail address to be checked.
1011
 * @return mixed            Returns the e-mail if it is valid, FALSE otherwise.
1012
 */
1013
function api_valid_email($address)
1014
{
1015
    return filter_var($address, FILTER_VALIDATE_EMAIL);
1016
}
1017
1018
/* PROTECTION FUNCTIONS
1019
   Use these functions to protect your scripts. */
1020
1021
/**
1022
 * Function used to protect a course script.
1023
 * The function blocks access when
1024
 * - there is no $_SESSION["_course"] defined; or
1025
 * - $is_allowed_in_course is set to false (this depends on the course
1026
 * visibility and user status).
1027
 *
1028
 * This is only the first proposal, test and improve!
1029
 * @param boolean       Option to print headers when displaying error message. Default: false
1030
 * @param boolean       Whether session admins should be allowed or not.
1031
 * @return boolean      True if the user has access to the current course or is out of a course context, false otherwise
1032
 * @todo replace global variable
1033
 * @author Roan Embrechts
1034
 */
1035
function api_protect_course_script($print_headers = false, $allow_session_admins = false, $allow_drh = false)
1036
{
1037
    $is_allowed_in_course = api_is_allowed_in_course();
1038
1039
    $is_visible = false;
1040
    $course_info = api_get_course_info();
1041
1042
    if (empty($course_info)) {
1043
        api_not_allowed($print_headers);
1044
        return false;
1045
    }
1046
1047
    if (api_is_drh()) {
1048
        return true;
1049
    }
1050
1051
    if (api_is_platform_admin($allow_session_admins)) {
1052
        return true;
1053
    }
1054
1055
    if (isset($course_info) && isset($course_info['visibility'])) {
1056
        switch ($course_info['visibility']) {
1057
            default:
1058 View Code Duplication
            case COURSE_VISIBILITY_CLOSED:
1059
                // Completely closed: the course is only accessible to the teachers. - 0
1060
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1061
                    $is_visible = true;
1062
                }
1063
                break;
1064 View Code Duplication
            case COURSE_VISIBILITY_REGISTERED:
1065
                // Private - access authorized to course members only - 1
1066
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1067
                    $is_visible = true;
1068
                }
1069
                break;
1070 View Code Duplication
            case COURSE_VISIBILITY_OPEN_PLATFORM:
1071
                // Open - access allowed for users registered on the platform - 2
1072
                if (api_get_user_id() && !api_is_anonymous() && $is_allowed_in_course) {
1073
                    $is_visible = true;
1074
                }
1075
                break;
1076
            case COURSE_VISIBILITY_OPEN_WORLD:
1077
                //Open - access allowed for the whole world - 3
1078
                $is_visible = true;
1079
                break;
1080
            case COURSE_VISIBILITY_HIDDEN:
1081
                //Completely closed: the course is only accessible to the teachers. - 0
1082
                if (api_is_platform_admin()) {
1083
                    $is_visible = true;
1084
                }
1085
                break;
1086
        }
1087
1088
        //If password is set and user is not registered to the course then the course is not visible
1089
        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...
1090
            isset($course_info['registration_code']) &&
1091
            !empty($course_info['registration_code'])
1092
        ) {
1093
            $is_visible = false;
1094
        }
1095
    }
1096
1097
    // Check session visibility
1098
    $session_id = api_get_session_id();
1099
1100
    if (!empty($session_id)) {
1101
        //$is_allowed_in_course was set in local.inc.php
1102
        if (!$is_allowed_in_course) {
1103
            $is_visible = false;
1104
        }
1105
    }
1106
1107
    if (!$is_visible) {
1108
        api_not_allowed($print_headers);
1109
        return false;
1110
    }
1111
    return true;
1112
}
1113
1114
/**
1115
 * Function used to protect an admin script.
1116
 *
1117
 * The function blocks access when the user has no platform admin rights
1118
 * with an error message printed on default output
1119
 * @param bool Whether to allow session admins as well
1120
 * @param bool Whether to allow HR directors as well
1121
 * @param string An optional message (already passed through get_lang)
1122
 * @return bool True if user is allowed, false otherwise.
1123
 * The function also outputs an error message in case not allowed
1124
 * @author Roan Embrechts (original author)
1125
 */
1126
function api_protect_admin_script($allow_sessions_admins = false, $allow_drh = false, $message = null)
1127
{
1128
    if (!api_is_platform_admin($allow_sessions_admins, $allow_drh)) {
1129
        api_not_allowed(true, $message);
1130
        return false;
1131
    }
1132
    return true;
1133
}
1134
1135
/**
1136
 * Function used to protect a teacher script.
1137
 * The function blocks access when the user has no teacher rights.
1138
 *
1139
 * @author Yoselyn Castillo
1140
 */
1141
function api_protect_teacher_script($allow_sessions_admins = false)
1142
{
1143
    if (!api_is_allowed_to_edit()) {
1144
        api_not_allowed(true);
1145
        return false;
1146
    }
1147
    return true;
1148
}
1149
1150
/**
1151
 * Function used to prevent anonymous users from accessing a script.
1152
 * @param bool|true $printHeaders
1153
 * @author Roan Embrechts
1154
 *
1155
 * @return bool
1156
 */
1157
function api_block_anonymous_users($printHeaders = true)
1158
{
1159
    $user = api_get_user_info();
1160 View Code Duplication
    if (!(isset($user['user_id']) && $user['user_id']) || api_is_anonymous($user['user_id'], true)) {
1161
        api_not_allowed($printHeaders);
1162
        return false;
1163
    }
1164
1165
    return true;
1166
}
1167
1168
/**
1169
 * @return array with the navigator name and version
1170
 */
1171
function api_get_navigator() {
1172
    $navigator = 'Unknown';
1173
    $version = 0;
1174
1175
    if (!isset($_SERVER['HTTP_USER_AGENT'])) {
1176
        return array('name' => 'Unknown', 'version' => '0.0.0');
1177
    }
1178
1179
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') !== false) {
1180
        $navigator = 'Opera';
1181
        list (, $version) = explode('Opera', $_SERVER['HTTP_USER_AGENT']);
1182 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {
1183
        $navigator = 'Internet Explorer';
1184
        list (, $version) = explode('MSIE', $_SERVER['HTTP_USER_AGENT']);
1185
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome') !== false) {
1186
        $navigator = 'Chrome';
1187
        list (, $version) = explode('Chrome', $_SERVER['HTTP_USER_AGENT']);
1188 View Code Duplication
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'safari') !== false) {
1189
        $navigator = 'Safari';
1190
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1191
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Gecko') !== false) {
1192
        $navigator = 'Mozilla';
1193
        list (, $version) = explode('; rv:', $_SERVER['HTTP_USER_AGENT']);
1194 View Code Duplication
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Netscape') !== false) {
1195
        $navigator = 'Netscape';
1196
        list (, $version) = explode('Netscape', $_SERVER['HTTP_USER_AGENT']);
1197
    } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Konqueror') !== false) {
1198
        $navigator = 'Konqueror';
1199
        list (, $version) = explode('Konqueror', $_SERVER['HTTP_USER_AGENT']);
1200 View Code Duplication
    } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'applewebkit') !== false) {
1201
        $navigator = 'AppleWebKit';
1202
        list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
1203
    }
1204
    $version = str_replace('/', '', $version);
1205
    if (strpos($version, '.') === false) {
1206
        $version = number_format(doubleval($version), 1);
1207
    }
1208
    $return = array('name' => $navigator, 'version' => $version);
1209
    return $return;
1210
}
1211
1212
/**
1213
 * @return True if user self registration is allowed, false otherwise.
1214
 */
1215
function api_is_self_registration_allowed()
1216
{
1217
    return isset($GLOBALS['allowSelfReg']) ? $GLOBALS['allowSelfReg'] : false;
1218
}
1219
1220
/**
1221
 * This function returns the id of the user which is stored in the $_user array.
1222
 *
1223
 * example: The function can be used to check if a user is logged in
1224
 *          if (api_get_user_id())
1225
 * @return integer the id of the current user, 0 if is empty
1226
 */
1227
function api_get_user_id()
1228
{
1229
    $userInfo = Session::read('_user');
1230
    if ($userInfo && isset($userInfo['user_id'])) {
1231
        return $userInfo['user_id'];
1232
    }
1233
    return 0;
1234
}
1235
1236
/**
1237
 * Gets the list of courses a specific user is subscribed to
1238
 * @param int       User ID
1239
 * @param boolean   $fetch_session Whether to get session courses or not - NOT YET IMPLEMENTED
1240
 * @return array    Array of courses in the form [0]=>('code'=>xxx,'db'=>xxx,'dir'=>xxx,'status'=>d)
1241
 */
1242
function api_get_user_courses($userid, $fetch_session = true)
1243
{
1244
    // Get out if not integer
1245
    if ($userid != strval(intval($userid))) {
1246
        return array();
1247
    }
1248
1249
    $t_course = Database::get_main_table(TABLE_MAIN_COURSE);
1250
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1251
1252
    $sql = "SELECT cc.id as real_id, cc.code code, cc.directory dir, cu.status status
1253
            FROM    $t_course       cc,
1254
                    $t_course_user   cu
1255
            WHERE
1256
                cc.id = cu.c_id AND
1257
                cu.user_id = '".$userid."' AND
1258
                cu.relation_type<>".COURSE_RELATION_TYPE_RRHH." ";
1259
    $result = Database::query($sql);
1260
    if ($result === false) {
1261
        return array();
1262
    }
1263
1264
    $courses = array();
1265
    while ($row = Database::fetch_array($result)) {
1266
        // we only need the database name of the course
1267
        $courses[] = $row;
1268
    }
1269
1270
    return $courses;
1271
}
1272
1273
/**
1274
 * Formats user information into a standard array
1275
 * This function should be only used inside api_get_user_info()
1276
 *
1277
 * @param array Non-standard user array
1278
 * @param bool $add_password
1279
 *
1280
 * @return array Standard user array
1281
 */
1282
function _api_format_user($user, $add_password = false)
1283
{
1284
    $result = array();
1285
1286
    $firstname = null;
1287
    $lastname = null;
1288
    if (isset($user['firstname']) && isset($user['lastname'])) {
1289
        $firstname = $user['firstname'];
1290
        $lastname = $user['lastname'];
1291
    } elseif (isset($user['firstName']) && isset($user['lastName'])) {
1292
        $firstname = isset($user['firstName']) ? $user['firstName'] : null;
1293
        $lastname = isset($user['lastName']) ? $user['lastName'] : null;
1294
    }
1295
1296
    $result['complete_name'] = api_get_person_name($firstname, $lastname);
1297
1298
    $result['complete_name_with_username'] = $result['complete_name'];
1299
1300
    if (!empty($user['username'])) {
1301
        $result['complete_name_with_username'] = $result['complete_name'].' ('.$user['username'].')';
1302
    }
1303
1304
    $result['firstname'] = $firstname;
1305
    $result['lastname'] = $lastname;
1306
1307
    // Kept for historical reasons
1308
    $result['firstName'] = $firstname;
1309
    $result['lastName'] = $lastname;
1310
1311
    $attributes = array(
1312
        'phone',
1313
        'address',
1314
        'picture_uri',
1315
        'official_code',
1316
        'status',
1317
        'active',
1318
        'auth_source',
1319
        'username',
1320
        'theme',
1321
        'language',
1322
        'creator_id',
1323
        'registration_date',
1324
        'hr_dept_id',
1325
        'expiration_date',
1326
        'last_login'
1327
    );
1328
    if (api_get_setting('extended_profile') === 'true') {
1329
        $attributes[] = 'competences';
1330
        $attributes[] = 'diplomas';
1331
        $attributes[] = 'teach';
1332
        $attributes[] = 'openarea';
1333
    }
1334
1335
    foreach ($attributes as $attribute) {
1336
        $result[$attribute] = isset($user[$attribute]) ? $user[$attribute] : null;
1337
    }
1338
1339
    if (isset($user['email'])) {
1340
        $result['mail'] = isset($user['email']) ? $user['email'] : null;
1341
        $result['email'] = isset($user['email'])? $user['email'] : null;
1342
    } else {
1343
        $result['mail'] = isset($user['mail']) ? $user['mail'] : null;
1344
        $result['email'] = isset($user['mail'])? $user['mail'] : null;
1345
    }
1346
    $user_id = intval($user['user_id']);
1347
    // Maintain the user_id index for backwards compatibility
1348
    $result['user_id'] = $result['id'] = $user_id;
1349
    $result['last_login'] = $user['last_login'];
1350
1351
    // Getting user avatar.
1352
    $originalFile = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_ORIGINAL, null, $result);
1353
    $smallFile = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_SMALL, null, $result);
1354
    $mediumFile = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_MEDIUM, null, $result);
1355
1356
    $result['avatar'] = $originalFile;
1357
    $avatarString = explode('?', $originalFile);
1358
    $result['avatar_no_query'] = reset($avatarString);
1359
    $result['avatar_small'] = $smallFile;
1360
    $result['avatar_medium'] = $mediumFile;
1361
1362
    if (isset($user['user_is_online'])) {
1363
        $result['user_is_online'] = $user['user_is_online'] == true ? 1 : 0;
1364
    }
1365
    if (isset($user['user_is_online_in_chat'])) {
1366
        $result['user_is_online_in_chat'] = intval($user['user_is_online_in_chat']);
1367
    }
1368
1369
    if ($add_password) {
1370
        $result['password'] = $user['password'];
1371
    }
1372
1373
    if (isset($result['profile_completed'])) {
1374
        $result['profile_completed'] = $user['profile_completed'];
1375
    }
1376
1377
    $result['profile_url'] = api_get_path(WEB_CODE_PATH).'social/profile.php?u='.$user_id;
1378
1379
    if (isset($user['extra'])) {
1380
        $result['extra'] = $user['extra'];
1381
    }
1382
1383
    return $result;
1384
}
1385
1386
/**
1387
 * Finds all the information about a user.
1388
 * If no parameter is passed you find all the information about the current user.
1389
 * @param int  $user_id
1390
 * @param bool $checkIfUserOnline
1391
 * @param bool $showPassword
1392
 * @param bool $loadExtraData
1393
 * @param bool $loadOnlyVisibleExtraData Get the user extra fields that are visible
1394
 * @return array $user_info user_id, lastname, firstname, username, email, etc
1395
 * @author Patrick Cool <[email protected]>
1396
 * @author Julio Montoya
1397
 * @version 21 September 2004
1398
 */
1399
function api_get_user_info(
1400
    $user_id = 0,
1401
    $checkIfUserOnline = false,
1402
    $showPassword = false,
1403
    $loadExtraData = false,
1404
    $loadOnlyVisibleExtraData = false
1405
) {
1406
    if (empty($user_id)) {
1407
        $userFromSession = Session::read('_user');
1408
        if (isset($userFromSession)) {
1409
            return _api_format_user($userFromSession);
1410
        }
1411
1412
        return false;
1413
    }
1414
1415
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1416
            WHERE id='".intval($user_id)."'";
1417
    $result = Database::query($sql);
1418
    if (Database::num_rows($result) > 0) {
1419
        $result_array = Database::fetch_array($result);
1420
        if ($checkIfUserOnline) {
1421
            $use_status_in_platform = UserManager::user_is_online($user_id);
1422
1423
            $result_array['user_is_online'] = $use_status_in_platform;
1424
            $user_online_in_chat = 0;
1425
1426
            if ($use_status_in_platform) {
1427
                $user_status = UserManager::get_extra_user_data_by_field(
1428
                    $user_id,
1429
                    'user_chat_status',
1430
                    false,
1431
                    true
1432
                );
1433
                if (intval($user_status['user_chat_status']) == 1) {
1434
                    $user_online_in_chat = 1;
1435
                }
1436
            }
1437
            $result_array['user_is_online_in_chat'] = $user_online_in_chat;
1438
        }
1439
1440
        if ($loadExtraData) {
1441
            $fieldValue = new ExtraFieldValue('user');
1442
1443
            $result_array['extra'] = $fieldValue->getAllValuesForAnItem(
1444
                $user_id,
1445
                $loadOnlyVisibleExtraData
1446
            );
1447
        }
1448
        $user = _api_format_user($result_array, $showPassword);
1449
1450
        return $user;
1451
    }
1452
    return false;
1453
}
1454
1455
/**
1456
 * @param int $userId
1457
 * @return User
1458
 */
1459
function api_get_user_entity($userId)
1460
{
1461
    /** @var \Chamilo\UserBundle\Repository\UserRepository $repo */
1462
    $repo = Database::getManager()->getRepository('ChamiloUserBundle:User');
1463
1464
    return $repo->find($userId);
1465
}
1466
1467
/**
1468
 * @param int $courseId
1469
 *
1470
 * @return Course
1471
 */
1472
function api_get_user_course_entity($courseId = 0)
1473
{
1474
    if (empty($courseId)) {
1475
        $courseId = api_get_course_int_id();
1476
    }
1477
    return CourseManager::getManager()->find($courseId);
1478
}
1479
1480
/**
1481
 * Finds all the information about a user from username instead of user id
1482
 * @param string $username
1483
 * @return array $user_info array user_id, lastname, firstname, username, email
1484
 * @author Yannick Warnier <[email protected]>
1485
 */
1486 View Code Duplication
function api_get_user_info_from_username($username = '')
1487
{
1488
    if (empty($username)) {
1489
        return false;
1490
    }
1491
    $username = trim($username);
1492
1493
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1494
            WHERE username='".Database::escape_string($username)."'";
1495
    $result = Database::query($sql);
1496
    if (Database::num_rows($result) > 0) {
1497
        $result_array = Database::fetch_array($result);
1498
        return _api_format_user($result_array);
1499
    }
1500
    return false;
1501
}
1502
1503
/**
1504
 * Get first user with an email
1505
 * @param string $email
1506
 * @return array|bool
1507
 */
1508 View Code Duplication
function api_get_user_info_from_email($email = '')
1509
{
1510
    if (empty($email)) {
1511
        return false;
1512
    }
1513
    $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)."
1514
            WHERE email ='".Database::escape_string($email)."' LIMIT 1";
1515
    $result = Database::query($sql);
1516
    if (Database::num_rows($result) > 0) {
1517
        $result_array = Database::fetch_array($result);
1518
        return _api_format_user($result_array);
1519
    }
1520
1521
    return false;
1522
}
1523
1524
/**
1525
 * @return string
1526
 */
1527
function api_get_course_id()
1528
{
1529
    return Session::read('_cid', null);
1530
}
1531
1532
/**
1533
 * Returns the current course id (integer)
1534
 * @param   string  $code   Optional course code
1535
 * @return int
1536
 */
1537
function api_get_course_int_id($code = null)
1538
{
1539 View Code Duplication
    if (!empty($code)) {
1540
        $code = Database::escape_string($code);
1541
        $row = Database::select(
1542
            'id',
1543
            Database::get_main_table(TABLE_MAIN_COURSE),
1544
            array('where'=> array('code = ?' => array($code))),
1545
            'first'
1546
        );
1547
1548
        if (is_array($row) && isset($row['id'])) {
1549
            return $row['id'];
1550
        } else {
1551
            return false;
1552
        }
1553
    }
1554
    return Session::read('_real_cid', 0);
1555
}
1556
1557
/**
1558
 * Returns the current course directory
1559
 *
1560
 * This function relies on api_get_course_info()
1561
 * @param string    The course code - optional (takes it from session if not given)
1562
 * @return string   The directory where the course is located inside the Chamilo "courses" directory
1563
 * @author Yannick Warnier <[email protected]>
1564
 */
1565
function api_get_course_path($course_code = null)
1566
{
1567
    $info = !empty($course_code) ? api_get_course_info($course_code) : api_get_course_info();
1568
    return $info['path'];
1569
}
1570
1571
/**
1572
 * Gets a course setting from the current course_setting table. Try always using integer values.
1573
 * @param string    The name of the setting we want from the table
1574
 * @param string    Optional: course code
1575
 * @param string $setting_name
1576
 * @return mixed    The value of that setting in that table. Return -1 if not found.
1577
 */
1578
function api_get_course_setting($setting_name, $course_code = null)
1579
{
1580
    $course_info = api_get_course_info($course_code);
1581
    $table = Database::get_course_table(TABLE_COURSE_SETTING);
1582
    $setting_name = Database::escape_string($setting_name);
1583
    if (!empty($course_info['real_id']) && !empty($setting_name)) {
1584
        $sql = "SELECT value FROM $table
1585
                WHERE c_id = {$course_info['real_id']} AND variable = '$setting_name'";
1586
        $res = Database::query($sql);
1587
        if (Database::num_rows($res) > 0) {
1588
            $row = Database::fetch_array($res);
1589
            return $row['value'];
1590
        }
1591
    }
1592
    return -1;
1593
}
1594
1595
/**
1596
 * Gets an anonymous user ID
1597
 *
1598
 * For some tools that need tracking, like the learnpath tool, it is necessary
1599
 * to have a usable user-id to enable some kind of tracking, even if not
1600
 * perfect. An anonymous ID is taken from the users table by looking for a
1601
 * status of "6" (anonymous).
1602
 * @return int  User ID of the anonymous user, or O if no anonymous user found
1603
 */
1604 View Code Duplication
function api_get_anonymous_id()
1605
{
1606
    $table = Database::get_main_table(TABLE_MAIN_USER);
1607
    $sql = "SELECT user_id FROM $table WHERE status = ".ANONYMOUS;
1608
    $res = Database::query($sql);
1609
    if (Database::num_rows($res) > 0) {
1610
        $row = Database::fetch_array($res);
1611
        return $row['user_id'];
1612
    }
1613
1614
    // No anonymous user was found.
1615
    return 0;
1616
}
1617
1618
/**
1619
 * @param string $courseCode
1620
 * @param int $sessionId
1621
 * @param int $groupId
1622
 * @return string
1623
 */
1624
function api_get_cidreq_params($courseCode, $sessionId = 0, $groupId = 0)
1625
{
1626
    $courseCode = !empty($courseCode) ? htmlspecialchars($courseCode) : '';
1627
    $sessionId = !empty($sessionId) ? (int) $sessionId : 0;
1628
    $groupId = !empty($groupId) ? (int) $groupId : 0;
1629
1630
    $url = 'cidReq='.$courseCode;
1631
    $url .= '&id_session='.$sessionId;
1632
    $url .= '&gidReq='.$groupId;
1633
1634
    return $url;
1635
}
1636
1637
/**
1638
 * Returns the current course url part including session, group, and gradebook params
1639
 *
1640
 * @param bool $addSessionId
1641
 * @param bool $addGroupId
1642
 * @param string $origin
1643
 *
1644
 * @return  string  Course & session references to add to a URL
1645
 *
1646
 */
1647
function api_get_cidreq($addSessionId = true, $addGroupId = true, $origin = '')
1648
{
1649
    $courseCode = api_get_course_id();
1650
    $url = empty($courseCode) ? '' : 'cidReq='.htmlspecialchars($courseCode);
1651
    $origin = empty($origin) ? api_get_origin() : Security::remove_XSS($origin);
1652
1653
    if ($addSessionId) {
1654
        if (!empty($url)) {
1655
            $url .= api_get_session_id() == 0 ? '&id_session=0' : '&id_session='.api_get_session_id();
1656
        }
1657
    }
1658
1659
    if ($addGroupId) {
1660
        if (!empty($url)) {
1661
            $url .= api_get_group_id() == 0 ? '&gidReq=0' : '&gidReq='.api_get_group_id();
1662
        }
1663
    }
1664
1665
    if (!empty($url)) {
1666
        $url .= '&gradebook='.intval(api_is_in_gradebook());
1667
        $url .= '&origin='.$origin;
1668
    }
1669
1670
    return $url;
1671
}
1672
1673
/**
1674
 * get gradebook in session
1675
 */
1676
function api_is_in_gradebook()
1677
{
1678
    return Session::read('in_gradebook', false);
1679
}
1680
1681
/**
1682
 * set gradebook session
1683
 */
1684
function api_set_in_gradebook()
1685
{
1686
    Session::write('in_gradebook', true);
1687
}
1688
1689
/**
1690
 * remove gradebook session
1691
 */
1692
function api_remove_in_gradebook()
1693
{
1694
    Session::erase('in_gradebook');
1695
}
1696
1697
/**
1698
 * Returns the current course info array see api_format_course_array()
1699
 * If the course_code is given, the returned array gives info about that
1700
 * particular course, if none given it gets the course info from the session.
1701
 *
1702
 * @param string $course_code
1703
 * @param bool $strict
1704
 *
1705
 * @return array
1706
 */
1707
function api_get_course_info($course_code = null, $strict = false)
1708
{
1709
    if (!empty($course_code)) {
1710
        $course_code = Database::escape_string($course_code);
1711
        $courseId = api_get_course_int_id($course_code);
1712
1713
        if (empty($courseId)) {
1714
            return array();
1715
        }
1716
1717
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1718
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1719
        $sql = "SELECT
1720
                    course.*,
1721
                    course_category.code faCode,
1722
                    course_category.name faName
1723
                FROM $course_table
1724
                LEFT JOIN $course_cat_table
1725
                ON course.category_code = course_category.code
1726
                WHERE course.id = $courseId";
1727
        $result = Database::query($sql);
1728
        $courseInfo = array();
1729
        if (Database::num_rows($result) > 0) {
1730
            $data = Database::fetch_array($result);
1731
            $courseInfo = api_format_course_array($data);
1732
        }
1733
1734
        return $courseInfo;
1735
    }
1736
1737
    $_course = Session::read('_course');
1738
    if ($_course == '-1') {
1739
        $_course = array();
1740
    }
1741
1742
    return $_course;
1743
}
1744
1745
/**
1746
 * Returns the current course info array.
1747
1748
 * Now if the course_code is given, the returned array gives info about that
1749
 * particular course, not specially the current one.
1750
 * @param int $id Numeric ID of the course
1751
 * @return array The course info as an array formatted by api_format_course_array, including category.name
1752
 */
1753
function api_get_course_info_by_id($id = null)
1754
{
1755
    if (!empty($id)) {
1756
        $id = intval($id);
1757
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1758
        $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
1759
        $sql = "SELECT
1760
                    course.*,
1761
                    course_category.code faCode,
1762
                    course_category.name faName
1763
                FROM $course_table
1764
                LEFT JOIN $course_cat_table
1765
                ON course.category_code =  course_category.code
1766
                WHERE course.id = $id";
1767
        $result = Database::query($sql);
1768
        $_course = array();
1769
        if (Database::num_rows($result) > 0) {
1770
            $course_data = Database::fetch_array($result);
1771
            $_course = api_format_course_array($course_data);
1772
        }
1773
        return $_course;
1774
    }
1775
1776
    global $_course;
1777
    if ($_course == '-1') $_course = array();
1778
    return $_course;
1779
}
1780
1781
/**
1782
 * Reformat the course array (output by api_get_course_info()) in order, mostly,
1783
 * to switch from 'code' to 'id' in the array. This is a legacy feature and is
1784
 * now possibly causing massive confusion as a new "id" field has been added to
1785
 * the course table in 1.9.0.
1786
 * @param $course_data
1787
 * @return array
1788
 * @todo eradicate the false "id"=code field of the $_course array and use the int id
1789
 */
1790
function api_format_course_array($course_data)
1791
{
1792
    if (empty($course_data)) {
1793
        return array();
1794
    }
1795
1796
    $_course = array();
1797
    $_course['id'] = $course_data['code'];
1798
    $_course['real_id'] = $course_data['id'];
1799
1800
    // Added
1801
    $_course['code'] = $course_data['code'];
1802
    $_course['name'] = $course_data['title'];
1803
    $_course['title'] = $course_data['title'];
1804
    $_course['official_code'] = $course_data['visual_code'];
1805
    $_course['visual_code'] = $course_data['visual_code'];
1806
    $_course['sysCode'] = $course_data['code'];
1807
    $_course['path'] = $course_data['directory']; // Use as key in path.
1808
    $_course['directory'] = $course_data['directory'];
1809
    $_course['creation_date'] = $course_data['creation_date'];
1810
    $_course['titular'] = $course_data['tutor_name'];
1811
    $_course['language'] = $course_data['course_language'];
1812
    $_course['extLink']['url'] = $course_data['department_url'];
1813
    $_course['extLink']['name'] = $course_data['department_name'];
1814
    $_course['categoryCode'] = $course_data['faCode'];
1815
    $_course['categoryName'] = $course_data['faName'];
1816
    $_course['visibility'] = $course_data['visibility'];
1817
    $_course['subscribe_allowed'] = $course_data['subscribe'];
1818
    $_course['subscribe'] = $course_data['subscribe'];
1819
    $_course['unsubscribe'] = $course_data['unsubscribe'];
1820
    $_course['course_language'] = $course_data['course_language'];
1821
    $_course['activate_legal'] = isset($course_data['activate_legal']) ? $course_data['activate_legal'] : false;
1822
    $_course['legal'] = $course_data['legal'];
1823
    $_course['show_score'] = $course_data['show_score']; //used in the work tool
1824
    $_course['department_name'] = $course_data['department_name'];
1825
    $_course['department_url'] = $course_data['department_url'];
1826
1827
    // Course password
1828
    $_course['registration_code'] = !empty($course_data['registration_code']) ? sha1($course_data['registration_code']) : null;
1829
    $_course['disk_quota'] = $course_data['disk_quota'];
1830
    $_course['course_public_url'] = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/index.php';
1831
1832
    if (array_key_exists('add_teachers_to_sessions_courses', $course_data)) {
1833
        $_course['add_teachers_to_sessions_courses'] = $course_data['add_teachers_to_sessions_courses'];
1834
    }
1835
1836
    if (file_exists(api_get_path(SYS_COURSE_PATH).$course_data['directory'].'/course-pic85x85.png')) {
1837
        $url_image = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/course-pic85x85.png';
1838
    } else {
1839
        $url_image = Display::return_icon('course.png', null, null, ICON_SIZE_BIG, null, true, false);
1840
    }
1841
    $_course['course_image'] = $url_image;
1842
1843
    if (file_exists(api_get_path(SYS_COURSE_PATH).$course_data['directory'].'/course-pic.png')) {
1844
        $url_image = api_get_path(WEB_COURSE_PATH).$course_data['directory'].'/course-pic.png';
1845
    } else {
1846
        $url_image = Display::returnIconPath('session_default.png');
1847
    }
1848
    $_course['course_image_large'] = $url_image;
1849
1850
    $_course['extra_fields'] = isset($course_data['extra_fields']) ? $course_data['extra_fields'] : array();
1851
    $_course['settings'] = isset($course_data['settings']) ? $course_data['settings'] : array();
1852
    $_course['teacher_list'] = isset($course_data['teacher_list']) ? $course_data['teacher_list'] : array();
1853
    $_course['teacher_list_formatted'] = isset($course_data['teacher_list_formatted']) ? $course_data['teacher_list_formatted'] : array();
1854
1855
    return $_course;
1856
}
1857
1858
/**
1859
 * Add a parameter to the existing URL. If this parameter already exists,
1860
 * just replace it with the new value
1861
 * @param   string  The URL
1862
 * @param   string  param=value string
1863
 * @param   boolean Whether to filter XSS or not
1864
 * @return  string  The URL with the added parameter
1865
 */
1866
function api_add_url_param($url, $param, $filter_xss = true) {
1867
    if (empty($param)) {
1868
        return $url;
1869
    }
1870
    if (strpos($url, '?') !== false) {
1871
        if ($param[0] != '&') {
1872
            $param = '&'.$param;
1873
        }
1874
        list (, $query_string) = explode('?', $url);
1875
        $param_list1 = explode('&', $param);
1876
        $param_list2 = explode('&', $query_string);
1877
        $param_list1_keys = $param_list1_vals = array();
1878
        foreach ($param_list1 as $key => $enreg) {
1879
            list ($param_list1_keys[$key], $param_list1_vals[$key]) = explode('=', $enreg);
1880
        }
1881
        $param_list1 = array ('keys' => $param_list1_keys, 'vals' => $param_list1_vals);
1882
        foreach ($param_list2 as $enreg) {
1883
            $enreg = explode('=', $enreg);
1884
            $key = array_search($enreg[0], $param_list1['keys']);
1885
            if (!is_null($key) && !is_bool($key)) {
1886
                $url = str_replace($enreg[0].'='.$enreg[1], $enreg[0].'='.$param_list1['vals'][$key], $url);
1887
                $param = str_replace('&'.$enreg[0].'='.$param_list1['vals'][$key], '', $param);
1888
            }
1889
        }
1890
        $url .= $param;
1891
    } else {
1892
        $url = $url.'?'.$param;
1893
    }
1894
    if ($filter_xss === true) {
1895
        $url = Security::remove_XSS(urldecode($url));
1896
    }
1897
    return $url;
1898
}
1899
1900
/**
1901
 * Returns a difficult to guess password.
1902
 * @param int $length the length of the password
1903
 * @return string the generated password
1904
 */
1905
function api_generate_password($length = 8)
1906
{
1907
    $characters = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
1908
    $numbers = '23456789';
1909
1910
    if ($length < 2) {
1911
        $length = 2;
1912
    }
1913
    $password = '';
1914
    for ($i = 0; $i < $length; $i ++) {
1915
        $password .= $characters[rand() % strlen($characters)];
1916
    }
1917
1918
    // At least 2 digits
1919
    for ($i = 0; $i < 2; $i ++) {
1920
        $password .= $numbers[rand() % strlen($numbers)];
1921
    }
1922
1923
    return $password;
1924
}
1925
1926
/**
1927
 * Checks a password to see wether it is OK to use.
1928
 * @param string $password
1929
 * @return boolean if the password is acceptable, false otherwise
1930
 * Notes about what a password "OK to use" is:
1931
 * 1. The password should be at least 5 characters long.
1932
 * 2. Only English letters (uppercase or lowercase, it doesn't matter) and digits are allowed.
1933
 * 3. The password should contain at least 3 letters.
1934
 * 4. It should contain at least 2 digits.
1935
 * 5. It should not contain 3 or more consequent (according to ASCII table) characters.
1936
 */
1937
function api_check_password($password) {
1938
    $password_length = api_strlen($password);
1939
    if ($password_length < 5) {
1940
        return false;
1941
    }
1942
    $password = api_strtolower($password);
1943
    $letters = 0;
1944
    $digits = 0;
1945
    $consequent_characters = 0;
1946
    $previous_character_code = 0;
1947
    for ($i = 0; $i < $password_length; $i ++) {
1948
        $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...
1949
        if ($i && abs($current_character_code - $previous_character_code) <= 1) {
1950
            $consequent_characters ++;
1951
            if ($consequent_characters == 3) {
1952
                return false;
1953
            }
1954
        } else {
1955
            $consequent_characters = 1;
1956
        }
1957
        if ($current_character_code >= 97 && $current_character_code <= 122) {
1958
            $letters ++;
1959
        } elseif ($current_character_code >= 48 && $current_character_code <= 57) {
1960
            $digits ++;
1961
        } else {
1962
            return false;
1963
        }
1964
        $previous_character_code = $current_character_code;
1965
    }
1966
    return ($letters >= 3 && $digits >= 2);
1967
}
1968
1969
/**
1970
 * Clears the user ID from the session if it was the anonymous user. Generally
1971
 * used on out-of-tools pages to remove a user ID that could otherwise be used
1972
 * in the wrong context.
1973
 * This function is to be used in conjunction with the api_set_anonymous()
1974
 * function to simulate the user existence in case of an anonymous visit.
1975
 * @param bool      database check switch - passed to api_is_anonymous()
1976
 * @return bool     true if succesfully unregistered, false if not anonymous.
1977
 */
1978
function api_clear_anonymous($db_check = false)
1979
{
1980
    global $_user;
1981
    if (api_is_anonymous($_user['user_id'], $db_check)) {
1982
        unset($_user['user_id']);
1983
        Session::erase('_uid');
1984
        return true;
1985
    }
1986
    return false;
1987
}
1988
1989
/**
1990
 * Returns the status string corresponding to the status code
1991
 * @author Noel Dieschburg
1992
 * @param the int status code
1993
 */
1994
function get_status_from_code($status_code)
1995
{
1996
    switch ($status_code) {
1997
        case STUDENT:
1998
            return get_lang('Student', '');
1999
        case TEACHER:
2000
            return get_lang('Teacher', '');
2001
        case COURSEMANAGER:
2002
            return get_lang('Manager', '');
2003
        case SESSIONADMIN:
2004
            return get_lang('SessionsAdmin', '');
2005
        case DRH:
2006
            return get_lang('Drh', '');
2007
    }
2008
}
2009
2010
/**
2011
 * Sets the current user as anonymous if it hasn't been identified yet. This
2012
 * function should be used inside a tool only. The function api_clear_anonymous()
2013
 * acts in the opposite direction by clearing the anonymous user's data every
2014
 * time we get on a course homepage or on a neutral page (index, admin, my space)
2015
 * @return bool     true if set user as anonymous, false if user was already logged in or anonymous id could not be found
2016
 */
2017
function api_set_anonymous() {
2018
    global $_user;
2019
2020
    if (!empty($_user['user_id'])) {
2021
        return false;
2022
    }
2023
    $user_id = api_get_anonymous_id();
2024
    if ($user_id == 0) {
2025
        return false;
2026
    }
2027
    Session::erase('_user');
2028
    $_user['user_id'] = $user_id;
2029
    $_user['is_anonymous'] = true;
2030
    $GLOBALS['_user'] = $_user;
2031
    Session::write('_user', $_user);
2032
    return true;
2033
}
2034
2035
/**
2036
 * Gets the current Chamilo (not PHP/cookie) session ID
2037
 * @return  int     O if no active session, the session ID otherwise
2038
 */
2039
function api_get_session_id()
2040
{
2041
    return Session::read('id_session', 0);
2042
}
2043
2044
/**
2045
 * Gets the current Chamilo (not social network) group ID
2046
 * @return  int     O if no active session, the session ID otherwise
2047
 */
2048
function api_get_group_id()
2049
{
2050
    return Session::read('_gid', 0);
2051
}
2052
2053
/**
2054
 * Gets the current or given session name
2055
 * @param   int     Session ID (optional)
2056
 * @return  string  The session name, or null if unfound
2057
 */
2058
function api_get_session_name($session_id = 0)
2059
{
2060
    if (empty($session_id)) {
2061
        $session_id = api_get_session_id();
2062
        if (empty($session_id)) {
2063
            return null;
2064
        }
2065
    }
2066
    $t = Database::get_main_table(TABLE_MAIN_SESSION);
2067
    $s = "SELECT name FROM $t WHERE id = ".(int)$session_id;
2068
    $r = Database::query($s);
2069
    $c = Database::num_rows($r);
2070
    if ($c > 0) {
2071
        //technically, there can be only one, but anyway we take the first
2072
        $rec = Database::fetch_array($r);
2073
        return $rec['name'];
2074
    }
2075
    return null;
2076
}
2077
2078
/**
2079
 * Gets the session info by id
2080
 * @param int       Session ID
2081
 * @return array    information of the session
2082
 */
2083
function api_get_session_info($session_id)
2084
{
2085
    return SessionManager::fetch($session_id);
2086
}
2087
2088
/**
2089
 * Gets the session visibility by session id
2090
 * @param int $session_id
2091
 * @param int $courseId
2092
 * @param bool $ignore_visibility_for_admins
2093
 * @return int
2094
 *  0 = session still available,
2095
 *  SESSION_VISIBLE_READ_ONLY = 1,
2096
 *  SESSION_VISIBLE = 2,
2097
 *  SESSION_INVISIBLE = 3
2098
 */
2099
function api_get_session_visibility(
2100
    $session_id,
2101
    $courseId = null,
2102
    $ignore_visibility_for_admins = true
2103
) {
2104
    // Means that the session is still available.
2105
    $visibility = 0;
2106
2107
    if (api_is_platform_admin()) {
2108
        if ($ignore_visibility_for_admins) {
2109
            return SESSION_AVAILABLE;
2110
        }
2111
    }
2112
2113
    $now = time();
2114
    if (!empty($session_id)) {
2115
        $session_id = intval($session_id);
2116
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2117
2118
        $sql = "SELECT * FROM $tbl_session
2119
                WHERE id = $session_id ";
2120
2121
        $result = Database::query($sql);
2122
2123
        if (Database::num_rows($result) > 0) {
2124
            $row = Database::fetch_array($result, 'ASSOC');
2125
            $visibility = $original_visibility = $row['visibility'];
2126
2127
            // I don't care the session visibility.
2128
            if (empty($row['access_start_date']) && empty($row['access_end_date'])) {
2129
                // Session duration per student.
2130
                if (isset($row['duration']) && !empty($row['duration'])) {
2131
                    $duration = $row['duration'] * 24 * 60 * 60;
2132
2133
                    $courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser(
2134
                        $session_id,
2135
                        api_get_user_id()
2136
                    );
2137
2138
                    // If there is a session duration but there is no previous
2139
                    // access by the user, then the session is still available
2140
                    if (count($courseAccess) == 0) {
2141
                        return SESSION_AVAILABLE;
2142
                    }
2143
2144
                    $currentTime = time();
2145
                    $firstAccess = 0;
2146
                    if (isset($courseAccess['login_course_date'])) {
2147
                        $firstAccess = api_strtotime(
2148
                            $courseAccess['login_course_date'],
2149
                            'UTC'
2150
                        );
2151
                    }
2152
                    $userDurationData = SessionManager::getUserSession(
2153
                        api_get_user_id(),
2154
                        $session_id
2155
                    );
2156
                    $userDuration = 0;
2157
                    if (isset($userDurationData['duration'])) {
2158
                        $userDuration = intval($userDurationData['duration']) * 24 * 60 * 60;
2159
                    }
2160
2161
                    $totalDuration = $firstAccess + $duration + $userDuration;
2162
                    if ($totalDuration > $currentTime) {
2163
                        return SESSION_AVAILABLE;
2164
                    } else {
2165
                        return SESSION_INVISIBLE;
2166
                    }
2167
                }
2168
2169
                return SESSION_AVAILABLE;
2170
            } else {
2171
                // If start date was set.
2172
                if (!empty($row['access_start_date'])) {
2173
                    if ($now > api_strtotime($row['access_start_date'], 'UTC')) {
2174
                        $visibility = SESSION_AVAILABLE;
2175
                    } else {
2176
                        $visibility = SESSION_INVISIBLE;
2177
                    }
2178
                }
2179
2180
                // If the end date was set.
2181
                if (!empty($row['access_end_date'])) {
2182
                    // Only if date_start said that it was ok
2183
                    if ($visibility === SESSION_AVAILABLE) {
2184
                        if ($now < api_strtotime($row['access_end_date'], 'UTC')) {
2185
                            // Date still available
2186
                            $visibility = SESSION_AVAILABLE;
2187
                        } else {
2188
                            // Session ends
2189
                            $visibility = $row['visibility'];
2190
                        }
2191
                    }
2192
                }
2193
            }
2194
2195
            /* If I'm a coach the visibility can change in my favor depending in
2196
             the coach dates */
2197
            $isCoach = api_is_coach($session_id, $courseId);
2198
2199
            if ($isCoach) {
2200
                // Test end date.
2201
                if (!empty($row['coach_access_end_date'])) {
2202
                    $endDateCoach = api_strtotime($row['coach_access_end_date'], 'UTC');
2203
2204
                    if ($endDateCoach >= $now) {
2205
                        $visibility = SESSION_AVAILABLE;
2206
                    } else {
2207
                        $visibility = SESSION_INVISIBLE;
2208
                    }
2209
                }
2210
2211
                // Test start date.
2212
                if (!empty($row['coach_access_start_date'])) {
2213
                    $start = api_strtotime($row['coach_access_start_date'], 'UTC');
2214
                    if ($start < $now) {
2215
                        $visibility = SESSION_AVAILABLE;
2216
                    } else {
2217
                        $visibility = SESSION_INVISIBLE;
2218
                    }
2219
                }
2220
            }
2221
        } else {
2222
            $visibility = SESSION_INVISIBLE;
2223
        }
2224
    }
2225
    return $visibility;
2226
}
2227
2228
/**
2229
 * This function returns a (star) session icon if the session is not null and
2230
 * the user is not a student
2231
 * @param int   $session_id
2232
 * @param int   $status_id User status id - if 5 (student), will return empty
2233
 * @return string   Session icon
2234
 */
2235
function api_get_session_image($session_id, $status_id)
2236
{
2237
    $session_id = (int)$session_id;
2238
    $session_img = '';
2239
    if ((int)$status_id != 5) { //check whether is not a student
2240
        if ($session_id > 0) {
2241
            $session_img = "&nbsp;&nbsp;".Display::return_icon(
2242
                'star.png',
2243
                get_lang('SessionSpecificResource'),
2244
                array('align' => 'absmiddle'),
2245
                ICON_SIZE_SMALL
2246
            );
2247
        }
2248
    }
2249
    return $session_img;
2250
}
2251
2252
/**
2253
 * This function add an additional condition according to the session of the course
2254
 * @param int       $session_id session id
2255
 * @param bool      $and optional, true if more than one condition false if the only condition in the query
2256
 * @param bool      $with_base_content optional, true to accept content with session=0 as well, false for strict session condition
2257
 * @return string   condition of the session
2258
 */
2259
function api_get_session_condition(
2260
    $session_id,
2261
    $and = true,
2262
    $with_base_content = false,
2263
    $session_field = "session_id"
2264
) {
2265
    $session_id = intval($session_id);
2266
2267
    if (empty($session_field)) {
2268
        $session_field = "session_id";
2269
    }
2270
    // Condition to show resources by session
2271
    $condition_add = $and ? " AND " : " WHERE ";
2272
2273
    if ($with_base_content) {
2274
        $condition_session = $condition_add." ( $session_field = $session_id OR $session_field = 0 OR $session_field IS NULL) ";
2275
    } else {
2276
        if (empty($session_id)) {
2277
            $condition_session = $condition_add." ($session_field = $session_id OR $session_field IS NULL)";
2278
        } else {
2279
            $condition_session = $condition_add." $session_field = $session_id ";
2280
        }
2281
    }
2282
    return $condition_session;
2283
}
2284
2285
/**
2286
 * @param string $variable
2287
 * @param string $option
2288
 * @return bool
2289
 */
2290
function api_get_setting_in_list($variable, $option)
2291
{
2292
    $value = api_get_setting($variable);
2293
2294
    return in_array($option, $value);
2295
}
2296
2297
2298
/**
2299
 * Returns the value of a setting from the web-adjustable admin config settings.
2300
 *
2301
 * WARNING true/false are stored as string, so when comparing you need to check e.g.
2302
 * if (api_get_setting('course.show_navigation_menu') == 'true') //CORRECT
2303
 * instead of
2304
 * if (api_get_setting('course.show_navigation_menu') == true) //INCORRECT
2305
 * @param string    $variable The variable name
2306
 * @return string
2307
 *
2308
 * @author Julio Montoya
2309
 */
2310
function api_get_setting($variable)
2311
{
2312
    $variable = trim($variable);
2313
2314
    switch ($variable) {
2315 View Code Duplication
        case 'header_extra_content':
2316
            $filename = api_get_path(SYS_PATH).api_get_home_path().'header_extra_content.txt';
2317
            if (file_exists($filename)) {
2318
                $value = file_get_contents($filename);
2319
                    return $value ;
2320
            } else {
2321
                return '';
2322
            }
2323
            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...
2324 View Code Duplication
        case 'footer_extra_content':
2325
            $filename = api_get_path(SYS_PATH).api_get_home_path().'footer_extra_content.txt';
2326
            if (file_exists($filename)) {
2327
                $value = file_get_contents($filename);
2328
                return $value ;
2329
            } else {
2330
                return '';
2331
            }
2332
            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...
2333
        case 'server_type':
2334
            $test = ['dev', 'test'];
2335
            $environment = Container::getEnvironment();
2336
            if (in_array($environment, $test)) {
2337
                return 'test';
2338
            }
2339
            return 'prod';
2340
        case 'stylesheets':
2341
            $variable = 'platform.theme';
2342
            break;
2343
        // deprecated settings
2344
        case 'openid_authentication':
2345
        case 'sso_authentication':
2346
        case 'service_ppt2lp':
2347
            break;
2348
        default:
2349
            return Container::getSettingsManager()->getSetting($variable);
2350
    }
2351
}
2352
2353
/**
2354
 * @param string $plugin
2355
 * @param string $variable
2356
 * @return string
2357
 */
2358
function api_get_plugin_setting($plugin, $variable)
2359
{
2360
    $variableName = $plugin.'_'.$variable;
2361
    $result = api_get_setting($variableName);
2362
    if (isset($result[$plugin])) {
2363
        return $result[$plugin];
2364
    }
2365
2366
    return null;
2367
}
2368
2369
/**
2370
 * Returns the value of a setting from the web-adjustable admin config settings.
2371
 **/
2372
function api_get_settings_params($params) {
2373
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2374
    $result = Database::select('*', $table, array('where' => $params));
2375
    return $result;
2376
}
2377
2378
function api_get_settings_params_simple($params) {
2379
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2380
    $result = Database::select('*', $table, array('where' => $params), 'one');
2381
    return $result;
2382
}
2383
2384
/**
2385
 * Returns the value of a setting from the web-adjustable admin config settings.
2386
 **/
2387
function api_delete_settings_params($params) {
2388
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2389
    $result = Database::delete($table, $params);
2390
    return $result;
2391
}
2392
2393
/**
2394
 * Returns an escaped version of $_SERVER['PHP_SELF'] to avoid XSS injection
2395
 * @return string   Escaped version of $_SERVER['PHP_SELF']
2396
 */
2397
function api_get_self() {
2398
    return htmlentities($_SERVER['PHP_SELF']);
2399
}
2400
2401
/**
2402
 * Checks whether current user is a platform administrator
2403
 * @param boolean $allowSessionAdmins Whether session admins should be considered admins or not
2404
 * @param boolean $allowDrh Whether HR directors should be considered admins or not
2405
 * @return boolean True if the user has platform admin rights,
2406
 * false otherwise.
2407
 * @see usermanager::is_admin(user_id) for a user-id specific function
2408
 */
2409
function api_is_platform_admin($allowSessionAdmins = false, $allowDrh = false)
2410
{
2411
    $checker = Container::getAuthorizationChecker();
2412
    if ($checker) {
2413
        if ($checker->isGranted('ROLE_ADMIN')) {
2414
        return true;
2415
    }
2416
        if ($allowSessionAdmins) {
2417
            if ($checker->isGranted('ROLE_SESSION_MANAGER')) {
2418
                return true;
2419
            }
2420
        }
2421
    }
2422
2423
    return false;
2424
2425
    $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...
2426
    if ($isPlatformAdmin) {
2427
        return true;
2428
    }
2429
    $_user = api_get_user_info();
2430
2431
    return
2432
        isset($_user['status']) &&
2433
        (
2434
            ($allowSessionAdmins && $_user['status'] == SESSIONADMIN) ||
2435
            ($allowDrh && $_user['status'] == DRH)
2436
        );
2437
}
2438
2439
/**
2440
 * Checks whether the user given as user id is in the admin table.
2441
 * @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...
2442
 * @param int $url URL ID. If provided, also check if the user is active on given URL
2443
 * @result bool True if the user is admin, false otherwise
2444
 */
2445
function api_is_platform_admin_by_id($user_id = null, $url = null)
2446
{
2447
    $user_id = intval($user_id);
2448
    if (empty($user_id)) {
2449
        $user_id = api_get_user_id();
2450
    }
2451
2452
    $em = Container::getEntityManager();
2453
    $user = $em->getRepository('ChamiloUserBundle:User')->find($user_id);
2454
    $is_admin = $user->hasRole('ROLE_ADMIN');
2455
2456
    if (!$is_admin or !isset($url)) {
2457
        return $is_admin;
2458
    }
2459
2460
    // We get here only if $url is set
2461
    $url = intval($url);
2462
    $url_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
2463
    $sql = "SELECT * FROM $url_user_table
2464
            WHERE access_url_id = $url AND user_id = $user_id";
2465
    $res = Database::query($sql);
2466
    $is_on_url = Database::num_rows($res) === 1;
2467
2468
    return $is_on_url;
2469
}
2470
2471
/**
2472
 * Returns the user's numeric status ID from the users table
2473
 * @param int $user_id If none provided, will use current user
2474
 * @return int User's status (1 for teacher, 5 for student, etc)
2475
 */
2476 View Code Duplication
function api_get_user_status($user_id = null)
2477
{
2478
    $user_id = intval($user_id);
2479
    if (empty($user_id)) {
2480
        $user_id = api_get_user_id();
2481
    }
2482
    $table = Database::get_main_table(TABLE_MAIN_USER);
2483
    $sql = "SELECT status FROM $table WHERE user_id = $user_id ";
2484
    $result = Database::query($sql);
2485
    $status = null;
2486
    if (Database::num_rows($result)) {
2487
        $row = Database::fetch_array($result);
2488
        $status = $row['status'];
2489
    }
2490
    return $status;
2491
}
2492
2493
/**
2494
 * Checks whether current user is allowed to create courses
2495
 * @return boolean True if the user has course creation rights,
2496
 * false otherwise.
2497
 */
2498
function api_is_allowed_to_create_course()
2499
{
2500
    if (api_is_platform_admin()) {
2501
        return true;
2502
    }
2503
2504
    // Teachers can only create courses
2505
    if (api_is_teacher()) {
2506
        if (api_get_setting('allow_users_to_create_courses') === 'true') {
2507
            return true;
2508
        } else {
2509
            return false;
2510
        }
2511
    }
2512
2513
    return Session::read('is_allowedCreateCourse');
2514
}
2515
2516
/**
2517
 * Checks whether the current user is a course administrator
2518
 * @return boolean True if current user is a course administrator
2519
 */
2520
function api_is_course_admin() {
2521
    if (api_is_platform_admin()) {
2522
        return true;
2523
    }
2524
    return Session::read('is_courseAdmin');
2525
}
2526
2527
/**
2528
 * Checks whether the current user is a course coach
2529
 * @return bool     True if current user is a course coach
2530
 */
2531
function api_is_course_coach() {
2532
    return Session::read('is_courseCoach');
2533
}
2534
2535
/**
2536
 * Checks whether the current user is a course tutor
2537
 * @return bool     True if current user is a course tutor
2538
 */
2539
function api_is_course_tutor() {
2540
    return Session::read('is_courseTutor');
2541
}
2542
2543
/**
2544
 * @param int $user_id
2545
 * @param int $courseId
2546
 * @param int $session_id
2547
 * @return bool
2548
 */
2549
function api_is_course_session_coach($user_id, $courseId, $session_id)
2550
{
2551
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2552
    $session_rel_course_rel_user_table  = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2553
2554
    $user_id = intval($user_id);
2555
    $session_id = intval($session_id);
2556
    $courseId = intval($courseId);
2557
2558
    $sql = "SELECT DISTINCT session.id
2559
            FROM $session_table
2560
            INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2561
            ON session.id = session_rc_ru.session_id
2562
            WHERE
2563
                session_rc_ru.user_id = '".$user_id."'  AND
2564
                session_rc_ru.c_id = '$courseId' AND
2565
                session_rc_ru.status = 2 AND
2566
                session_rc_ru.session_id = '$session_id'";
2567
    $result = Database::query($sql);
2568
2569
    return Database::num_rows($result) > 0;
2570
}
2571
2572
/**
2573
 * Checks whether the current user is a course or session coach
2574
 * @param int $session_id
2575
 * @param int $courseId
2576
 * @param bool  Check whether we are in student view and, if we are, return false
2577
 * @return boolean True if current user is a course or session coach
2578
 */
2579
function api_is_coach($session_id = 0, $courseId = null, $check_student_view = true)
2580
{
2581
    $userId = api_get_user_id();
2582
2583
    if (!empty($session_id)) {
2584
        $session_id = intval($session_id);
2585
    } else {
2586
        $session_id = api_get_session_id();
2587
    }
2588
2589
    // The student preview was on
2590
    if ($check_student_view &&
2591
        isset($_SESSION['studentview']) && $_SESSION['studentview'] == "studentview"
2592
    ) {
2593
        return false;
2594
    }
2595
2596
    if (!empty($courseId)) {
2597
        $courseId = intval($courseId);
2598
    } else {
2599
        $courseId = api_get_course_int_id();
2600
    }
2601
2602
    $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
2603
    $session_rel_course_rel_user_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2604
    $sessionIsCoach = null;
2605
2606
    if (!empty($courseId)) {
2607
        $sql = "SELECT DISTINCT s.id, name, access_start_date, access_end_date
2608
                FROM $session_table s
2609
                INNER JOIN $session_rel_course_rel_user_table session_rc_ru
2610
                ON session_rc_ru.session_id = s.id AND session_rc_ru.user_id = '".$userId."'
2611
                WHERE
2612
                    session_rc_ru.c_id = '$courseId' AND
2613
                    session_rc_ru.status = 2 AND
2614
                    session_rc_ru.session_id = '$session_id'";
2615
        $result = Database::query($sql);
2616
        $sessionIsCoach = Database::store_result($result);
2617
    }
2618
2619
    if (!empty($session_id)) {
2620
        $sql = "SELECT DISTINCT id, name, access_start_date, access_end_date
2621
                FROM $session_table
2622
                WHERE session.id_coach = $userId AND id = $session_id
2623
                ORDER BY access_start_date, access_end_date, name";
2624
        $result = Database::query($sql);
2625
        if (!empty($sessionIsCoach)) {
2626
            $sessionIsCoach = array_merge($sessionIsCoach , Database::store_result($result));
2627
        } else {
2628
            $sessionIsCoach = Database::store_result($result);
2629
        }
2630
    }
2631
2632
    return (count($sessionIsCoach) > 0);
2633
}
2634
2635
/**
2636
 * Checks whether the current user is a session administrator
2637
 * @return boolean True if current user is a course administrator
2638
 */
2639
function api_is_session_admin()
2640
{
2641
    $user = api_get_user_info();
2642
    return isset($user['status']) && $user['status'] == SESSIONADMIN;
2643
}
2644
2645
/**
2646
 * Checks whether the current user is a human resources manager
2647
 * @return boolean True if current user is a human resources manager
2648
 */
2649
function api_is_drh()
2650
{
2651
    $user = api_get_user_info();
2652
    return isset($user['status']) && $user['status'] == DRH;
2653
}
2654
2655
/**
2656
 * Checks whether the current user is a student
2657
 * @return boolean True if current user is a human resources manager
2658
 */
2659
function api_is_student()
2660
{
2661
    $user = api_get_user_info();
2662
    return isset($user['status']) && $user['status'] == STUDENT;
2663
}
2664
2665
/**
2666
 * Checks whether the current user has the status 'teacher'
2667
 * @return boolean True if current user is a human resources manager
2668
 */
2669
function api_is_teacher()
2670
{
2671
    $user = api_get_user_info();
2672
    return isset($user['status']) && $user['status'] == COURSEMANAGER;
2673
}
2674
2675
/**
2676
 * Checks whether the current user is a invited user
2677
 * @return boolean
2678
 */
2679
function api_is_invitee()
2680
{
2681
    $user = api_get_user_info();
2682
2683
    return isset($user['status']) && $user['status'] == INVITEE;
2684
}
2685
2686
/**
2687
 * This function checks whether a session is assigned into a category
2688
 * @param int       - session id
2689
 * @param string    - category name
2690
 * @return bool     - true if is found, otherwise false
2691
 */
2692
function api_is_session_in_category($session_id, $category_name)
2693
{
2694
    $session_id = intval($session_id);
2695
    $category_name = Database::escape_string($category_name);
2696
2697
    $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2698
    $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
2699
2700
    $sql = "SELECT 1
2701
            FROM $tbl_session
2702
            WHERE $session_id IN (
2703
                SELECT s.id FROM $tbl_session s, $tbl_session_category sc
2704
                WHERE
2705
                  s.session_category_id = sc.id AND
2706
                  sc.name LIKE '%$category_name'
2707
            )";
2708
    $rs = Database::query($sql);
2709
2710
    if (Database::num_rows($rs) > 0) {
2711
        return true;
2712
    } else {
2713
        return false;
2714
    }
2715
}
2716
2717
/**
2718
 * Displays the title of a tool.
2719
 * Normal use: parameter is a string:
2720
 * api_display_tool_title("My Tool")
2721
 *
2722
 * Optionally, there can be a subtitle below
2723
 * the normal title, and / or a supra title above the normal title.
2724
 *
2725
 * e.g. supra title:
2726
 * group
2727
 * GROUP PROPERTIES
2728
 *
2729
 * e.g. subtitle:
2730
 * AGENDA
2731
 * calender & events tool
2732
 *
2733
 * @author Hugues Peeters <[email protected]>
2734
 * @param  mixed $title_element - it could either be a string or an array
2735
 *                               containing 'supraTitle', 'mainTitle',
2736
 *                               'subTitle'
2737
 * @return void
2738
 */
2739
function api_display_tool_title($title_element) {
2740
    if (is_string($title_element)) {
2741
        $tit = $title_element;
2742
        unset ($title_element);
2743
        $title_element['mainTitle'] = $tit;
2744
    }
2745
    echo '<h3>';
2746
    if (!empty($title_element['supraTitle'])) {
2747
        echo '<small>'.$title_element['supraTitle'].'</small><br />';
2748
    }
2749
    if (!empty($title_element['mainTitle'])) {
2750
        echo $title_element['mainTitle'];
2751
    }
2752
    if (!empty($title_element['subTitle'])) {
2753
        echo '<br /><small>'.$title_element['subTitle'].'</small>';
2754
    }
2755
    echo '</h3>';
2756
}
2757
2758
/**
2759
 * Displays options for switching between student view and course manager view
2760
 *
2761
 * Changes in version 1.2 (Patrick Cool)
2762
 * Student view switch now behaves as a real switch. It maintains its current state until the state
2763
 * is changed explicitly
2764
 *
2765
 * Changes in version 1.1 (Patrick Cool)
2766
 * student view now works correctly in subfolders of the document tool
2767
 * student view works correctly in the new links tool
2768
 *
2769
 * Example code for using this in your tools:
2770
 * //if ($is_courseAdmin && api_get_setting('student_view_enabled') == 'true') {
2771
 * //   display_tool_view_option($isStudentView);
2772
 * //}
2773
 * //and in later sections, use api_is_allowed_to_edit()
2774
 *
2775
 * @author Roan Embrechts
2776
 * @author Patrick Cool
2777
 * @author Julio Montoya, changes added in Chamilo
2778
 * @version 1.2
2779
 * @todo rewrite code so it is easier to understand
2780
 */
2781
function api_display_tool_view_option() {
2782
    if (api_get_setting('student_view_enabled') != 'true') {
2783
        return '';
2784
    }
2785
2786
    $sourceurl = '';
2787
    $is_framed = false;
2788
    // Exceptions apply for all multi-frames pages
2789
    if (strpos($_SERVER['REQUEST_URI'], 'chat/chat_banner.php') !== false) {
2790
        // The chat is a multiframe bit that doesn't work too well with the student_view, so do not show the link
2791
        return '';
2792
    }
2793
2794
    // Uncomment to remove student view link from document view page
2795
    if (strpos($_SERVER['REQUEST_URI'], 'lp/lp_header.php') !== false) {
2796
        if (empty($_GET['lp_id'])) {
2797
            return '';
2798
        }
2799
        $sourceurl = substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], '?'));
2800
        $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);
2801
        //showinframes doesn't handle student view anyway...
2802
        //return '';
2803
        $is_framed = true;
2804
    }
2805
2806
    // Check whether the $_SERVER['REQUEST_URI'] contains already url parameters (thus a questionmark)
2807
    if (!$is_framed) {
2808
        if (strpos($_SERVER['REQUEST_URI'], '?') === false) {
2809
            $sourceurl = api_get_self().'?'.api_get_cidreq();
2810
        } else {
2811
            $sourceurl = $_SERVER['REQUEST_URI'];
2812
        }
2813
    }
2814
2815
    $output_string = '';
2816
    if (!empty($_SESSION['studentview'])) {
2817
        if ($_SESSION['studentview'] == 'studentview') {
2818
            // We have to remove the isStudentView=true from the $sourceurl
2819
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
2820
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
2821
            $output_string .= '<a class="btn btn-primary btn-sm" href="'.$sourceurl.'&isStudentView=false" target="_self">'.Display::returnFontAwesomeIcon('eye').' '.get_lang('SwitchToTeacherView').'</a>';
2822
        } elseif ($_SESSION['studentview'] == 'teacherview') {
2823
            // Switching to teacherview
2824
            $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
2825
            $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
2826
            $output_string .= '<a class="btn btn-default btn-sm" href="'.$sourceurl.'&isStudentView=true" target="_self">'.Display::returnFontAwesomeIcon('eye').' '.get_lang('SwitchToStudentView').'</a>';
2827
        }
2828
    } else {
2829
        $output_string .= '<a class="btn btn-default btn-sm" href="'.$sourceurl.'&isStudentView=true" target="_self">'.Display::returnFontAwesomeIcon('eye').' '.get_lang('SwitchToStudentView').'</a>';
2830
    }
2831
    $html = Display::tag('div', $output_string, array('class'=>'view-options'));
2832
    return $html;
2833
}
2834
2835
// TODO: This is for the permission section.
2836
/**
2837
 * Function that removes the need to directly use is_courseAdmin global in
2838
 * tool scripts. It returns true or false depending on the user's rights in
2839
 * this particular course.
2840
 * Optionally checking for tutor and coach roles here allows us to use the
2841
 * student_view feature altogether with these roles as well.
2842
 * @param bool  Whether to check if the user has the tutor role
2843
 * @param bool  Whether to check if the user has the coach role
2844
 * @param bool  Whether to check if the user has the session coach role
2845
 * @param bool  check the student view or not
2846
 *
2847
 * @author Roan Embrechts
2848
 * @author Patrick Cool
2849
 * @author Julio Montoya
2850
 * @version 1.1, February 2004
2851
 * @return boolean true: the user has the rights to edit, false: he does not
2852
 */
2853
2854
function api_is_allowed_to_edit(
2855
    $tutor = false,
2856
    $coach = false,
2857
    $session_coach = false,
2858
    $check_student_view = true
2859
) {
2860
    $my_session_id = api_get_session_id();
2861
    $is_allowed_coach_to_edit = api_is_coach(null, null, $check_student_view);
2862
    $session_visibility = api_get_session_visibility($my_session_id);
2863
2864
    // Admins can edit anything.
2865
    if (api_is_platform_admin(false)) {
2866
        // The student preview was on
2867
        if ($check_student_view && api_is_student_view_active()) {
2868
            return false;
2869
        } else {
2870
            return true;
2871
        }
2872
    }
2873
2874
    $is_courseAdmin = api_is_course_admin();
2875
2876
    if (!$is_courseAdmin && $tutor) {
2877
        // If we also want to check if the user is a tutor...
2878
        $is_courseAdmin = $is_courseAdmin || api_is_course_tutor();
2879
    }
2880
2881
    if (!$is_courseAdmin && $coach) {
2882
        // If we also want to check if the user is a coach...';
2883
        // Check if session visibility is read only for coaches.
2884
        if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
2885
            $is_allowed_coach_to_edit = false;
2886
        }
2887
2888
        if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
2889
            // Check if coach is allowed to edit a course.
2890
            $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
2891
        }
2892
    }
2893
2894
    if (!$is_courseAdmin && $session_coach) {
2895
        $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
2896
    }
2897
2898
    // Check if the student_view is enabled, and if so, if it is activated.
2899
    if (api_get_setting('student_view_enabled') == 'true') {
2900
        if (!empty($my_session_id)) {
2901
            // Check if session visibility is read only for coaches.
2902
            if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
2903
                $is_allowed_coach_to_edit = false;
2904
            }
2905
2906
            if (api_get_setting('allow_coach_to_edit_course_session') == 'true') {
2907
                // Check if coach is allowed to edit a course.
2908
                $is_allowed = $is_allowed_coach_to_edit;
2909
            } else {
2910
                $is_allowed = false;
2911
            }
2912
            if ($check_student_view) {
2913
                $is_allowed = $is_allowed && $_SESSION['studentview'] != 'studentview';
2914
            }
2915
        } else {
2916
            if ($check_student_view) {
2917
                $is_allowed = $is_courseAdmin && $_SESSION['studentview'] != 'studentview';
2918
            } else {
2919
                $is_allowed = $is_courseAdmin;
2920
            }
2921
        }
2922
2923
        return $is_allowed;
2924
    } else {
2925
2926
        return $is_courseAdmin;
2927
    }
2928
}
2929
2930
/**
2931
 * Returns true if user is a course coach of at least one course in session
2932
 * @param int $sessionId
2933
 * @return bool
2934
 */
2935
function api_is_coach_of_course_in_session($sessionId)
2936
{
2937
    if (api_is_platform_admin()) {
2938
        return true;
2939
    }
2940
2941
    $userId = api_get_user_id();
2942
    $courseList = UserManager::get_courses_list_by_session(
2943
        $userId,
2944
        $sessionId
2945
    );
2946
2947
    // Session visibility.
2948
    $visibility = api_get_session_visibility(
2949
        $sessionId,
2950
        null,
2951
        false
2952
    );
2953
2954 View Code Duplication
    if ($visibility != SESSION_VISIBLE && !empty($courseList)) {
2955
        // Course Coach session visibility.
2956
        $blockedCourseCount = 0;
2957
        $closedVisibilityList = array(
2958
            COURSE_VISIBILITY_CLOSED,
2959
            COURSE_VISIBILITY_HIDDEN
2960
        );
2961
2962
        foreach ($courseList as $course) {
2963
            // Checking session visibility
2964
            $sessionCourseVisibility = api_get_session_visibility(
2965
                $sessionId,
2966
                $course['real_id'],
2967
                $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...
2968
            );
2969
2970
            $courseIsVisible = !in_array(
2971
                $course['visibility'],
2972
                $closedVisibilityList
2973
            );
2974
            if ($courseIsVisible === false || $sessionCourseVisibility == SESSION_INVISIBLE) {
2975
                $blockedCourseCount++;
2976
            }
2977
        }
2978
2979
        // If all courses are blocked then no show in the list.
2980
        if ($blockedCourseCount === count($courseList)) {
2981
            $visibility = SESSION_INVISIBLE;
2982
        } else {
2983
            $visibility = SESSION_VISIBLE;
2984
        }
2985
    }
2986
2987
    switch ($visibility) {
2988
        case SESSION_VISIBLE_READ_ONLY:
2989
        case SESSION_VISIBLE:
2990
        case SESSION_AVAILABLE:
2991
            return true;
2992
            break;
2993
        case SESSION_INVISIBLE:
2994
            return false;
2995
    }
2996
2997
    return false;
2998
}
2999
3000
/**
3001
* Checks if a student can edit contents in a session depending
3002
* on the session visibility
3003
* @param bool $tutor  Whether to check if the user has the tutor role
3004
* @param bool  $coach Whether to check if the user has the coach role
3005
* @return boolean true: the user has the rights to edit, false: he does not
3006
*/
3007
function api_is_allowed_to_session_edit($tutor = false, $coach = false)
3008
{
3009
    if (api_is_allowed_to_edit($tutor, $coach)) {
3010
        // If I'm a teacher, I will return true in order to not affect the normal behaviour of Chamilo tools.
3011
        return true;
3012
    } else {
3013
        if (api_get_session_id() == 0) {
3014
            // I'm not in a session so i will return true to not affect the normal behaviour of Chamilo tools.
3015
            return true;
3016
        } else {
3017
            // I'm in a session and I'm a student
3018
            $session_id = api_get_session_id();
3019
3020
            // Get the session visibility
3021
            $session_visibility = api_get_session_visibility($session_id);
3022
            // if 5 the session is still available
3023
3024
            //@todo We could load the session_rel_course_rel_user permission to increase the level of detail.
3025
            //echo api_get_user_id();
3026
            //echo api_get_course_id();
3027
3028
            switch ($session_visibility) {
3029
                case SESSION_VISIBLE_READ_ONLY: // 1
3030
                    return false;
3031
                case SESSION_VISIBLE:           // 2
3032
                    return true;
3033
                case SESSION_INVISIBLE:         // 3
3034
                    return false;
3035
                case SESSION_AVAILABLE:         //5
3036
                    return true;
3037
            }
3038
        }
3039
    }
3040
}
3041
3042
/**
3043
* Checks whether the user is allowed in a specific tool for a specific action
3044
* @param string $tool the tool we are checking if the user has a certain permission
3045
* @param string $action the action we are checking (add, edit, delete, move, visibility)
3046
* @author Patrick Cool <[email protected]>, Ghent University
3047
* @author Julio Montoya
3048
* @version 1.0
3049
*/
3050
function api_is_allowed($tool, $action, $task_id = 0)
3051
{
3052
    $_user = api_get_user_info();
3053
    $_course = api_get_course_info();
3054
3055
    if (api_is_course_admin()) {
3056
        return true;
3057
    }
3058
    //if (!$_SESSION['total_permissions'][$_course['code']] and $_course)
3059
    if (is_array($_course) and count($_course) > 0) {
3060
        require_once api_get_path(SYS_CODE_PATH).'permissions/permissions_functions.inc.php';
3061
3062
        // Getting the permissions of this user.
3063
        if ($task_id == 0) {
3064
            $user_permissions = get_permissions('user', $_user['user_id']);
3065
            $_SESSION['total_permissions'][$_course['code']] = $user_permissions;
3066
        }
3067
3068
        // Getting the permissions of the task.
3069
        if ($task_id != 0) {
3070
            $task_permissions = get_permissions('task', $task_id);
3071
            /* !!! */$_SESSION['total_permissions'][$_course['code']] = $task_permissions;
3072
        }
3073
        //print_r($_SESSION['total_permissions']);
3074
3075
        // Getting the permissions of the groups of the user
3076
        //$groups_of_user = GroupManager::get_group_ids($_course['db_name'], $_user['user_id']);
3077
3078
        //foreach($groups_of_user as $group)
3079
        //   $this_group_permissions = get_permissions('group', $group);
3080
3081
        // Getting the permissions of the courseroles of the user
3082
        $user_courserole_permissions = get_roles_permissions('user', $_user['user_id']);
3083
3084
        // Getting the permissions of the platformroles of the user
3085
        //$user_platformrole_permissions = get_roles_permissions('user', $_user['user_id'], ', platform');
3086
3087
        // Getting the permissions of the roles of the groups of the user
3088
        //foreach($groups_of_user as $group)
3089
        //    $this_group_courserole_permissions = get_roles_permissions('group', $group);
3090
3091
        // Getting the permissions of the platformroles of the groups of the user
3092
        //foreach($groups_of_user as $group)
3093
        //    $this_group_platformrole_permissions = get_roles_permissions('group', $group, 'platform');
3094
    }
3095
3096
    // If the permissions are limited, we have to map the extended ones to the limited ones.
3097
    if (api_get_setting('permissions') == 'limited') {
3098
        if ($action == 'Visibility') {
3099
            $action = 'Edit';
3100
        }
3101
        if ($action == 'Move') {
3102
            $action = 'Edit';
3103
        }
3104
    }
3105
3106
    // The session that contains all the permissions already exists for this course
3107
    // so there is no need to requery everything.
3108
    //my_print_r($_SESSION['total_permissions'][$_course['code']][$tool]);
3109
    if (is_array($_SESSION['total_permissions'][$_course['code']][$tool])) {
3110
        if (in_array($action, $_SESSION['total_permissions'][$_course['code']][$tool])) {
3111
            return true;
3112
        } else {
3113
            return false;
3114
        }
3115
    }
3116
}
3117
3118
/**
3119
 * Tells whether this user is an anonymous user
3120
 * @param int  $user_id      User ID (optional, will take session ID if not provided)
3121
 * @param bool $db_check     Whether to check in the database (true) or simply in
3122
 * the session (false) to see if the current user is the anonymous user
3123
 * @return bool     true if this user is anonymous, false otherwise
3124
 */
3125
function api_is_anonymous($user_id = null, $db_check = false)
3126
{
3127
    if (!isset($user_id)) {
3128
        $user_id = api_get_user_id();
3129
    }
3130
3131
    if ($db_check) {
3132
        $info = api_get_user_info($user_id);
3133
        if ($info['status'] == ANONYMOUS) {
3134
            return true;
3135
        }
3136
    }
3137
3138
    $_user = api_get_user_info();
3139
3140
    if (isset($_user['status']) && $_user['status'] == ANONYMOUS) {
3141
        //if ($_user['user_id'] == 0) {
3142
        // In some cases, api_set_anonymous doesn't seem to be triggered in local.inc.php. Make sure it is.
3143
        // Occurs in agenda for admin links - YW
3144
        global $use_anonymous;
3145
        if (isset($use_anonymous) && $use_anonymous) {
3146
            api_set_anonymous();
3147
        }
3148
3149
        return true;
3150
    }
3151
3152
    return (isset($_user['is_anonymous']) && $_user['is_anonymous'] === true) || $_user === false;
3153
}
3154
3155
/**
3156
 * Displays message "You are not allowed here..." and exits the entire script.
3157
 * @param bool   $print_headers    Whether or not to print headers (default = false -> does not print them)
3158
 * @param string $message
3159
 */
3160
function api_not_allowed($print_headers = false, $message = null)
3161
{
3162
    if (empty($message)) {
3163
        $message = get_lang('NotAllowed');
3164
    }
3165
    throw new Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException($message);
3166
3167
    if (api_get_setting('sso_authentication') === 'true') {
0 ignored issues
show
Unused Code introduced by
if (api_get_setting('sso...osso->logout(); } } does not seem to be reachable.

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

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

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

    return false;
}

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

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