1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* For licensing terms, see /license.txt */ |
4
|
|
|
|
5
|
|
|
use Chamilo\CoreBundle\Entity\ExtraField as EntityExtraField; |
6
|
|
|
use Chamilo\CoreBundle\Entity\Repository\AccessUrlRepository; |
7
|
|
|
use Chamilo\CoreBundle\Entity\Session as SessionEntity; |
8
|
|
|
use Chamilo\CoreBundle\Entity\SkillRelUser; |
|
|
|
|
9
|
|
|
use Chamilo\CoreBundle\Entity\SkillRelUserComment; |
10
|
|
|
use Chamilo\CoreBundle\Entity\TrackELoginAttempt; |
11
|
|
|
use Chamilo\UserBundle\Entity\User; |
12
|
|
|
use Chamilo\UserBundle\Repository\UserRepository; |
13
|
|
|
use ChamiloSession as Session; |
14
|
|
|
use Symfony\Component\Filesystem\Filesystem; |
15
|
|
|
use Symfony\Component\Security\Core\Encoder\EncoderFactory; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Class UserManager. |
19
|
|
|
* |
20
|
|
|
* This library provides functions for user management. |
21
|
|
|
* Include/require it in your code to use its functionality. |
22
|
|
|
* |
23
|
|
|
* @author Julio Montoya <[email protected]> Social network groups added 2009/12 |
24
|
|
|
*/ |
25
|
|
|
class UserManager |
26
|
|
|
{ |
27
|
|
|
// This constants are deprecated use the constants located in ExtraField |
28
|
|
|
public const USER_FIELD_TYPE_TEXT = 1; |
29
|
|
|
public const USER_FIELD_TYPE_TEXTAREA = 2; |
30
|
|
|
public const USER_FIELD_TYPE_RADIO = 3; |
31
|
|
|
public const USER_FIELD_TYPE_SELECT = 4; |
32
|
|
|
public const USER_FIELD_TYPE_SELECT_MULTIPLE = 5; |
33
|
|
|
public const USER_FIELD_TYPE_DATE = 6; |
34
|
|
|
public const USER_FIELD_TYPE_DATETIME = 7; |
35
|
|
|
public const USER_FIELD_TYPE_DOUBLE_SELECT = 8; |
36
|
|
|
public const USER_FIELD_TYPE_DIVIDER = 9; |
37
|
|
|
public const USER_FIELD_TYPE_TAG = 10; |
38
|
|
|
public const USER_FIELD_TYPE_TIMEZONE = 11; |
39
|
|
|
public const USER_FIELD_TYPE_SOCIAL_PROFILE = 12; |
40
|
|
|
public const USER_FIELD_TYPE_FILE = 13; |
41
|
|
|
public const USER_FIELD_TYPE_MOBILE_PHONE_NUMBER = 14; |
42
|
|
|
|
43
|
|
|
private static $encryptionMethod; |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* Constructor. |
47
|
|
|
* |
48
|
|
|
* @assert () === null |
49
|
|
|
*/ |
50
|
|
|
public function __construct() |
51
|
|
|
{ |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* Repository is use to query the DB, selects, etc. |
56
|
|
|
* |
57
|
|
|
* @return UserRepository |
58
|
|
|
*/ |
59
|
|
|
public static function getRepository() |
60
|
|
|
{ |
61
|
|
|
/** @var UserRepository $userRepository */ |
62
|
|
|
|
63
|
|
|
return Database::getManager()->getRepository('ChamiloUserBundle:User'); |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* Create/update/delete methods are available in the UserManager |
68
|
|
|
* (based in the Sonata\UserBundle\Entity\UserManager). |
69
|
|
|
* |
70
|
|
|
* @return Chamilo\UserBundle\Entity\Manager\UserManager |
71
|
|
|
*/ |
72
|
|
|
public static function getManager() |
73
|
|
|
{ |
74
|
|
|
static $userManager; |
75
|
|
|
|
76
|
|
|
if (!isset($userManager)) { |
77
|
|
|
$encoderFactory = self::getEncoderFactory(); |
78
|
|
|
$passwordUpdater = new \FOS\UserBundle\Util\PasswordUpdater($encoderFactory); |
79
|
|
|
$canonicalFieldUpdater = new \FOS\UserBundle\Util\CanonicalFieldsUpdater( |
80
|
|
|
new \FOS\UserBundle\Util\Canonicalizer(), new \FOS\UserBundle\Util\Canonicalizer() |
81
|
|
|
); |
82
|
|
|
$userManager = new Chamilo\UserBundle\Entity\Manager\UserManager( |
83
|
|
|
$passwordUpdater, |
84
|
|
|
$canonicalFieldUpdater, |
85
|
|
|
Database::getManager(), |
86
|
|
|
'Chamilo\\UserBundle\\Entity\\User' |
87
|
|
|
); |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
return $userManager; |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* @param string $encryptionMethod |
95
|
|
|
*/ |
96
|
|
|
public static function setPasswordEncryption($encryptionMethod) |
97
|
|
|
{ |
98
|
|
|
self::$encryptionMethod = $encryptionMethod; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* @return bool|mixed |
103
|
|
|
*/ |
104
|
|
|
public static function getPasswordEncryption() |
105
|
|
|
{ |
106
|
|
|
$encryptionMethod = self::$encryptionMethod; |
107
|
|
|
if (empty($encryptionMethod)) { |
108
|
|
|
$encryptionMethod = api_get_configuration_value('password_encryption'); |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
return $encryptionMethod; |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* Validates the password. |
116
|
|
|
* |
117
|
|
|
* @param $encoded |
118
|
|
|
* @param $raw |
119
|
|
|
* @param $salt |
120
|
|
|
* |
121
|
|
|
* @return bool |
122
|
|
|
*/ |
123
|
|
|
public static function isPasswordValid($encoded, $raw, $salt) |
124
|
|
|
{ |
125
|
|
|
$encoder = new \Chamilo\UserBundle\Security\Encoder(self::getPasswordEncryption()); |
126
|
|
|
|
127
|
|
|
return $encoder->isPasswordValid($encoded, $raw, $salt); |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* Detects and returns the type of encryption of the given encrypted |
132
|
|
|
* password. |
133
|
|
|
* |
134
|
|
|
* @param string $encoded The encrypted password |
135
|
|
|
* @param string $salt The user salt, if any |
136
|
|
|
*/ |
137
|
|
|
public static function detectPasswordEncryption(string $encoded, string $salt): string |
138
|
|
|
{ |
139
|
|
|
$encryption = false; |
140
|
|
|
|
141
|
|
|
$length = strlen($encoded); |
142
|
|
|
|
143
|
|
|
$pattern = '/^\$2y\$04\$[A-Za-z0-9\.\/]{53}$/'; |
144
|
|
|
|
145
|
|
|
if ($length == 60 && preg_match($pattern, $encoded)) { |
146
|
|
|
$encryption = 'bcrypt'; |
147
|
|
|
} elseif ($length == 32 && ctype_xdigit($encoded)) { |
148
|
|
|
$encryption = 'md5'; |
149
|
|
|
} elseif ($length == 40 && ctype_xdigit($encoded)) { |
150
|
|
|
$encryption = 'sha1'; |
151
|
|
|
} else { |
152
|
|
|
$start = strpos($encoded, '{'); |
153
|
|
|
if ($start !== false && substr($encoded, -1, 1) == '}') { |
154
|
|
|
if (substr($encoded, $start + 1, -1) == $salt) { |
155
|
|
|
$encryption = 'none'; |
156
|
|
|
} |
157
|
|
|
} |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
return $encryption; |
|
|
|
|
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
/** |
164
|
|
|
* Checks if the password is correct for this user. |
165
|
|
|
* If the password_conversion setting is true, also update the password |
166
|
|
|
* in the database to a new encryption method. |
167
|
|
|
* |
168
|
|
|
* @param string $encoded Encrypted password |
169
|
|
|
* @param string $raw Clear password given through login form |
170
|
|
|
* @param string $salt User salt, if any |
171
|
|
|
* @param int $userId The user's internal ID |
172
|
|
|
*/ |
173
|
|
|
public static function checkPassword(string $encoded, string $raw, string $salt, int $userId): bool |
174
|
|
|
{ |
175
|
|
|
$result = false; |
176
|
|
|
|
177
|
|
|
if (true === api_get_configuration_value('password_conversion')) { |
178
|
|
|
$detectedEncryption = self::detectPasswordEncryption($encoded, $salt); |
179
|
|
|
if (self::getPasswordEncryption() != $detectedEncryption) { |
180
|
|
|
$encoder = new \Chamilo\UserBundle\Security\Encoder($detectedEncryption); |
181
|
|
|
$result = $encoder->isPasswordValid($encoded, $raw, $salt); |
182
|
|
|
if ($result) { |
183
|
|
|
$raw = $encoder->encodePassword($encoded, $salt); |
184
|
|
|
self::updatePassword($userId, $raw); |
185
|
|
|
} |
186
|
|
|
} else { |
187
|
|
|
$result = self::isPasswordValid($encoded, $raw, $salt); |
188
|
|
|
} |
189
|
|
|
} else { |
190
|
|
|
$result = self::isPasswordValid($encoded, $raw, $salt); |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
return $result; |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* Encrypt the password using the current encoder. |
198
|
|
|
* |
199
|
|
|
* @param string $raw The clear password |
200
|
|
|
*/ |
201
|
|
|
public static function encryptPassword(string $raw, User $user): string |
202
|
|
|
{ |
203
|
|
|
$encoder = self::getEncoder($user); |
204
|
|
|
|
205
|
|
|
return $encoder->encodePassword( |
206
|
|
|
$raw, |
207
|
|
|
$user->getSalt() |
208
|
|
|
); |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
/** |
212
|
|
|
* Update the password of the given user to the given (in-clear) password. |
213
|
|
|
* |
214
|
|
|
* @param int $userId Internal user ID |
215
|
|
|
* @param string $password Password in clear |
216
|
|
|
*/ |
217
|
|
|
public static function updatePassword(int $userId, string $password): void |
218
|
|
|
{ |
219
|
|
|
$repository = self::getRepository(); |
220
|
|
|
/** @var User $user */ |
221
|
|
|
$user = $repository->find($userId); |
222
|
|
|
$userManager = self::getManager(); |
223
|
|
|
$user->setPlainPassword($password); |
224
|
|
|
$userManager->updateUser($user, true); |
225
|
|
|
Event::addEvent(LOG_USER_PASSWORD_UPDATE, LOG_USER_ID, $userId); |
|
|
|
|
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
/** |
229
|
|
|
* Updates user expiration date. |
230
|
|
|
* |
231
|
|
|
* @param int $userId |
232
|
|
|
* @param string $expirationDate |
233
|
|
|
*/ |
234
|
|
|
public static function updateExpirationDate($userId, $expirationDate) |
235
|
|
|
{ |
236
|
|
|
$repository = self::getRepository(); |
237
|
|
|
/** @var User $user */ |
238
|
|
|
$user = $repository->find($userId); |
239
|
|
|
$userManager = self::getManager(); |
240
|
|
|
$expirationDate = api_get_utc_datetime($expirationDate, false, true); |
241
|
|
|
$user->setExpirationDate($expirationDate); |
242
|
|
|
$userManager->updateUser($user, true); |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* Creates a new user for the platform. |
247
|
|
|
* |
248
|
|
|
* @author Hugues Peeters <[email protected]>, |
249
|
|
|
* @author Roan Embrechts <[email protected]> |
250
|
|
|
* |
251
|
|
|
* @param string $firstName |
252
|
|
|
* @param string $lastName |
253
|
|
|
* @param int $status (1 for course tutor, 5 for student, 6 for anonymous) |
254
|
|
|
* @param string $email |
255
|
|
|
* @param string $loginName |
256
|
|
|
* @param string $password |
257
|
|
|
* @param string $official_code Any official code (optional) |
258
|
|
|
* @param string $language User language (optional) |
259
|
|
|
* @param string $phone Phone number (optional) |
260
|
|
|
* @param string $picture_uri Picture URI (optional) |
261
|
|
|
* @param string $authSource Authentication source (defaults to 'platform', dependind on constant) |
262
|
|
|
* @param string $expirationDate Account expiration date (optional, defaults to null) |
263
|
|
|
* @param int $active Whether the account is enabled or disabled by default |
264
|
|
|
* @param int $hr_dept_id The department of HR in which the user is registered (defaults to 0) |
265
|
|
|
* @param array $extra Extra fields (prefix labels with "extra_") |
266
|
|
|
* @param string $encrypt_method Used if password is given encrypted. Set to an empty string by default |
267
|
|
|
* @param bool $send_mail |
268
|
|
|
* @param bool $isAdmin |
269
|
|
|
* @param string $address |
270
|
|
|
* @param bool $sendEmailToAllAdmins |
271
|
|
|
* @param FormValidator $form |
272
|
|
|
* @param int $creatorId |
273
|
|
|
* @param array $emailTemplate |
274
|
|
|
* @param string $redirectToURLAfterLogin |
275
|
|
|
* |
276
|
|
|
* @return mixed new user id - if the new user creation succeeds, false otherwise |
277
|
|
|
* @desc The function tries to retrieve user id from the session. |
278
|
|
|
* If it exists, the current user id is the creator id. If a problem arises, |
279
|
|
|
* @assert ('Sam','Gamegie',5,'[email protected]','jo','jo') > 1 |
280
|
|
|
* @assert ('Pippin','Took',null,null,'jo','jo') === false |
281
|
|
|
*/ |
282
|
|
|
public static function create_user( |
283
|
|
|
$firstName, |
284
|
|
|
$lastName, |
285
|
|
|
$status, |
286
|
|
|
$email, |
287
|
|
|
$loginName, |
288
|
|
|
$password, |
289
|
|
|
$official_code = '', |
290
|
|
|
$language = '', |
291
|
|
|
$phone = '', |
292
|
|
|
$picture_uri = '', |
293
|
|
|
$authSource = PLATFORM_AUTH_SOURCE, |
294
|
|
|
$expirationDate = null, |
295
|
|
|
$active = 1, |
296
|
|
|
$hr_dept_id = 0, |
297
|
|
|
$extra = [], |
298
|
|
|
$encrypt_method = '', |
299
|
|
|
$send_mail = false, |
300
|
|
|
$isAdmin = false, |
301
|
|
|
$address = '', |
302
|
|
|
$sendEmailToAllAdmins = false, |
303
|
|
|
$form = null, |
304
|
|
|
$creatorId = 0, |
305
|
|
|
$emailTemplate = [], |
306
|
|
|
$redirectToURLAfterLogin = '' |
307
|
|
|
) { |
308
|
|
|
$creatorId = empty($creatorId) ? api_get_user_id() : 0; |
309
|
|
|
$creatorInfo = api_get_user_info($creatorId); |
310
|
|
|
$creatorEmail = isset($creatorInfo['email']) ? $creatorInfo['email'] : ''; |
311
|
|
|
|
312
|
|
|
$hook = HookCreateUser::create(); |
313
|
|
|
if (!empty($hook)) { |
314
|
|
|
$hook->notifyCreateUser(HOOK_EVENT_TYPE_PRE); |
315
|
|
|
} |
316
|
|
|
|
317
|
|
|
if ('true' === api_get_setting('registration', 'email')) { |
318
|
|
|
// Force email validation. |
319
|
|
|
if (false === api_valid_email($email)) { |
320
|
|
|
Display::addFlash( |
321
|
|
|
Display::return_message(get_lang('PleaseEnterValidEmail').' - '.$email, 'warning') |
322
|
|
|
); |
323
|
|
|
|
324
|
|
|
return false; |
325
|
|
|
} |
326
|
|
|
} else { |
327
|
|
|
// Allow empty email. If email is set, check if is valid. |
328
|
|
|
if (!empty($email) && false === api_valid_email($email)) { |
329
|
|
|
Display::addFlash( |
330
|
|
|
Display::return_message(get_lang('PleaseEnterValidEmail').' - '.$email, 'warning') |
331
|
|
|
); |
332
|
|
|
|
333
|
|
|
return false; |
334
|
|
|
} |
335
|
|
|
} |
336
|
|
|
|
337
|
|
|
if ('true' === api_get_setting('login_is_email')) { |
338
|
|
|
if (false === api_valid_email($loginName)) { |
339
|
|
|
Display::addFlash( |
340
|
|
|
Display::return_message(get_lang('PleaseEnterValidEmail').' - '.$loginName, 'warning') |
341
|
|
|
); |
342
|
|
|
|
343
|
|
|
return false; |
344
|
|
|
} |
345
|
|
|
} else { |
346
|
|
|
if (false === self::is_username_valid($loginName)) { |
347
|
|
|
Display::addFlash( |
348
|
|
|
Display::return_message(get_lang('UsernameWrong').' - '.$loginName, 'warning') |
349
|
|
|
); |
350
|
|
|
|
351
|
|
|
return false; |
352
|
|
|
} |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
// First check wether the login already exists |
356
|
|
|
if (!self::is_username_available($loginName)) { |
357
|
|
|
Display::addFlash( |
358
|
|
|
Display::return_message(get_lang('LoginAlreadyTaken').' - '.$loginName, 'warning') |
359
|
|
|
); |
360
|
|
|
|
361
|
|
|
return false; |
362
|
|
|
} |
363
|
|
|
|
364
|
|
|
global $_configuration; |
365
|
|
|
$original_password = $password; |
366
|
|
|
|
367
|
|
|
$access_url_id = 1; |
368
|
|
|
if (api_get_multiple_access_url()) { |
369
|
|
|
$access_url_id = api_get_current_access_url_id(); |
370
|
|
|
} else { |
371
|
|
|
// In some cases, the first access_url ID might be different from 1 |
372
|
|
|
// for example when using a DB cluster or hacking the DB manually. |
373
|
|
|
// In this case, we want the first row, not necessarily "1". |
374
|
|
|
$dbm = Database::getManager(); |
375
|
|
|
/** @var AccessUrlRepository $accessUrlRepository */ |
376
|
|
|
$accessUrlRepository = $dbm->getRepository('ChamiloCoreBundle:AccessUrl'); |
377
|
|
|
$accessUrl = $accessUrlRepository->getFirstId(); |
378
|
|
|
if (!empty($accessUrl[0]) && !empty($accessUrl[0][1])) { |
379
|
|
|
$access_url_id = $accessUrl[0][1]; |
380
|
|
|
} |
381
|
|
|
} |
382
|
|
|
|
383
|
|
|
if (isset($_configuration[$access_url_id]) && |
384
|
|
|
is_array($_configuration[$access_url_id]) && |
385
|
|
|
isset($_configuration[$access_url_id]['hosting_limit_users']) && |
386
|
|
|
$_configuration[$access_url_id]['hosting_limit_users'] > 0) { |
387
|
|
|
$num = self::get_number_of_users(null, $access_url_id); |
388
|
|
|
if ($num >= $_configuration[$access_url_id]['hosting_limit_users']) { |
389
|
|
|
api_warn_hosting_contact('hosting_limit_users'); |
390
|
|
|
Display::addFlash( |
391
|
|
|
Display::return_message( |
392
|
|
|
get_lang('PortalUsersLimitReached'), |
393
|
|
|
'warning' |
394
|
|
|
) |
395
|
|
|
); |
396
|
|
|
|
397
|
|
|
return false; |
398
|
|
|
} |
399
|
|
|
} |
400
|
|
|
|
401
|
|
|
if ($status === 1 && |
402
|
|
|
isset($_configuration[$access_url_id]) && |
403
|
|
|
is_array($_configuration[$access_url_id]) && |
404
|
|
|
isset($_configuration[$access_url_id]['hosting_limit_teachers']) && |
405
|
|
|
$_configuration[$access_url_id]['hosting_limit_teachers'] > 0 |
406
|
|
|
) { |
407
|
|
|
$num = self::get_number_of_users(1, $access_url_id); |
408
|
|
|
if ($num >= $_configuration[$access_url_id]['hosting_limit_teachers']) { |
409
|
|
|
Display::addFlash( |
410
|
|
|
Display::return_message( |
411
|
|
|
get_lang('PortalTeachersLimitReached'), |
412
|
|
|
'warning' |
413
|
|
|
) |
414
|
|
|
); |
415
|
|
|
api_warn_hosting_contact('hosting_limit_teachers'); |
416
|
|
|
|
417
|
|
|
return false; |
418
|
|
|
} |
419
|
|
|
} |
420
|
|
|
|
421
|
|
|
if (empty($password)) { |
422
|
|
|
if ($authSource === PLATFORM_AUTH_SOURCE) { |
423
|
|
|
Display::addFlash( |
424
|
|
|
Display::return_message( |
425
|
|
|
get_lang('ThisFieldIsRequired').': '.get_lang( |
426
|
|
|
'Password' |
427
|
|
|
), |
428
|
|
|
'warning' |
429
|
|
|
) |
430
|
|
|
); |
431
|
|
|
|
432
|
|
|
return false; |
433
|
|
|
} |
434
|
|
|
|
435
|
|
|
// We use the authSource as password. |
436
|
|
|
// The real validation will be by processed by the auth |
437
|
|
|
// source not Chamilo |
438
|
|
|
$password = $authSource; |
439
|
|
|
} |
440
|
|
|
|
441
|
|
|
// database table definition |
442
|
|
|
$table_user = Database::get_main_table(TABLE_MAIN_USER); |
443
|
|
|
|
444
|
|
|
// Checking the user language |
445
|
|
|
$languages = api_get_languages(); |
446
|
|
|
$language = strtolower($language); |
447
|
|
|
|
448
|
|
|
if (isset($languages['folder'])) { |
449
|
|
|
if (!in_array($language, $languages['folder'])) { |
450
|
|
|
$language = api_get_setting('platformLanguage'); |
451
|
|
|
} |
452
|
|
|
} |
453
|
|
|
|
454
|
|
|
$currentDate = api_get_utc_datetime(); |
455
|
|
|
$now = new DateTime(); |
456
|
|
|
|
457
|
|
|
if (empty($expirationDate) || $expirationDate == '0000-00-00 00:00:00') { |
458
|
|
|
// Default expiration date |
459
|
|
|
// if there is a default duration of a valid account then |
460
|
|
|
// we have to change the expiration_date accordingly |
461
|
|
|
// Accept 0000-00-00 00:00:00 as a null value to avoid issues with |
462
|
|
|
// third party code using this method with the previous (pre-1.10) |
463
|
|
|
// value of 0000... |
464
|
|
|
if (api_get_setting('account_valid_duration') != '') { |
465
|
|
|
$expirationDate = new DateTime($currentDate); |
466
|
|
|
$days = (int) api_get_setting('account_valid_duration'); |
467
|
|
|
$expirationDate->modify('+'.$days.' day'); |
468
|
|
|
} |
469
|
|
|
} else { |
470
|
|
|
$expirationDate = api_get_utc_datetime($expirationDate); |
471
|
|
|
$expirationDate = new \DateTime($expirationDate, new DateTimeZone('UTC')); |
472
|
|
|
} |
473
|
|
|
|
474
|
|
|
$userManager = self::getManager(); |
475
|
|
|
|
476
|
|
|
/** @var User $user */ |
477
|
|
|
$user = $userManager->createUser(); |
478
|
|
|
|
479
|
|
|
$user |
480
|
|
|
->setLastname($lastName) |
481
|
|
|
->setFirstname($firstName) |
482
|
|
|
->setUsername($loginName) |
483
|
|
|
->setStatus($status) |
484
|
|
|
->setPlainPassword($password) |
485
|
|
|
->setEmail($email) |
486
|
|
|
->setOfficialCode($official_code) |
487
|
|
|
->setPictureUri($picture_uri) |
488
|
|
|
->setCreatorId($creatorId) |
489
|
|
|
->setAuthSource($authSource) |
490
|
|
|
->setPhone($phone) |
491
|
|
|
->setAddress($address) |
492
|
|
|
->setLanguage($language) |
493
|
|
|
->setRegistrationDate($now) |
494
|
|
|
->setHrDeptId($hr_dept_id) |
495
|
|
|
->setActive($active) |
496
|
|
|
->setEnabled($active) |
497
|
|
|
; |
498
|
|
|
|
499
|
|
|
if (!empty($expirationDate)) { |
500
|
|
|
$user->setExpirationDate($expirationDate); |
501
|
|
|
} |
502
|
|
|
|
503
|
|
|
$userManager->updateUser($user); |
504
|
|
|
$userId = $user->getId(); |
505
|
|
|
|
506
|
|
|
if (!empty($userId)) { |
507
|
|
|
$return = $userId; |
508
|
|
|
$sql = "UPDATE $table_user SET user_id = $return WHERE id = $return"; |
509
|
|
|
Database::query($sql); |
510
|
|
|
|
511
|
|
|
if ($isAdmin) { |
512
|
|
|
self::addUserAsAdmin($user); |
513
|
|
|
} |
514
|
|
|
|
515
|
|
|
if (api_get_multiple_access_url()) { |
516
|
|
|
UrlManager::add_user_to_url($userId, api_get_current_access_url_id()); |
517
|
|
|
} else { |
518
|
|
|
//we are adding by default the access_url_user table with access_url_id = 1 |
519
|
|
|
UrlManager::add_user_to_url($userId, 1); |
520
|
|
|
} |
521
|
|
|
|
522
|
|
|
$extra['item_id'] = $userId; |
523
|
|
|
|
524
|
|
|
if (is_array($extra) && count($extra) > 0) { |
525
|
|
|
$userFieldValue = new ExtraFieldValue('user'); |
526
|
|
|
// Force saving of extra fields (otherwise, if the current |
527
|
|
|
// user is not admin, fields not visible to the user - most |
528
|
|
|
// of them - are just ignored) |
529
|
|
|
$userFieldValue->saveFieldValues( |
530
|
|
|
$extra, |
531
|
|
|
true, |
532
|
|
|
null, |
533
|
|
|
null, |
534
|
|
|
null, |
535
|
|
|
true |
536
|
|
|
); |
537
|
|
|
} else { |
538
|
|
|
// Create notify settings by default |
539
|
|
|
self::update_extra_field_value( |
540
|
|
|
$userId, |
541
|
|
|
'mail_notify_invitation', |
542
|
|
|
'1' |
543
|
|
|
); |
544
|
|
|
self::update_extra_field_value( |
545
|
|
|
$userId, |
546
|
|
|
'mail_notify_message', |
547
|
|
|
'1' |
548
|
|
|
); |
549
|
|
|
self::update_extra_field_value( |
550
|
|
|
$userId, |
551
|
|
|
'mail_notify_group_message', |
552
|
|
|
'1' |
553
|
|
|
); |
554
|
|
|
} |
555
|
|
|
|
556
|
|
|
self::update_extra_field_value( |
557
|
|
|
$userId, |
558
|
|
|
'already_logged_in', |
559
|
|
|
'false' |
560
|
|
|
); |
561
|
|
|
|
562
|
|
|
if (!empty($redirectToURLAfterLogin) && api_get_configuration_value('plugin_redirection_enabled')) { |
563
|
|
|
RedirectionPlugin::insert($userId, $redirectToURLAfterLogin); |
564
|
|
|
} |
565
|
|
|
|
566
|
|
|
if (!empty($email) && $send_mail) { |
567
|
|
|
$recipient_name = api_get_person_name( |
568
|
|
|
$firstName, |
569
|
|
|
$lastName, |
570
|
|
|
null, |
571
|
|
|
PERSON_NAME_EMAIL_ADDRESS |
572
|
|
|
); |
573
|
|
|
$tplSubject = new Template( |
574
|
|
|
null, |
575
|
|
|
false, |
576
|
|
|
false, |
577
|
|
|
false, |
578
|
|
|
false, |
579
|
|
|
false |
580
|
|
|
); |
581
|
|
|
// the complete_name is not used in the default Chamilo template but used in a specific template -refs BT#21334 |
582
|
|
|
$tplSubject->assign('complete_name', stripslashes(api_get_person_name($firstName, $lastName))); |
583
|
|
|
$layoutSubject = $tplSubject->get_template('mail/subject_registration_platform.tpl'); |
584
|
|
|
$emailSubject = $tplSubject->fetch($layoutSubject); |
585
|
|
|
$sender_name = api_get_person_name( |
586
|
|
|
api_get_setting('administratorName'), |
587
|
|
|
api_get_setting('administratorSurname'), |
588
|
|
|
null, |
589
|
|
|
PERSON_NAME_EMAIL_ADDRESS |
590
|
|
|
); |
591
|
|
|
$email_admin = api_get_setting('emailAdministrator'); |
592
|
|
|
|
593
|
|
|
$url = api_get_path(WEB_PATH); |
594
|
|
|
if (api_is_multiple_url_enabled()) { |
595
|
|
|
$access_url_id = api_get_current_access_url_id(); |
596
|
|
|
if ($access_url_id != -1) { |
597
|
|
|
$urlInfo = api_get_access_url($access_url_id); |
598
|
|
|
if ($urlInfo) { |
|
|
|
|
599
|
|
|
$url = $urlInfo['url']; |
600
|
|
|
} |
601
|
|
|
} |
602
|
|
|
} |
603
|
|
|
|
604
|
|
|
$tplContent = new Template( |
605
|
|
|
null, |
606
|
|
|
false, |
607
|
|
|
false, |
608
|
|
|
false, |
609
|
|
|
false, |
610
|
|
|
false |
611
|
|
|
); |
612
|
|
|
// variables for the default template |
613
|
|
|
$tplContent->assign('complete_name', stripslashes(api_get_person_name($firstName, $lastName))); |
614
|
|
|
$tplContent->assign('login_name', $loginName); |
615
|
|
|
$tplContent->assign('original_password', stripslashes($original_password)); |
616
|
|
|
$tplContent->assign('mailWebPath', $url); |
617
|
|
|
$tplContent->assign('new_user', $user); |
618
|
|
|
// Adding this variable but not used in default template, used for task BT19518 with a customized template |
619
|
|
|
$tplContent->assign('status_type', $status); |
620
|
|
|
|
621
|
|
|
$layoutContent = $tplContent->get_template('mail/content_registration_platform.tpl'); |
622
|
|
|
$emailBody = $tplContent->fetch($layoutContent); |
623
|
|
|
|
624
|
|
|
$userInfo = api_get_user_info($userId); |
625
|
|
|
$mailTemplateManager = new MailTemplateManager(); |
626
|
|
|
|
627
|
|
|
/* MANAGE EVENT WITH MAIL */ |
628
|
|
|
if (EventsMail::check_if_using_class('user_registration')) { |
629
|
|
|
$values["about_user"] = $return; |
|
|
|
|
630
|
|
|
$values["password"] = $original_password; |
631
|
|
|
$values["send_to"] = [$return]; |
632
|
|
|
$values["prior_lang"] = null; |
633
|
|
|
EventsDispatcher::events('user_registration', $values); |
634
|
|
|
} else { |
635
|
|
|
$phoneNumber = isset($extra['mobile_phone_number']) ? $extra['mobile_phone_number'] : null; |
636
|
|
|
$additionalParameters = [ |
637
|
|
|
'smsType' => SmsPlugin::WELCOME_LOGIN_PASSWORD, |
638
|
|
|
'userId' => $return, |
639
|
|
|
'mobilePhoneNumber' => $phoneNumber, |
640
|
|
|
'password' => $original_password, |
641
|
|
|
]; |
642
|
|
|
|
643
|
|
|
$emailBodyTemplate = ''; |
644
|
|
|
if (!empty($emailTemplate)) { |
645
|
|
|
if (isset($emailTemplate['content_registration_platform.tpl']) && |
646
|
|
|
!empty($emailTemplate['content_registration_platform.tpl']) |
647
|
|
|
) { |
648
|
|
|
$emailBodyTemplate = $mailTemplateManager->parseTemplate( |
649
|
|
|
$emailTemplate['content_registration_platform.tpl'], |
650
|
|
|
$userInfo |
651
|
|
|
); |
652
|
|
|
} |
653
|
|
|
} |
654
|
|
|
|
655
|
|
|
$twoEmail = api_get_configuration_value('send_two_inscription_confirmation_mail'); |
656
|
|
|
if ($twoEmail === true) { |
657
|
|
|
$layoutContent = $tplContent->get_template('mail/new_user_first_email_confirmation.tpl'); |
658
|
|
|
$emailBody = $tplContent->fetch($layoutContent); |
659
|
|
|
|
660
|
|
|
if (!empty($emailTemplate) && |
661
|
|
|
isset($emailTemplate['new_user_first_email_confirmation.tpl']) && |
662
|
|
|
!empty($emailTemplate['new_user_first_email_confirmation.tpl']) |
663
|
|
|
) { |
664
|
|
|
$emailBody = $mailTemplateManager->parseTemplate( |
665
|
|
|
$emailTemplate['new_user_first_email_confirmation.tpl'], |
666
|
|
|
$userInfo |
667
|
|
|
); |
668
|
|
|
} |
669
|
|
|
|
670
|
|
|
api_mail_html( |
671
|
|
|
$recipient_name, |
672
|
|
|
$email, |
673
|
|
|
$emailSubject, |
674
|
|
|
$emailBody, |
675
|
|
|
$sender_name, |
676
|
|
|
$email_admin, |
677
|
|
|
null, |
678
|
|
|
null, |
679
|
|
|
null, |
680
|
|
|
$additionalParameters, |
681
|
|
|
$creatorEmail |
682
|
|
|
); |
683
|
|
|
|
684
|
|
|
$layoutContent = $tplContent->get_template('mail/new_user_second_email_confirmation.tpl'); |
685
|
|
|
$emailBody = $tplContent->fetch($layoutContent); |
686
|
|
|
|
687
|
|
|
if (!empty($emailTemplate) && |
688
|
|
|
isset($emailTemplate['new_user_second_email_confirmation.tpl']) && |
689
|
|
|
!empty($emailTemplate['new_user_second_email_confirmation.tpl']) |
690
|
|
|
) { |
691
|
|
|
$emailBody = $mailTemplateManager->parseTemplate( |
692
|
|
|
$emailTemplate['new_user_second_email_confirmation.tpl'], |
693
|
|
|
$userInfo |
694
|
|
|
); |
695
|
|
|
} |
696
|
|
|
|
697
|
|
|
api_mail_html( |
698
|
|
|
$recipient_name, |
699
|
|
|
$email, |
700
|
|
|
$emailSubject, |
701
|
|
|
$emailBody, |
702
|
|
|
$sender_name, |
703
|
|
|
$email_admin, |
704
|
|
|
null, |
705
|
|
|
null, |
706
|
|
|
null, |
707
|
|
|
$additionalParameters, |
708
|
|
|
$creatorEmail |
709
|
|
|
); |
710
|
|
|
} else { |
711
|
|
|
if (!empty($emailBodyTemplate)) { |
712
|
|
|
$emailBody = $emailBodyTemplate; |
713
|
|
|
} |
714
|
|
|
$sendToInbox = api_get_configuration_value('send_inscription_msg_to_inbox'); |
715
|
|
|
if ($sendToInbox) { |
716
|
|
|
$adminList = self::get_all_administrators(); |
717
|
|
|
$senderId = 1; |
718
|
|
|
if (!empty($adminList)) { |
719
|
|
|
$adminInfo = current($adminList); |
720
|
|
|
$senderId = $adminInfo['user_id']; |
721
|
|
|
} |
722
|
|
|
|
723
|
|
|
MessageManager::send_message_simple( |
724
|
|
|
$userId, |
725
|
|
|
$emailSubject, |
726
|
|
|
$emailBody, |
727
|
|
|
$senderId |
728
|
|
|
); |
729
|
|
|
} else { |
730
|
|
|
api_mail_html( |
731
|
|
|
$recipient_name, |
732
|
|
|
$email, |
733
|
|
|
$emailSubject, |
734
|
|
|
$emailBody, |
735
|
|
|
$sender_name, |
736
|
|
|
$email_admin, |
737
|
|
|
null, |
738
|
|
|
null, |
739
|
|
|
null, |
740
|
|
|
$additionalParameters, |
741
|
|
|
$creatorEmail |
742
|
|
|
); |
743
|
|
|
} |
744
|
|
|
} |
745
|
|
|
|
746
|
|
|
$notification = api_get_configuration_value('send_notification_when_user_added'); |
747
|
|
|
if (!empty($notification) && isset($notification['admins']) && is_array($notification['admins'])) { |
748
|
|
|
foreach ($notification['admins'] as $adminId) { |
749
|
|
|
$emailSubjectToAdmin = get_lang('UserAdded').': '.api_get_person_name($firstName, $lastName); |
750
|
|
|
MessageManager::send_message_simple($adminId, $emailSubjectToAdmin, $emailBody, $userId); |
751
|
|
|
} |
752
|
|
|
} |
753
|
|
|
} |
754
|
|
|
|
755
|
|
|
if ($sendEmailToAllAdmins) { |
756
|
|
|
$adminList = self::get_all_administrators(); |
757
|
|
|
|
758
|
|
|
$tplContent = new Template( |
759
|
|
|
null, |
760
|
|
|
false, |
761
|
|
|
false, |
762
|
|
|
false, |
763
|
|
|
false, |
764
|
|
|
false |
765
|
|
|
); |
766
|
|
|
// variables for the default template |
767
|
|
|
$tplContent->assign('complete_name', stripslashes(api_get_person_name($firstName, $lastName))); |
768
|
|
|
$tplContent->assign('user_added', $user); |
769
|
|
|
$renderer = FormValidator::getDefaultRenderer(); |
770
|
|
|
// Form template |
771
|
|
|
$elementTemplate = ' {label}: {element} <br />'; |
772
|
|
|
$renderer->setElementTemplate($elementTemplate); |
773
|
|
|
/** @var FormValidator $form */ |
774
|
|
|
$form->freeze(null, $elementTemplate); |
775
|
|
|
$form->removeElement('submit'); |
776
|
|
|
$formData = $form->returnForm(); |
777
|
|
|
$url = api_get_path(WEB_CODE_PATH).'admin/user_information.php?user_id='.$user->getId(); |
778
|
|
|
$tplContent->assign('link', Display::url($url, $url)); |
779
|
|
|
$tplContent->assign('form', $formData); |
780
|
|
|
|
781
|
|
|
$layoutContent = $tplContent->get_template('mail/content_registration_platform_to_admin.tpl'); |
782
|
|
|
$emailBody = $tplContent->fetch($layoutContent); |
783
|
|
|
|
784
|
|
|
if (!empty($emailTemplate) && |
785
|
|
|
isset($emailTemplate['content_registration_platform_to_admin.tpl']) && |
786
|
|
|
!empty($emailTemplate['content_registration_platform_to_admin.tpl']) |
787
|
|
|
) { |
788
|
|
|
$emailBody = $mailTemplateManager->parseTemplate( |
789
|
|
|
$emailTemplate['content_registration_platform_to_admin.tpl'], |
790
|
|
|
$userInfo |
791
|
|
|
); |
792
|
|
|
} |
793
|
|
|
|
794
|
|
|
$subject = get_lang('UserAdded'); |
795
|
|
|
foreach ($adminList as $adminId => $data) { |
796
|
|
|
MessageManager::send_message_simple( |
797
|
|
|
$adminId, |
798
|
|
|
$subject, |
799
|
|
|
$emailBody, |
800
|
|
|
$userId |
801
|
|
|
); |
802
|
|
|
} |
803
|
|
|
} |
804
|
|
|
/* ENDS MANAGE EVENT WITH MAIL */ |
805
|
|
|
} |
806
|
|
|
|
807
|
|
|
if (!empty($hook)) { |
808
|
|
|
$hook->setEventData([ |
809
|
|
|
'return' => $userId, |
810
|
|
|
'originalPassword' => $original_password, |
811
|
|
|
]); |
812
|
|
|
$hook->notifyCreateUser(HOOK_EVENT_TYPE_POST); |
813
|
|
|
} |
814
|
|
|
Event::addEvent(LOG_USER_CREATE, LOG_USER_ID, $userId); |
815
|
|
|
} else { |
816
|
|
|
Display::addFlash( |
817
|
|
|
Display::return_message(get_lang('ErrorContactPlatformAdmin')) |
818
|
|
|
); |
819
|
|
|
|
820
|
|
|
return false; |
821
|
|
|
} |
822
|
|
|
|
823
|
|
|
return $return; |
824
|
|
|
} |
825
|
|
|
|
826
|
|
|
/** |
827
|
|
|
* Ensure the CAS-authenticated user exists in the database. |
828
|
|
|
* |
829
|
|
|
* @param $casUser string the CAS user identifier |
830
|
|
|
* |
831
|
|
|
* @throws Exception if more than one user share the same CAS user identifier |
832
|
|
|
* |
833
|
|
|
* @return string|bool the recognised user login name or false if not found |
834
|
|
|
*/ |
835
|
|
|
public static function casUserLoginName($casUser) |
836
|
|
|
{ |
837
|
|
|
$loginName = false; |
838
|
|
|
|
839
|
|
|
// look inside the casUser extra field |
840
|
|
|
if (UserManager::is_extra_field_available('cas_user')) { |
841
|
|
|
$valueModel = new ExtraFieldValue('user'); |
842
|
|
|
$itemList = $valueModel->get_item_id_from_field_variable_and_field_value( |
843
|
|
|
'cas_user', |
844
|
|
|
$casUser, |
845
|
|
|
false, |
846
|
|
|
false, |
847
|
|
|
true |
848
|
|
|
); |
849
|
|
|
if (false !== $itemList) { |
850
|
|
|
// at least one user has $casUser in the 'cas_user' extra field |
851
|
|
|
// we attempt to load each candidate user because there might be deleted ones |
852
|
|
|
// (extra field values of a deleted user might remain) |
853
|
|
|
foreach ($itemList as $item) { |
854
|
|
|
$userId = intval($item['item_id']); |
855
|
|
|
$user = UserManager::getRepository()->find($userId); |
856
|
|
|
if (!is_null($user)) { |
857
|
|
|
if (false === $loginName) { |
858
|
|
|
$loginName = $user->getUsername(); |
859
|
|
|
} else { |
860
|
|
|
throw new Exception(get_lang('MoreThanOneUserMatched')); |
861
|
|
|
} |
862
|
|
|
} |
863
|
|
|
} |
864
|
|
|
} |
865
|
|
|
} |
866
|
|
|
|
867
|
|
|
if (false === $loginName) { |
868
|
|
|
// no matching 'cas_user' extra field value, or no such extra field |
869
|
|
|
// falling back to the old behaviour: $casUser must be the login name |
870
|
|
|
$userId = UserManager::get_user_id_from_username($casUser); |
871
|
|
|
if (false !== $userId) { |
872
|
|
|
$loginName = $casUser; |
873
|
|
|
} |
874
|
|
|
} |
875
|
|
|
|
876
|
|
|
return $loginName; |
877
|
|
|
} |
878
|
|
|
|
879
|
|
|
/** |
880
|
|
|
* Checks the availability of extra field 'cas_user' |
881
|
|
|
* and creates it if missing. |
882
|
|
|
* |
883
|
|
|
* @throws Exception on failure |
884
|
|
|
*/ |
885
|
|
|
public static function ensureCASUserExtraFieldExists() |
886
|
|
|
{ |
887
|
|
|
if (!self::is_extra_field_available('cas_user')) { |
888
|
|
|
$extraField = new ExtraField('user'); |
889
|
|
|
if (false === $extraField->save( |
890
|
|
|
[ |
891
|
|
|
'variable' => 'cas_user', |
892
|
|
|
'field_type' => ExtraField::FIELD_TYPE_TEXT, |
893
|
|
|
'display_text' => get_lang('CAS User Identifier'), |
894
|
|
|
'visible_to_self' => true, |
895
|
|
|
'filter' => true, |
896
|
|
|
] |
897
|
|
|
)) { |
898
|
|
|
throw new Exception(get_lang('FailedToCreateExtraFieldCasUser')); |
899
|
|
|
} |
900
|
|
|
|
901
|
|
|
$rules = api_get_configuration_value('cas_user_map'); |
902
|
|
|
if (!empty($rules) && isset($rules['extra'])) { |
903
|
|
|
foreach ($rules['extra'] as $extra) { |
904
|
|
|
$extraField->save( |
905
|
|
|
[ |
906
|
|
|
'variable' => $extra, |
907
|
|
|
'field_type' => ExtraField::FIELD_TYPE_TEXT, |
908
|
|
|
'display_text' => $extra, |
909
|
|
|
'visible_to_self' => false, |
910
|
|
|
'filter' => false, |
911
|
|
|
] |
912
|
|
|
); |
913
|
|
|
} |
914
|
|
|
} |
915
|
|
|
} |
916
|
|
|
} |
917
|
|
|
|
918
|
|
|
/** |
919
|
|
|
* Create a CAS-authenticated user from scratch, from its CAS user identifier, with temporary default values. |
920
|
|
|
* |
921
|
|
|
* @param string $casUser the CAS user identifier |
922
|
|
|
* |
923
|
|
|
* @throws Exception on error |
924
|
|
|
* |
925
|
|
|
* @return string the login name of the new user |
926
|
|
|
*/ |
927
|
|
|
public static function createCASAuthenticatedUserFromScratch($casUser) |
928
|
|
|
{ |
929
|
|
|
self::ensureCASUserExtraFieldExists(); |
930
|
|
|
|
931
|
|
|
$loginName = 'cas_user_'.$casUser; |
932
|
|
|
$defaultValue = get_lang('EditInProfile'); |
933
|
|
|
$defaultEmailValue = get_lang('EditInProfile'); |
934
|
|
|
require_once __DIR__.'/../../auth/external_login/functions.inc.php'; |
935
|
|
|
if ('true' === api_get_setting('login_is_email')) { |
936
|
|
|
$defaultEmailValue = $casUser; |
937
|
|
|
} |
938
|
|
|
$userId = external_add_user( |
939
|
|
|
[ |
940
|
|
|
'username' => $loginName, |
941
|
|
|
'auth_source' => CAS_AUTH_SOURCE, |
942
|
|
|
'firstname' => $defaultValue, |
943
|
|
|
'lastname' => $defaultValue, |
944
|
|
|
'email' => $defaultEmailValue, |
945
|
|
|
] |
946
|
|
|
); |
947
|
|
|
if (false === $userId) { |
948
|
|
|
throw new Exception(get_lang('FailedUserCreation')); |
949
|
|
|
} |
950
|
|
|
// Not checking function update_extra_field_value return value because not reliable |
951
|
|
|
self::update_extra_field_value($userId, 'cas_user', $casUser); |
952
|
|
|
|
953
|
|
|
return $loginName; |
954
|
|
|
} |
955
|
|
|
|
956
|
|
|
public static function updateCasUser($_user) |
957
|
|
|
{ |
958
|
|
|
$rules = api_get_configuration_value('cas_user_map'); |
959
|
|
|
|
960
|
|
|
if (empty($_user)) { |
961
|
|
|
return false; |
962
|
|
|
} |
963
|
|
|
|
964
|
|
|
if (!empty($rules)) { |
965
|
|
|
$userEntity = api_get_user_entity($_user['id']); |
966
|
|
|
$attributes = phpCAS::getAttributes(); |
967
|
|
|
if (isset($rules['fields'])) { |
968
|
|
|
$isAdmin = false; |
969
|
|
|
foreach ($rules['fields'] as $field => $attributeName) { |
970
|
|
|
if (!isset($attributes[$attributeName])) { |
971
|
|
|
continue; |
972
|
|
|
} |
973
|
|
|
$value = $attributes[$attributeName]; |
974
|
|
|
// Check replace. |
975
|
|
|
if (isset($rules['replace'][$attributeName])) { |
976
|
|
|
$value = $rules['replace'][$attributeName][$value]; |
977
|
|
|
} |
978
|
|
|
|
979
|
|
|
switch ($field) { |
980
|
|
|
case 'email': |
981
|
|
|
$userEntity->setEmail($value); |
982
|
|
|
break; |
983
|
|
|
case 'firstname': |
984
|
|
|
$userEntity->setFirstname($value); |
985
|
|
|
break; |
986
|
|
|
case 'lastname': |
987
|
|
|
$userEntity->setLastname($value); |
988
|
|
|
break; |
989
|
|
|
case 'active': |
990
|
|
|
$userEntity->setActive('false' === $value); |
991
|
|
|
break; |
992
|
|
|
case 'status': |
993
|
|
|
if (PLATFORM_ADMIN === (int) $value) { |
994
|
|
|
$value = COURSEMANAGER; |
995
|
|
|
$isAdmin = true; |
996
|
|
|
} |
997
|
|
|
$userEntity->setStatus($value); |
998
|
|
|
break; |
999
|
|
|
} |
1000
|
|
|
|
1001
|
|
|
Database::getManager()->persist($userEntity); |
1002
|
|
|
Database::getManager()->flush(); |
1003
|
|
|
|
1004
|
|
|
if ($isAdmin) { |
1005
|
|
|
self::addUserAsAdmin($userEntity); |
1006
|
|
|
} |
1007
|
|
|
} |
1008
|
|
|
} |
1009
|
|
|
|
1010
|
|
|
if (isset($rules['extra'])) { |
1011
|
|
|
foreach ($rules['extra'] as $variable) { |
1012
|
|
|
if (isset($attributes[$variable])) { |
1013
|
|
|
self::update_extra_field_value( |
1014
|
|
|
$_user['id'], |
1015
|
|
|
$variable, |
1016
|
|
|
$attributes[$variable] |
1017
|
|
|
); |
1018
|
|
|
} |
1019
|
|
|
} |
1020
|
|
|
} |
1021
|
|
|
} |
1022
|
|
|
} |
1023
|
|
|
|
1024
|
|
|
/** |
1025
|
|
|
* Create a CAS-authenticated user from LDAP, from its CAS user identifier. |
1026
|
|
|
* |
1027
|
|
|
* @param $casUser |
1028
|
|
|
* |
1029
|
|
|
* @throws Exception |
1030
|
|
|
* |
1031
|
|
|
* @return string login name of the new user |
1032
|
|
|
*/ |
1033
|
|
|
public static function createCASAuthenticatedUserFromLDAP($casUser) |
1034
|
|
|
{ |
1035
|
|
|
self::ensureCASUserExtraFieldExists(); |
1036
|
|
|
|
1037
|
|
|
require_once __DIR__.'/../../auth/external_login/ldap.inc.php'; |
1038
|
|
|
$login = extldapCasUserLogin($casUser); |
1039
|
|
|
if (false !== $login) { |
1040
|
|
|
$ldapUser = extldap_authenticate($login, 'nopass', true); |
1041
|
|
|
if (false !== $ldapUser) { |
1042
|
|
|
require_once __DIR__.'/../../auth/external_login/functions.inc.php'; |
1043
|
|
|
$user = extldap_get_chamilo_user($ldapUser); |
1044
|
|
|
$user['username'] = $login; |
1045
|
|
|
$user['auth_source'] = CAS_AUTH_SOURCE; |
1046
|
|
|
$userId = external_add_user($user); |
1047
|
|
|
if (false !== $userId) { |
1048
|
|
|
// Not checking function update_extra_field_value return value because not reliable |
1049
|
|
|
self::update_extra_field_value($userId, 'cas_user', $casUser); |
1050
|
|
|
|
1051
|
|
|
return $login; |
1052
|
|
|
} else { |
1053
|
|
|
throw new Exception('Could not create the new user '.$login); |
1054
|
|
|
} |
1055
|
|
|
} else { |
1056
|
|
|
throw new Exception('Could not load the new user from LDAP using its login '.$login); |
|
|
|
|
1057
|
|
|
} |
1058
|
|
|
} else { |
1059
|
|
|
throw new Exception('Could not find the new user from LDAP using its cas user identifier '.$casUser); |
1060
|
|
|
} |
1061
|
|
|
} |
1062
|
|
|
|
1063
|
|
|
/** |
1064
|
|
|
* updates user record in database from its LDAP record |
1065
|
|
|
* copies relevant LDAP attribute values : firstname, lastname and email. |
1066
|
|
|
* |
1067
|
|
|
* @param $login string the user login name |
1068
|
|
|
* |
1069
|
|
|
* @throws Exception when the user login name is not found in the LDAP or in the database |
1070
|
|
|
*/ |
1071
|
|
|
public static function updateUserFromLDAP($login) |
1072
|
|
|
{ |
1073
|
|
|
require_once __DIR__.'/../../auth/external_login/ldap.inc.php'; |
1074
|
|
|
|
1075
|
|
|
$ldapUser = extldap_authenticate($login, 'nopass', true); |
1076
|
|
|
if (false === $ldapUser) { |
1077
|
|
|
throw new Exception(get_lang('NoSuchUserInLDAP')); |
1078
|
|
|
} |
1079
|
|
|
|
1080
|
|
|
$user = extldap_get_chamilo_user($ldapUser); |
1081
|
|
|
$userInfo = api_get_user_info_from_username($login); |
1082
|
|
|
if (false === $userInfo) { |
1083
|
|
|
throw new Exception(get_lang('NoSuchUserInInternalDatabase')); |
1084
|
|
|
} |
1085
|
|
|
|
1086
|
|
|
$userId = UserManager::update_user( |
1087
|
|
|
$userInfo['user_id'], |
1088
|
|
|
$user["firstname"], |
1089
|
|
|
$user["lastname"], |
1090
|
|
|
$login, |
1091
|
|
|
null, |
1092
|
|
|
$userInfo['auth_source'], |
1093
|
|
|
$user["email"], |
1094
|
|
|
$userInfo['status'], |
1095
|
|
|
$userInfo['official_code'], |
1096
|
|
|
$userInfo['phone'], |
1097
|
|
|
$userInfo['picture_uri'], |
1098
|
|
|
$userInfo['expiration_date'], |
1099
|
|
|
$userInfo['active'], |
1100
|
|
|
$userInfo['creator_id'], |
1101
|
|
|
$userInfo['hr_dept_id'], |
1102
|
|
|
null, |
1103
|
|
|
$userInfo['language'] |
1104
|
|
|
); |
1105
|
|
|
if (false === $userId) { |
1106
|
|
|
throw new Exception(get_lang('CouldNotUpdateUser')); |
1107
|
|
|
} |
1108
|
|
|
} |
1109
|
|
|
|
1110
|
|
|
/** |
1111
|
|
|
* Can user be deleted? This function checks whether there's a course |
1112
|
|
|
* in which the given user is the |
1113
|
|
|
* only course administrator. If that is the case, the user can't be |
1114
|
|
|
* deleted because the course would remain without a course admin. |
1115
|
|
|
* |
1116
|
|
|
* @param int $user_id The user id |
1117
|
|
|
* |
1118
|
|
|
* @return bool true if user can be deleted |
1119
|
|
|
* |
1120
|
|
|
* @assert (null) === false |
1121
|
|
|
* @assert (-1) === false |
1122
|
|
|
* @assert ('abc') === false |
1123
|
|
|
*/ |
1124
|
|
|
public static function canDeleteUser($user_id) |
1125
|
|
|
{ |
1126
|
|
|
$deny = api_get_configuration_value('deny_delete_users'); |
1127
|
|
|
|
1128
|
|
|
if ($deny) { |
1129
|
|
|
return false; |
1130
|
|
|
} |
1131
|
|
|
|
1132
|
|
|
$table_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER); |
1133
|
|
|
$user_id = (int) $user_id; |
1134
|
|
|
|
1135
|
|
|
if (empty($user_id)) { |
1136
|
|
|
return false; |
1137
|
|
|
} |
1138
|
|
|
|
1139
|
|
|
$res = Database::query( |
1140
|
|
|
"SELECT c_id FROM $table_course_user WHERE status = 1 AND user_id = $user_id" |
1141
|
|
|
); |
1142
|
|
|
while ($course = Database::fetch_assoc($res)) { |
1143
|
|
|
$sql = Database::query( |
1144
|
|
|
"SELECT COUNT(id) number FROM $table_course_user WHERE status = 1 AND c_id = {$course['c_id']}" |
1145
|
|
|
); |
1146
|
|
|
$res2 = Database::fetch_assoc($sql); |
1147
|
|
|
|
1148
|
|
|
if ($res2['number'] == 1) { |
1149
|
|
|
return false; |
1150
|
|
|
} |
1151
|
|
|
} |
1152
|
|
|
|
1153
|
|
|
return true; |
1154
|
|
|
} |
1155
|
|
|
|
1156
|
|
|
/** |
1157
|
|
|
* Delete a user from the platform, and all its belongings. This is a |
1158
|
|
|
* very dangerous function that should only be accessible by |
1159
|
|
|
* super-admins. Other roles should only be able to disable a user, |
1160
|
|
|
* which removes access to the platform but doesn't delete anything. |
1161
|
|
|
* |
1162
|
|
|
* @param int The ID of th user to be deleted |
1163
|
|
|
* |
1164
|
|
|
* @throws Exception |
1165
|
|
|
* |
1166
|
|
|
* @return bool true if user is successfully deleted, false otherwise |
1167
|
|
|
* @assert (null) === false |
1168
|
|
|
* @assert ('abc') === false |
1169
|
|
|
*/ |
1170
|
|
|
public static function delete_user($user_id) |
1171
|
|
|
{ |
1172
|
|
|
$user_id = (int) $user_id; |
1173
|
|
|
|
1174
|
|
|
if (empty($user_id)) { |
1175
|
|
|
return false; |
1176
|
|
|
} |
1177
|
|
|
|
1178
|
|
|
if (!self::canDeleteUser($user_id)) { |
1179
|
|
|
return false; |
1180
|
|
|
} |
1181
|
|
|
|
1182
|
|
|
$table_user = Database::get_main_table(TABLE_MAIN_USER); |
1183
|
|
|
$usergroup_rel_user = Database::get_main_table(TABLE_USERGROUP_REL_USER); |
1184
|
|
|
$table_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER); |
1185
|
|
|
$table_course = Database::get_main_table(TABLE_MAIN_COURSE); |
1186
|
|
|
$table_session = Database::get_main_table(TABLE_MAIN_SESSION); |
1187
|
|
|
$table_admin = Database::get_main_table(TABLE_MAIN_ADMIN); |
1188
|
|
|
$table_session_user = Database::get_main_table(TABLE_MAIN_SESSION_USER); |
1189
|
|
|
$table_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER); |
1190
|
|
|
$table_group = Database::get_course_table(TABLE_GROUP_USER); |
1191
|
|
|
$table_work = Database::get_course_table(TABLE_STUDENT_PUBLICATION); |
1192
|
|
|
|
1193
|
|
|
// Unsubscribe the user from all groups in all his courses |
1194
|
|
|
$sql = "SELECT c.id |
1195
|
|
|
FROM $table_course c |
1196
|
|
|
INNER JOIN $table_course_user cu |
1197
|
|
|
ON (c.id = cu.c_id) |
1198
|
|
|
WHERE |
1199
|
|
|
cu.user_id = '".$user_id."' AND |
1200
|
|
|
relation_type<>".COURSE_RELATION_TYPE_RRHH." |
1201
|
|
|
"; |
1202
|
|
|
|
1203
|
|
|
$res = Database::query($sql); |
1204
|
|
|
while ($course = Database::fetch_object($res)) { |
1205
|
|
|
$sql = "DELETE FROM $table_group |
1206
|
|
|
WHERE c_id = {$course->id} AND user_id = $user_id"; |
1207
|
|
|
Database::query($sql); |
1208
|
|
|
} |
1209
|
|
|
|
1210
|
|
|
// Unsubscribe user from usergroup_rel_user |
1211
|
|
|
$sql = "DELETE FROM $usergroup_rel_user WHERE user_id = '".$user_id."'"; |
1212
|
|
|
Database::query($sql); |
1213
|
|
|
|
1214
|
|
|
// Unsubscribe user from all courses |
1215
|
|
|
$sql = "DELETE FROM $table_course_user WHERE user_id = '".$user_id."'"; |
1216
|
|
|
Database::query($sql); |
1217
|
|
|
|
1218
|
|
|
// Unsubscribe user from all courses in sessions |
1219
|
|
|
$sql = "DELETE FROM $table_session_course_user WHERE user_id = '".$user_id."'"; |
1220
|
|
|
Database::query($sql); |
1221
|
|
|
|
1222
|
|
|
// If the user was added as a id_coach then set the current admin as coach see BT# |
1223
|
|
|
$currentUserId = api_get_user_id(); |
1224
|
|
|
$sql = "UPDATE $table_session SET id_coach = $currentUserId |
1225
|
|
|
WHERE id_coach = '".$user_id."'"; |
1226
|
|
|
Database::query($sql); |
1227
|
|
|
|
1228
|
|
|
$sql = "UPDATE $table_session SET session_admin_id = $currentUserId |
1229
|
|
|
WHERE session_admin_id = '".$user_id."'"; |
1230
|
|
|
Database::query($sql); |
1231
|
|
|
|
1232
|
|
|
// Unsubscribe user from all sessions |
1233
|
|
|
$sql = "DELETE FROM $table_session_user |
1234
|
|
|
WHERE user_id = '".$user_id."'"; |
1235
|
|
|
Database::query($sql); |
1236
|
|
|
|
1237
|
|
|
if (api_get_configuration_value('plugin_redirection_enabled')) { |
1238
|
|
|
RedirectionPlugin::deleteUserRedirection($user_id); |
1239
|
|
|
} |
1240
|
|
|
|
1241
|
|
|
$user_info = api_get_user_info($user_id); |
1242
|
|
|
|
1243
|
|
|
try { |
1244
|
|
|
self::deleteUserFiles($user_id); |
1245
|
|
|
} catch (Exception $exception) { |
1246
|
|
|
error_log('Delete user exception: '.$exception->getMessage()); |
1247
|
|
|
} |
1248
|
|
|
|
1249
|
|
|
// Delete the personal course categories |
1250
|
|
|
$course_cat_table = Database::get_main_table(TABLE_USER_COURSE_CATEGORY); |
1251
|
|
|
$sql = "DELETE FROM $course_cat_table WHERE user_id = '".$user_id."'"; |
1252
|
|
|
Database::query($sql); |
1253
|
|
|
|
1254
|
|
|
// Delete user from the admin table |
1255
|
|
|
$sql = "DELETE FROM $table_admin WHERE user_id = '".$user_id."'"; |
1256
|
|
|
Database::query($sql); |
1257
|
|
|
|
1258
|
|
|
// Delete the personal agenda-items from this user |
1259
|
|
|
$agenda_table = Database::get_main_table(TABLE_PERSONAL_AGENDA); |
1260
|
|
|
$sql = "DELETE FROM $agenda_table WHERE user = '".$user_id."'"; |
1261
|
|
|
Database::query($sql); |
1262
|
|
|
|
1263
|
|
|
$gradebook_results_table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_RESULT); |
1264
|
|
|
$sql = 'DELETE FROM '.$gradebook_results_table.' WHERE user_id = '.$user_id; |
1265
|
|
|
Database::query($sql); |
1266
|
|
|
|
1267
|
|
|
$extraFieldValue = new ExtraFieldValue('user'); |
1268
|
|
|
$extraFieldValue->deleteValuesByItem($user_id); |
1269
|
|
|
|
1270
|
|
|
UrlManager::deleteUserFromAllUrls($user_id); |
1271
|
|
|
|
1272
|
|
|
if (api_get_setting('allow_social_tool') === 'true') { |
1273
|
|
|
$userGroup = new UserGroup(); |
1274
|
|
|
//Delete user from portal groups |
1275
|
|
|
$group_list = $userGroup->get_groups_by_user($user_id); |
1276
|
|
|
if (!empty($group_list)) { |
1277
|
|
|
foreach ($group_list as $group_id => $data) { |
1278
|
|
|
$userGroup->delete_user_rel_group($user_id, $group_id); |
1279
|
|
|
} |
1280
|
|
|
} |
1281
|
|
|
|
1282
|
|
|
// Delete user from friend lists |
1283
|
|
|
SocialManager::remove_user_rel_user($user_id, true); |
1284
|
|
|
} |
1285
|
|
|
|
1286
|
|
|
// Removing survey invitation |
1287
|
|
|
SurveyManager::delete_all_survey_invitations_by_user($user_id); |
1288
|
|
|
|
1289
|
|
|
// Delete students works |
1290
|
|
|
$sql = "DELETE FROM $table_work WHERE user_id = $user_id AND c_id <> 0"; |
1291
|
|
|
Database::query($sql); |
1292
|
|
|
|
1293
|
|
|
$sql = "UPDATE c_item_property SET to_user_id = NULL |
1294
|
|
|
WHERE to_user_id = '".$user_id."'"; |
1295
|
|
|
Database::query($sql); |
1296
|
|
|
|
1297
|
|
|
$sql = "UPDATE c_item_property SET insert_user_id = NULL |
1298
|
|
|
WHERE insert_user_id = '".$user_id."'"; |
1299
|
|
|
Database::query($sql); |
1300
|
|
|
|
1301
|
|
|
$sql = "UPDATE c_item_property SET lastedit_user_id = NULL |
1302
|
|
|
WHERE lastedit_user_id = '".$user_id."'"; |
1303
|
|
|
Database::query($sql); |
1304
|
|
|
|
1305
|
|
|
// Skills |
1306
|
|
|
$em = Database::getManager(); |
1307
|
|
|
|
1308
|
|
|
$criteria = ['user' => $user_id]; |
1309
|
|
|
$skills = $em->getRepository('ChamiloCoreBundle:SkillRelUser')->findBy($criteria); |
1310
|
|
|
if ($skills) { |
1311
|
|
|
/** @var SkillRelUser $skill */ |
1312
|
|
|
foreach ($skills as $skill) { |
1313
|
|
|
$comments = $skill->getComments(); |
1314
|
|
|
if ($comments) { |
1315
|
|
|
/** @var SkillRelUserComment $comment */ |
1316
|
|
|
foreach ($comments as $comment) { |
1317
|
|
|
$em->remove($comment); |
1318
|
|
|
} |
1319
|
|
|
} |
1320
|
|
|
$em->remove($skill); |
1321
|
|
|
} |
1322
|
|
|
$em->flush(); |
1323
|
|
|
} |
1324
|
|
|
|
1325
|
|
|
// ExtraFieldSavedSearch |
1326
|
|
|
$criteria = ['user' => $user_id]; |
1327
|
|
|
$searchList = $em->getRepository('ChamiloCoreBundle:ExtraFieldSavedSearch')->findBy($criteria); |
1328
|
|
|
if ($searchList) { |
1329
|
|
|
foreach ($searchList as $search) { |
1330
|
|
|
$em->remove($search); |
1331
|
|
|
} |
1332
|
|
|
$em->flush(); |
1333
|
|
|
} |
1334
|
|
|
|
1335
|
|
|
$connection = Database::getManager()->getConnection(); |
1336
|
|
|
$tableExists = $connection->getSchemaManager()->tablesExist(['plugin_bbb_room']); |
1337
|
|
|
if ($tableExists) { |
1338
|
|
|
// Delete user from database |
1339
|
|
|
$sql = "DELETE FROM plugin_bbb_room WHERE participant_id = $user_id"; |
1340
|
|
|
Database::query($sql); |
1341
|
|
|
} |
1342
|
|
|
|
1343
|
|
|
// Delete user/ticket relationships :( |
1344
|
|
|
$tableExists = $connection->getSchemaManager()->tablesExist(['ticket_ticket']); |
1345
|
|
|
if ($tableExists) { |
1346
|
|
|
TicketManager::deleteUserFromTicketSystem($user_id); |
1347
|
|
|
} |
1348
|
|
|
|
1349
|
|
|
$tableExists = $connection->getSchemaManager()->tablesExist(['c_lp_category_user']); |
1350
|
|
|
if ($tableExists) { |
1351
|
|
|
$sql = "DELETE FROM c_lp_category_user WHERE user_id = $user_id"; |
1352
|
|
|
Database::query($sql); |
1353
|
|
|
} |
1354
|
|
|
|
1355
|
|
|
$app_plugin = new AppPlugin(); |
1356
|
|
|
$app_plugin->performActionsWhenDeletingItem('user', $user_id); |
1357
|
|
|
|
1358
|
|
|
// Delete user from database |
1359
|
|
|
$sql = "DELETE FROM $table_user WHERE id = '".$user_id."'"; |
1360
|
|
|
Database::query($sql); |
1361
|
|
|
|
1362
|
|
|
// Add event to system log |
1363
|
|
|
$user_id_manager = api_get_user_id(); |
1364
|
|
|
|
1365
|
|
|
Event::addEvent( |
1366
|
|
|
LOG_USER_DELETE, |
1367
|
|
|
LOG_USER_ID, |
1368
|
|
|
$user_id, |
1369
|
|
|
api_get_utc_datetime(), |
1370
|
|
|
$user_id_manager |
1371
|
|
|
); |
1372
|
|
|
|
1373
|
|
|
Event::addEvent( |
1374
|
|
|
LOG_USER_DELETE, |
1375
|
|
|
LOG_USER_OBJECT, |
1376
|
|
|
$user_info, |
1377
|
|
|
api_get_utc_datetime(), |
1378
|
|
|
$user_id_manager |
1379
|
|
|
); |
1380
|
|
|
$cacheAvailable = api_get_configuration_value('apc'); |
1381
|
|
|
if ($cacheAvailable === true) { |
1382
|
|
|
$apcVar = api_get_configuration_value('apc_prefix').'userinfo_'.$user_id; |
1383
|
|
|
if (apcu_exists($apcVar)) { |
1384
|
|
|
apcu_delete($apcVar); |
1385
|
|
|
} |
1386
|
|
|
} |
1387
|
|
|
|
1388
|
|
|
return true; |
1389
|
|
|
} |
1390
|
|
|
|
1391
|
|
|
/** |
1392
|
|
|
* Deletes users completely. Can be called either as: |
1393
|
|
|
* - UserManager::delete_users(1, 2, 3); or |
1394
|
|
|
* - UserManager::delete_users(array(1, 2, 3));. |
1395
|
|
|
* |
1396
|
|
|
* @param array|int $ids |
1397
|
|
|
* |
1398
|
|
|
* @return bool True if at least one user was successfuly deleted. False otherwise. |
1399
|
|
|
* |
1400
|
|
|
* @author Laurent Opprecht |
1401
|
|
|
* |
1402
|
|
|
* @uses \UserManager::delete_user() to actually delete each user |
1403
|
|
|
* @assert (null) === false |
1404
|
|
|
* @assert (-1) === false |
1405
|
|
|
* @assert (array(-1)) === false |
1406
|
|
|
*/ |
1407
|
|
|
public static function delete_users($ids = []) |
1408
|
|
|
{ |
1409
|
|
|
$result = false; |
1410
|
|
|
$ids = is_array($ids) ? $ids : func_get_args(); |
1411
|
|
|
if (!is_array($ids) || count($ids) == 0) { |
1412
|
|
|
return false; |
1413
|
|
|
} |
1414
|
|
|
$ids = array_map('intval', $ids); |
1415
|
|
|
foreach ($ids as $id) { |
1416
|
|
|
if (empty($id) || $id < 1) { |
1417
|
|
|
continue; |
1418
|
|
|
} |
1419
|
|
|
$deleted = self::delete_user($id); |
1420
|
|
|
$result = $deleted || $result; |
1421
|
|
|
} |
1422
|
|
|
|
1423
|
|
|
return $result; |
1424
|
|
|
} |
1425
|
|
|
|
1426
|
|
|
/** |
1427
|
|
|
* Disable users. Can be called either as: |
1428
|
|
|
* - UserManager::deactivate_users(1, 2, 3); |
1429
|
|
|
* - UserManager::deactivate_users(array(1, 2, 3));. |
1430
|
|
|
* |
1431
|
|
|
* @param array|int $ids |
1432
|
|
|
* |
1433
|
|
|
* @return bool |
1434
|
|
|
* |
1435
|
|
|
* @author Laurent Opprecht |
1436
|
|
|
* @assert (null) === false |
1437
|
|
|
* @assert (array(-1)) === false |
1438
|
|
|
*/ |
1439
|
|
|
public static function deactivate_users($ids = []) |
1440
|
|
|
{ |
1441
|
|
|
if (empty($ids)) { |
1442
|
|
|
return false; |
1443
|
|
|
} |
1444
|
|
|
|
1445
|
|
|
$table_user = Database::get_main_table(TABLE_MAIN_USER); |
1446
|
|
|
|
1447
|
|
|
$ids = is_array($ids) ? $ids : func_get_args(); |
1448
|
|
|
$ids = array_map('intval', $ids); |
1449
|
|
|
$ids = implode(',', $ids); |
1450
|
|
|
|
1451
|
|
|
$sql = "UPDATE $table_user SET active = 0 WHERE id IN ($ids)"; |
1452
|
|
|
$r = Database::query($sql); |
1453
|
|
|
if ($r !== false) { |
1454
|
|
|
Event::addEvent(LOG_USER_DISABLE, LOG_USER_ID, $ids); |
1455
|
|
|
|
1456
|
|
|
return true; |
1457
|
|
|
} |
1458
|
|
|
|
1459
|
|
|
return false; |
1460
|
|
|
} |
1461
|
|
|
|
1462
|
|
|
/** |
1463
|
|
|
* Enable users. Can be called either as: |
1464
|
|
|
* - UserManager::activate_users(1, 2, 3); |
1465
|
|
|
* - UserManager::activate_users(array(1, 2, 3));. |
1466
|
|
|
* |
1467
|
|
|
* @param array|int IDs of the users to enable |
1468
|
|
|
* |
1469
|
|
|
* @return bool |
1470
|
|
|
* |
1471
|
|
|
* @author Laurent Opprecht |
1472
|
|
|
* @assert (null) === false |
1473
|
|
|
* @assert (array(-1)) === false |
1474
|
|
|
*/ |
1475
|
|
|
public static function activate_users($ids = []) |
1476
|
|
|
{ |
1477
|
|
|
if (empty($ids)) { |
1478
|
|
|
return false; |
1479
|
|
|
} |
1480
|
|
|
|
1481
|
|
|
$table_user = Database::get_main_table(TABLE_MAIN_USER); |
1482
|
|
|
|
1483
|
|
|
$ids = is_array($ids) ? $ids : func_get_args(); |
1484
|
|
|
$ids = array_map('intval', $ids); |
1485
|
|
|
$ids = implode(',', $ids); |
1486
|
|
|
|
1487
|
|
|
$sql = "UPDATE $table_user SET active = 1 WHERE id IN ($ids)"; |
1488
|
|
|
$r = Database::query($sql); |
1489
|
|
|
if ($r !== false) { |
1490
|
|
|
Event::addEvent(LOG_USER_ENABLE, LOG_USER_ID, $ids); |
1491
|
|
|
|
1492
|
|
|
return true; |
1493
|
|
|
} |
1494
|
|
|
|
1495
|
|
|
return false; |
1496
|
|
|
} |
1497
|
|
|
|
1498
|
|
|
/** |
1499
|
|
|
* Update user information with new openid. |
1500
|
|
|
* |
1501
|
|
|
* @param int $user_id |
1502
|
|
|
* @param string $openid |
1503
|
|
|
* |
1504
|
|
|
* @return bool true if the user information was updated |
1505
|
|
|
* @assert (false,'') === false |
1506
|
|
|
* @assert (-1,'') === false |
1507
|
|
|
*/ |
1508
|
|
|
public static function update_openid($user_id, $openid) |
1509
|
|
|
{ |
1510
|
|
|
$table_user = Database::get_main_table(TABLE_MAIN_USER); |
1511
|
|
|
if ($user_id != strval(intval($user_id))) { |
1512
|
|
|
return false; |
1513
|
|
|
} |
1514
|
|
|
if ($user_id === false) { |
1515
|
|
|
return false; |
1516
|
|
|
} |
1517
|
|
|
$sql = "UPDATE $table_user SET |
1518
|
|
|
openid='".Database::escape_string($openid)."'"; |
1519
|
|
|
$sql .= " WHERE id= $user_id"; |
1520
|
|
|
|
1521
|
|
|
if (Database::query($sql) !== false) { |
1522
|
|
|
return true; |
1523
|
|
|
} |
1524
|
|
|
|
1525
|
|
|
return false; |
1526
|
|
|
} |
1527
|
|
|
|
1528
|
|
|
/** |
1529
|
|
|
* Update user information with all the parameters passed to this function. |
1530
|
|
|
* |
1531
|
|
|
* @param int $user_id The ID of the user to be updated |
1532
|
|
|
* @param string $firstname The user's firstname |
1533
|
|
|
* @param string $lastname The user's lastname |
1534
|
|
|
* @param string $username The user's username (login) |
1535
|
|
|
* @param string $password The user's password |
1536
|
|
|
* @param string $auth_source The authentication source (default: "platform") |
1537
|
|
|
* @param string $email The user's e-mail address |
1538
|
|
|
* @param int $status The user's status |
1539
|
|
|
* @param string $official_code The user's official code (usually just an internal institutional code) |
1540
|
|
|
* @param string $phone The user's phone number |
1541
|
|
|
* @param string $picture_uri The user's picture URL (internal to the Chamilo directory) |
1542
|
|
|
* @param string $expiration_date The date at which this user will be automatically disabled |
1543
|
|
|
* @param int $active Whether this account needs to be enabled (1) or disabled (0) |
1544
|
|
|
* @param int $creator_id The user ID of the person who registered this user (optional, defaults to null) |
1545
|
|
|
* @param int $hr_dept_id The department of HR in which the user is registered (optional, defaults to 0) |
1546
|
|
|
* @param array $extra Additional fields to add to this user as extra fields (defaults to null) |
1547
|
|
|
* @param string $language The language to which the user account will be set |
1548
|
|
|
* @param string $encrypt_method The cipher method. This parameter is deprecated. It will use the system's default |
1549
|
|
|
* @param bool $send_email Whether to send an e-mail to the user after the update is complete |
1550
|
|
|
* @param int $reset_password Method used to reset password (0, 1, 2 or 3 - see usage examples for details) |
1551
|
|
|
* @param string $address |
1552
|
|
|
* @param array $emailTemplate |
1553
|
|
|
* |
1554
|
|
|
* @return bool|int False on error, or the user ID if the user information was updated |
1555
|
|
|
* @assert (false, false, false, false, false, false, false, false, false, false, false, false, false) === false |
1556
|
|
|
*/ |
1557
|
|
|
public static function update_user( |
1558
|
|
|
$user_id, |
1559
|
|
|
$firstname, |
1560
|
|
|
$lastname, |
1561
|
|
|
$username, |
1562
|
|
|
$password, |
1563
|
|
|
$auth_source, |
1564
|
|
|
$email, |
1565
|
|
|
$status, |
1566
|
|
|
$official_code, |
1567
|
|
|
$phone, |
1568
|
|
|
$picture_uri, |
1569
|
|
|
$expiration_date, |
1570
|
|
|
$active, |
1571
|
|
|
$creator_id = null, |
1572
|
|
|
$hr_dept_id = 0, |
1573
|
|
|
$extra = null, |
1574
|
|
|
$language = 'english', |
1575
|
|
|
$encrypt_method = '', |
1576
|
|
|
$send_email = false, |
1577
|
|
|
$reset_password = 0, |
1578
|
|
|
$address = null, |
1579
|
|
|
$emailTemplate = [] |
1580
|
|
|
) { |
1581
|
|
|
$hook = HookUpdateUser::create(); |
1582
|
|
|
if (!empty($hook)) { |
1583
|
|
|
$hook->notifyUpdateUser(HOOK_EVENT_TYPE_PRE); |
1584
|
|
|
} |
1585
|
|
|
$original_password = $password; |
1586
|
|
|
$user_id = (int) $user_id; |
1587
|
|
|
$creator_id = (int) $creator_id; |
1588
|
|
|
|
1589
|
|
|
if (empty($user_id)) { |
1590
|
|
|
return false; |
1591
|
|
|
} |
1592
|
|
|
|
1593
|
|
|
$userManager = self::getManager(); |
1594
|
|
|
/** @var User $user */ |
1595
|
|
|
$user = self::getRepository()->find($user_id); |
1596
|
|
|
|
1597
|
|
|
if (empty($user)) { |
1598
|
|
|
return false; |
1599
|
|
|
} |
1600
|
|
|
|
1601
|
|
|
if ($reset_password == 0) { |
1602
|
|
|
$password = null; |
1603
|
|
|
$auth_source = $user->getAuthSource(); |
1604
|
|
|
} elseif ($reset_password == 1) { |
1605
|
|
|
$original_password = $password = api_generate_password(); |
1606
|
|
|
$auth_source = PLATFORM_AUTH_SOURCE; |
1607
|
|
|
} elseif ($reset_password == 2) { |
1608
|
|
|
//$password = $password; |
1609
|
|
|
$auth_source = PLATFORM_AUTH_SOURCE; |
1610
|
|
|
} elseif ($reset_password == 3) { |
1611
|
|
|
//$password = $password; |
1612
|
|
|
//$auth_source = $auth_source; |
1613
|
|
|
} |
1614
|
|
|
|
1615
|
|
|
// Checking the user language |
1616
|
|
|
$languages = api_get_languages(); |
1617
|
|
|
if (!in_array($language, $languages['folder'])) { |
1618
|
|
|
$language = api_get_setting('platformLanguage'); |
1619
|
|
|
} |
1620
|
|
|
|
1621
|
|
|
$change_active = 0; |
1622
|
|
|
$isUserActive = $user->getActive(); |
1623
|
|
|
if ($isUserActive != $active) { |
1624
|
|
|
$change_active = 1; |
1625
|
|
|
} |
1626
|
|
|
|
1627
|
|
|
$originalUsername = $user->getUsername(); |
1628
|
|
|
|
1629
|
|
|
// If username is different from original then check if it exists. |
1630
|
|
|
if ($originalUsername !== $username) { |
1631
|
|
|
$available = self::is_username_available($username); |
1632
|
|
|
if ($available === false) { |
1633
|
|
|
return false; |
1634
|
|
|
} |
1635
|
|
|
} |
1636
|
|
|
|
1637
|
|
|
if (!empty($expiration_date)) { |
1638
|
|
|
$expiration_date = api_get_utc_datetime($expiration_date); |
1639
|
|
|
$expiration_date = new \DateTime( |
1640
|
|
|
$expiration_date, |
1641
|
|
|
new DateTimeZone('UTC') |
1642
|
|
|
); |
1643
|
|
|
} |
1644
|
|
|
|
1645
|
|
|
$user |
1646
|
|
|
->setLastname($lastname) |
1647
|
|
|
->setFirstname($firstname) |
1648
|
|
|
->setUsername($username) |
1649
|
|
|
->setStatus($status) |
1650
|
|
|
->setAuthSource($auth_source) |
1651
|
|
|
->setLanguage($language) |
1652
|
|
|
->setEmail($email) |
1653
|
|
|
->setOfficialCode($official_code) |
1654
|
|
|
->setPhone($phone) |
1655
|
|
|
->setAddress($address) |
1656
|
|
|
->setPictureUri($picture_uri) |
1657
|
|
|
->setExpirationDate($expiration_date) |
1658
|
|
|
->setActive($active) |
1659
|
|
|
->setEnabled($active) |
1660
|
|
|
->setHrDeptId($hr_dept_id) |
1661
|
|
|
; |
1662
|
|
|
|
1663
|
|
|
if (!is_null($password)) { |
1664
|
|
|
$user->setPlainPassword($password); |
1665
|
|
|
Event::addEvent(LOG_USER_PASSWORD_UPDATE, LOG_USER_ID, $user_id); |
1666
|
|
|
$date = api_get_local_time( |
1667
|
|
|
null, |
1668
|
|
|
null, |
1669
|
|
|
null, |
1670
|
|
|
null, |
1671
|
|
|
null, |
1672
|
|
|
null, |
1673
|
|
|
'Y-m-d' |
1674
|
|
|
); |
1675
|
|
|
$extraFieldValue = new ExtraFieldValue('user'); |
1676
|
|
|
$extraFieldValue->save( |
1677
|
|
|
[ |
1678
|
|
|
'item_id' => $user->getId(), |
1679
|
|
|
'variable' => 'password_updated_at', |
1680
|
|
|
'value' => $date, |
1681
|
|
|
] |
1682
|
|
|
); |
1683
|
|
|
} |
1684
|
|
|
|
1685
|
|
|
$userManager->updateUser($user, true); |
1686
|
|
|
Event::addEvent(LOG_USER_UPDATE, LOG_USER_ID, $user_id); |
1687
|
|
|
|
1688
|
|
|
if ($change_active == 1) { |
1689
|
|
|
if ($active == 1) { |
1690
|
|
|
$event_title = LOG_USER_ENABLE; |
1691
|
|
|
} else { |
1692
|
|
|
$event_title = LOG_USER_DISABLE; |
1693
|
|
|
} |
1694
|
|
|
Event::addEvent($event_title, LOG_USER_ID, $user_id); |
1695
|
|
|
} |
1696
|
|
|
|
1697
|
|
|
if (is_array($extra) && count($extra) > 0) { |
1698
|
|
|
$res = true; |
1699
|
|
|
foreach ($extra as $fname => $fvalue) { |
1700
|
|
|
$res = $res && self::update_extra_field_value( |
1701
|
|
|
$user_id, |
1702
|
|
|
$fname, |
1703
|
|
|
$fvalue |
1704
|
|
|
); |
1705
|
|
|
} |
1706
|
|
|
} |
1707
|
|
|
|
1708
|
|
|
if (!empty($email) && $send_email) { |
1709
|
|
|
$recipient_name = api_get_person_name($firstname, $lastname, null, PERSON_NAME_EMAIL_ADDRESS); |
1710
|
|
|
$sender_name = api_get_person_name( |
1711
|
|
|
api_get_setting('administratorName'), |
1712
|
|
|
api_get_setting('administratorSurname'), |
1713
|
|
|
null, |
1714
|
|
|
PERSON_NAME_EMAIL_ADDRESS |
1715
|
|
|
); |
1716
|
|
|
$email_admin = api_get_setting('emailAdministrator'); |
1717
|
|
|
$url = api_get_path(WEB_PATH); |
1718
|
|
|
if (api_is_multiple_url_enabled()) { |
1719
|
|
|
$access_url_id = api_get_current_access_url_id(); |
1720
|
|
|
if ($access_url_id != -1) { |
1721
|
|
|
$url = api_get_access_url($access_url_id); |
1722
|
|
|
$url = $url['url']; |
1723
|
|
|
} |
1724
|
|
|
} |
1725
|
|
|
|
1726
|
|
|
$tplContent = new Template( |
1727
|
|
|
null, |
1728
|
|
|
false, |
1729
|
|
|
false, |
1730
|
|
|
false, |
1731
|
|
|
false, |
1732
|
|
|
false |
1733
|
|
|
); |
1734
|
|
|
$tplContent->assign('complete_name', stripslashes(api_get_person_name($firstname, $lastname))); |
1735
|
|
|
$tplContent->assign('login_name', $username); |
1736
|
|
|
$originalPassword = ''; |
1737
|
|
|
if ($reset_password > 0) { |
1738
|
|
|
$originalPassword = stripslashes($original_password); |
1739
|
|
|
} |
1740
|
|
|
$tplContent->assign('original_password', $originalPassword); |
1741
|
|
|
// variables for the default template |
1742
|
|
|
$tplContent->assign('portal_url', $url); |
1743
|
|
|
// Adding this variable but not used in default template, used for task BT19518 with a customized template |
1744
|
|
|
$tplContent->assign('status_type', $status); |
1745
|
|
|
$creatorInfo = api_get_user_info($creator_id); |
1746
|
|
|
$creatorEmail = isset($creatorInfo['email']) ? $creatorInfo['email'] : ''; |
1747
|
|
|
$tplSubject = new Template( |
1748
|
|
|
null, |
1749
|
|
|
false, |
1750
|
|
|
false, |
1751
|
|
|
false, |
1752
|
|
|
false, |
1753
|
|
|
false |
1754
|
|
|
); |
1755
|
|
|
// the complete_name is not used in the default Chamilo template but used in a specific template -refs BT#21334 |
1756
|
|
|
$tplSubject->assign('complete_name', stripslashes(api_get_person_name($firstName, $lastName))); |
|
|
|
|
1757
|
|
|
$layoutSubject = $tplSubject->get_template('mail/subject_user_edit.tpl'); |
1758
|
|
|
$emailSubject = $tplSubject->fetch($layoutSubject); |
1759
|
|
|
|
1760
|
|
|
if (!is_null($password) && api_get_configuration_value('send_two_inscription_confirmation_mail')) { |
1761
|
|
|
// The user has a new password *and* we need to tell him so, |
1762
|
|
|
// but the configuration is set to send 2 separate e-mails |
1763
|
|
|
// (one for username, one for password) when sending pass |
1764
|
|
|
$layoutContent = $tplContent->get_template('mail/new_user_first_email_confirmation.tpl'); |
1765
|
|
|
$emailBody = $tplContent->fetch($layoutContent); |
1766
|
|
|
$mailTemplateManager = new MailTemplateManager(); |
1767
|
|
|
if (!empty($emailTemplate) && |
1768
|
|
|
isset($emailTemplate['new_user_first_email_confirmation.tpl']) && |
1769
|
|
|
!empty($emailTemplate['new_user_first_email_confirmation.tpl']) |
1770
|
|
|
) { |
1771
|
|
|
$userInfo = api_get_user_info($user_id); |
1772
|
|
|
$emailBody = $mailTemplateManager->parseTemplate( |
1773
|
|
|
$emailTemplate['new_user_first_email_confirmation.tpl'], |
1774
|
|
|
$userInfo |
1775
|
|
|
); |
1776
|
|
|
} |
1777
|
|
|
|
1778
|
|
|
api_mail_html( |
1779
|
|
|
$recipient_name, |
1780
|
|
|
$email, |
1781
|
|
|
$emailSubject, |
1782
|
|
|
$emailBody, |
1783
|
|
|
$sender_name, |
1784
|
|
|
$email_admin, |
1785
|
|
|
null, |
1786
|
|
|
null, |
1787
|
|
|
null, |
1788
|
|
|
null, |
1789
|
|
|
$creatorEmail |
1790
|
|
|
); |
1791
|
|
|
|
1792
|
|
|
$layoutContent = $tplContent->get_template('mail/new_user_second_email_confirmation.tpl'); |
1793
|
|
|
$emailBody = $tplContent->fetch($layoutContent); |
1794
|
|
|
$mailTemplateManager = new MailTemplateManager(); |
1795
|
|
|
if (!empty($emailTemplate) && |
1796
|
|
|
isset($emailTemplate['new_user_second_email_confirmation.tpl']) && |
1797
|
|
|
!empty($emailTemplate['new_user_second_email_confirmation.tpl']) |
1798
|
|
|
) { |
1799
|
|
|
$userInfo = api_get_user_info($user_id); |
1800
|
|
|
$emailBody = $mailTemplateManager->parseTemplate( |
1801
|
|
|
$emailTemplate['new_user_second_email_confirmation.tpl'], |
1802
|
|
|
$userInfo |
1803
|
|
|
); |
1804
|
|
|
} |
1805
|
|
|
|
1806
|
|
|
api_mail_html( |
1807
|
|
|
$recipient_name, |
1808
|
|
|
$email, |
1809
|
|
|
$emailSubject, |
1810
|
|
|
$emailBody, |
1811
|
|
|
$sender_name, |
1812
|
|
|
$email_admin, |
1813
|
|
|
null, |
1814
|
|
|
null, |
1815
|
|
|
null, |
1816
|
|
|
null, |
1817
|
|
|
$creatorEmail |
1818
|
|
|
); |
1819
|
|
|
} else { |
1820
|
|
|
$layoutContent = $tplContent->get_template('mail/user_edit_content.tpl'); |
1821
|
|
|
$emailBody = $tplContent->fetch($layoutContent); |
1822
|
|
|
$mailTemplateManager = new MailTemplateManager(); |
1823
|
|
|
if (!empty($emailTemplate) && |
1824
|
|
|
isset($emailTemplate['user_edit_content.tpl']) && |
1825
|
|
|
!empty($emailTemplate['user_edit_content.tpl']) |
1826
|
|
|
) { |
1827
|
|
|
$userInfo = api_get_user_info($user_id); |
1828
|
|
|
$emailBody = $mailTemplateManager->parseTemplate( |
1829
|
|
|
$emailTemplate['user_edit_content.tpl'], |
1830
|
|
|
$userInfo |
1831
|
|
|
); |
1832
|
|
|
} |
1833
|
|
|
|
1834
|
|
|
api_mail_html( |
1835
|
|
|
$recipient_name, |
1836
|
|
|
$email, |
1837
|
|
|
$emailSubject, |
1838
|
|
|
$emailBody, |
1839
|
|
|
$sender_name, |
1840
|
|
|
$email_admin, |
1841
|
|
|
null, |
1842
|
|
|
null, |
1843
|
|
|
null, |
1844
|
|
|
null, |
1845
|
|
|
$creatorEmail |
1846
|
|
|
); |
1847
|
|
|
} |
1848
|
|
|
} |
1849
|
|
|
|
1850
|
|
|
if (!empty($hook)) { |
1851
|
|
|
$hook->setEventData(['user' => $user]); |
1852
|
|
|
$hook->notifyUpdateUser(HOOK_EVENT_TYPE_POST); |
1853
|
|
|
} |
1854
|
|
|
|
1855
|
|
|
$cacheAvailable = api_get_configuration_value('apc'); |
1856
|
|
|
if ($cacheAvailable === true) { |
1857
|
|
|
$apcVar = api_get_configuration_value('apc_prefix').'userinfo_'.$user_id; |
1858
|
|
|
if (apcu_exists($apcVar)) { |
1859
|
|
|
apcu_delete($apcVar); |
1860
|
|
|
} |
1861
|
|
|
} |
1862
|
|
|
|
1863
|
|
|
return $user->getId(); |
1864
|
|
|
} |
1865
|
|
|
|
1866
|
|
|
/** |
1867
|
|
|
* Disables a user. |
1868
|
|
|
* |
1869
|
|
|
* @param int User id |
1870
|
|
|
* |
1871
|
|
|
* @return bool |
1872
|
|
|
* |
1873
|
|
|
* @uses \UserManager::change_active_state() to actually disable the user |
1874
|
|
|
* @assert (0) === false |
1875
|
|
|
*/ |
1876
|
|
|
public static function disable($user_id) |
1877
|
|
|
{ |
1878
|
|
|
if (empty($user_id)) { |
1879
|
|
|
return false; |
1880
|
|
|
} |
1881
|
|
|
self::change_active_state($user_id, 0); |
1882
|
|
|
|
1883
|
|
|
return true; |
1884
|
|
|
} |
1885
|
|
|
|
1886
|
|
|
/** |
1887
|
|
|
* Enable a user. |
1888
|
|
|
* |
1889
|
|
|
* @param int User id |
1890
|
|
|
* |
1891
|
|
|
* @return bool |
1892
|
|
|
* |
1893
|
|
|
* @uses \UserManager::change_active_state() to actually disable the user |
1894
|
|
|
* @assert (0) === false |
1895
|
|
|
*/ |
1896
|
|
|
public static function enable($user_id) |
1897
|
|
|
{ |
1898
|
|
|
if (empty($user_id)) { |
1899
|
|
|
return false; |
1900
|
|
|
} |
1901
|
|
|
self::change_active_state($user_id, 1); |
1902
|
|
|
|
1903
|
|
|
return true; |
1904
|
|
|
} |
1905
|
|
|
|
1906
|
|
|
/** |
1907
|
|
|
* Returns the user's id based on the original id and field name in |
1908
|
|
|
* the extra fields. Returns 0 if no user was found. This function is |
1909
|
|
|
* mostly useful in the context of a web services-based sinchronization. |
1910
|
|
|
* |
1911
|
|
|
* @param string Original user id |
1912
|
|
|
* @param string Original field name |
1913
|
|
|
* |
1914
|
|
|
* @return int User id |
1915
|
|
|
* @assert ('0','---') === 0 |
1916
|
|
|
*/ |
1917
|
|
|
public static function get_user_id_from_original_id( |
1918
|
|
|
$original_user_id_value, |
1919
|
|
|
$original_user_id_name |
1920
|
|
|
) { |
1921
|
|
|
$t_uf = Database::get_main_table(TABLE_EXTRA_FIELD); |
1922
|
|
|
$t_ufv = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES); |
1923
|
|
|
$extraFieldType = EntityExtraField::USER_FIELD_TYPE; |
1924
|
|
|
|
1925
|
|
|
$original_user_id_name = Database::escape_string($original_user_id_name); |
1926
|
|
|
$original_user_id_value = Database::escape_string($original_user_id_value); |
1927
|
|
|
|
1928
|
|
|
$sql = "SELECT item_id as user_id |
1929
|
|
|
FROM $t_uf uf |
1930
|
|
|
INNER JOIN $t_ufv ufv |
1931
|
|
|
ON ufv.field_id = uf.id |
1932
|
|
|
WHERE |
1933
|
|
|
variable = '$original_user_id_name' AND |
1934
|
|
|
value = '$original_user_id_value' AND |
1935
|
|
|
extra_field_type = $extraFieldType |
1936
|
|
|
"; |
1937
|
|
|
$res = Database::query($sql); |
1938
|
|
|
$row = Database::fetch_object($res); |
1939
|
|
|
if ($row) { |
1940
|
|
|
return $row->user_id; |
1941
|
|
|
} |
1942
|
|
|
|
1943
|
|
|
return 0; |
1944
|
|
|
} |
1945
|
|
|
|
1946
|
|
|
/** |
1947
|
|
|
* Check if a username is available. |
1948
|
|
|
* |
1949
|
|
|
* @param string $username the wanted username |
1950
|
|
|
* |
1951
|
|
|
* @return bool true if the wanted username is available |
1952
|
|
|
* @assert ('') === false |
1953
|
|
|
* @assert ('xyzxyzxyz') === true |
1954
|
|
|
*/ |
1955
|
|
|
public static function is_username_available($username) |
1956
|
|
|
{ |
1957
|
|
|
if (empty($username)) { |
1958
|
|
|
return false; |
1959
|
|
|
} |
1960
|
|
|
$table_user = Database::get_main_table(TABLE_MAIN_USER); |
1961
|
|
|
$sql = "SELECT username FROM $table_user |
1962
|
|
|
WHERE username = '".Database::escape_string($username)."'"; |
1963
|
|
|
$res = Database::query($sql); |
1964
|
|
|
|
1965
|
|
|
return Database::num_rows($res) == 0; |
1966
|
|
|
} |
1967
|
|
|
|
1968
|
|
|
/** |
1969
|
|
|
* Creates a username using person's names, i.e. creates jmontoya from Julio Montoya. |
1970
|
|
|
* |
1971
|
|
|
* @param string $firstname the first name of the user |
1972
|
|
|
* @param string $lastname the last name of the user |
1973
|
|
|
* |
1974
|
|
|
* @return string suggests a username that contains only ASCII-letters and digits, |
1975
|
|
|
* without check for uniqueness within the system |
1976
|
|
|
* |
1977
|
|
|
* @author Julio Montoya Armas |
1978
|
|
|
* @author Ivan Tcholakov, 2009 - rework about internationalization. |
1979
|
|
|
* @assert ('','') === false |
1980
|
|
|
* @assert ('a','b') === 'ab' |
1981
|
|
|
*/ |
1982
|
|
|
public static function create_username($firstname, $lastname) |
1983
|
|
|
{ |
1984
|
|
|
if (empty($firstname) && empty($lastname)) { |
1985
|
|
|
return false; |
1986
|
|
|
} |
1987
|
|
|
|
1988
|
|
|
// The first letter only. |
1989
|
|
|
$firstname = api_substr( |
1990
|
|
|
preg_replace(USERNAME_PURIFIER, '', $firstname), |
1991
|
|
|
0, |
1992
|
|
|
1 |
1993
|
|
|
); |
1994
|
|
|
//Looking for a space in the lastname |
1995
|
|
|
$pos = api_strpos($lastname, ' '); |
1996
|
|
|
if ($pos !== false) { |
1997
|
|
|
$lastname = api_substr($lastname, 0, $pos); |
1998
|
|
|
} |
1999
|
|
|
|
2000
|
|
|
$lastname = preg_replace(USERNAME_PURIFIER, '', $lastname); |
2001
|
|
|
$username = $firstname.$lastname; |
2002
|
|
|
if (empty($username)) { |
2003
|
|
|
$username = 'user'; |
2004
|
|
|
} |
2005
|
|
|
|
2006
|
|
|
$username = URLify::transliterate($username); |
2007
|
|
|
|
2008
|
|
|
return strtolower(substr($username, 0, USERNAME_MAX_LENGTH - 3)); |
2009
|
|
|
} |
2010
|
|
|
|
2011
|
|
|
/** |
2012
|
|
|
* Creates a unique username, using: |
2013
|
|
|
* 1. the first name and the last name of a user; |
2014
|
|
|
* 2. an already created username but not checked for uniqueness yet. |
2015
|
|
|
* |
2016
|
|
|
* @param string $firstname The first name of a given user. If the second parameter $lastname is NULL, then this |
2017
|
|
|
* parameter is treated as username which is to be checked f |
2018
|
|
|
* or uniqueness and to be modified when it is necessary. |
2019
|
|
|
* @param string $lastname the last name of the user |
2020
|
|
|
* |
2021
|
|
|
* @return string Returns a username that contains only ASCII-letters and digits and that is unique in the system. |
2022
|
|
|
* Note: When the method is called several times with same parameters, |
2023
|
|
|
* its results look like the following sequence: ivan, ivan2, ivan3, ivan4, ... |
2024
|
|
|
* |
2025
|
|
|
* @author Ivan Tcholakov, 2009 |
2026
|
|
|
*/ |
2027
|
|
|
public static function create_unique_username($firstname, $lastname = null) |
2028
|
|
|
{ |
2029
|
|
|
if (is_null($lastname)) { |
2030
|
|
|
// In this case the actual input parameter $firstname should contain ASCII-letters and digits only. |
2031
|
|
|
// For making this method tolerant of mistakes, |
2032
|
|
|
// let us transliterate and purify the suggested input username anyway. |
2033
|
|
|
// So, instead of the sentence $username = $firstname; we place the following: |
2034
|
|
|
$username = strtolower(preg_replace(USERNAME_PURIFIER, '', $firstname)); |
2035
|
|
|
} else { |
2036
|
|
|
$username = self::create_username($firstname, $lastname); |
2037
|
|
|
} |
2038
|
|
|
if (!self::is_username_available($username)) { |
2039
|
|
|
$i = 2; |
2040
|
|
|
$temp_username = substr($username, 0, USERNAME_MAX_LENGTH - strlen((string) $i)).$i; |
2041
|
|
|
while (!self::is_username_available($temp_username)) { |
2042
|
|
|
$i++; |
2043
|
|
|
$temp_username = substr($username, 0, USERNAME_MAX_LENGTH - strlen((string) $i)).$i; |
2044
|
|
|
} |
2045
|
|
|
$username = $temp_username; |
2046
|
|
|
} |
2047
|
|
|
|
2048
|
|
|
$username = URLify::transliterate($username); |
2049
|
|
|
|
2050
|
|
|
return $username; |
2051
|
|
|
} |
2052
|
|
|
|
2053
|
|
|
/** |
2054
|
|
|
* Modifies a given username accordingly to the specification for valid characters and length. |
2055
|
|
|
* |
2056
|
|
|
* @param $username string The input username |
2057
|
|
|
* @param bool $strict (optional) When this flag is TRUE, the result is guaranteed for full compliance, |
2058
|
|
|
* otherwise compliance may be partial. The default value is FALSE. |
2059
|
|
|
* |
2060
|
|
|
* @return string the resulting purified username |
2061
|
|
|
*/ |
2062
|
|
|
public static function purify_username($username, $strict = false) |
2063
|
|
|
{ |
2064
|
|
|
if ($strict) { |
2065
|
|
|
// 1. Conversion of unacceptable letters (latinian letters with accents for example) |
2066
|
|
|
// into ASCII letters in order they not to be totally removed. |
2067
|
|
|
// 2. Applying the strict purifier. |
2068
|
|
|
// 3. Length limitation. |
2069
|
|
|
if ('true' === api_get_setting('login_is_email')) { |
2070
|
|
|
$return = substr(preg_replace(USERNAME_PURIFIER_MAIL, '', $username), 0, USERNAME_MAX_LENGTH); |
2071
|
|
|
} else { |
2072
|
|
|
$return = substr(preg_replace(USERNAME_PURIFIER, '', $username), 0, USERNAME_MAX_LENGTH); |
2073
|
|
|
} |
2074
|
|
|
|
2075
|
|
|
return URLify::transliterate($return); |
2076
|
|
|
} |
2077
|
|
|
|
2078
|
|
|
// 1. Applying the shallow purifier. |
2079
|
|
|
// 2. Length limitation. |
2080
|
|
|
return substr( |
2081
|
|
|
preg_replace(USERNAME_PURIFIER_SHALLOW, '', $username), |
2082
|
|
|
0, |
2083
|
|
|
USERNAME_MAX_LENGTH |
2084
|
|
|
); |
2085
|
|
|
} |
2086
|
|
|
|
2087
|
|
|
/** |
2088
|
|
|
* Checks whether the user id exists in the database. |
2089
|
|
|
* |
2090
|
|
|
* @param int $userId User id |
2091
|
|
|
* |
2092
|
|
|
* @return bool True if user id was found, false otherwise |
2093
|
|
|
*/ |
2094
|
|
|
public static function is_user_id_valid($userId) |
2095
|
|
|
{ |
2096
|
|
|
$resultData = Database::select( |
2097
|
|
|
'COUNT(1) AS count', |
2098
|
|
|
Database::get_main_table(TABLE_MAIN_USER), |
2099
|
|
|
[ |
2100
|
|
|
'where' => ['id = ?' => (int) $userId], |
2101
|
|
|
], |
2102
|
|
|
'first' |
2103
|
|
|
); |
2104
|
|
|
|
2105
|
|
|
if ($resultData === false) { |
2106
|
|
|
return false; |
2107
|
|
|
} |
2108
|
|
|
|
2109
|
|
|
return $resultData['count'] > 0; |
2110
|
|
|
} |
2111
|
|
|
|
2112
|
|
|
/** |
2113
|
|
|
* Checks whether a given username matches to the specification strictly. |
2114
|
|
|
* The empty username is assumed here as invalid. |
2115
|
|
|
* Mostly this function is to be used in the user interface built-in validation routines |
2116
|
|
|
* for providing feedback while usernames are enterd manually. |
2117
|
|
|
* |
2118
|
|
|
* @param string $username the input username |
2119
|
|
|
* |
2120
|
|
|
* @return bool returns TRUE if the username is valid, FALSE otherwise |
2121
|
|
|
*/ |
2122
|
|
|
public static function is_username_valid($username) |
2123
|
|
|
{ |
2124
|
|
|
return !empty($username) && $username == self::purify_username($username, true); |
2125
|
|
|
} |
2126
|
|
|
|
2127
|
|
|
/** |
2128
|
|
|
* Checks whether a username is empty. If the username contains whitespace characters, |
2129
|
|
|
* such as spaces, tabulators, newlines, etc., |
2130
|
|
|
* it is assumed as empty too. This function is safe for validation unpurified data (during importing). |
2131
|
|
|
* |
2132
|
|
|
* @param string $username the given username |
2133
|
|
|
* |
2134
|
|
|
* @return bool returns TRUE if length of the username exceeds the limit, FALSE otherwise |
2135
|
|
|
*/ |
2136
|
|
|
public static function is_username_empty($username) |
2137
|
|
|
{ |
2138
|
|
|
return strlen(self::purify_username($username, false)) == 0; |
2139
|
|
|
} |
2140
|
|
|
|
2141
|
|
|
/** |
2142
|
|
|
* Checks whether a username is too long or not. |
2143
|
|
|
* |
2144
|
|
|
* @param string $username the given username, it should contain only ASCII-letters and digits |
2145
|
|
|
* |
2146
|
|
|
* @return bool returns TRUE if length of the username exceeds the limit, FALSE otherwise |
2147
|
|
|
*/ |
2148
|
|
|
public static function is_username_too_long($username) |
2149
|
|
|
{ |
2150
|
|
|
return strlen($username) > USERNAME_MAX_LENGTH; |
2151
|
|
|
} |
2152
|
|
|
|
2153
|
|
|
/** |
2154
|
|
|
* Get the users by ID. |
2155
|
|
|
* |
2156
|
|
|
* @param array $ids student ids |
2157
|
|
|
* @param string $active |
2158
|
|
|
* @param string $order |
2159
|
|
|
* @param string $limit |
2160
|
|
|
* |
2161
|
|
|
* @return array $result student information |
2162
|
|
|
*/ |
2163
|
|
|
public static function get_user_list_by_ids($ids = [], $active = null, $order = null, $limit = null) |
2164
|
|
|
{ |
2165
|
|
|
if (empty($ids)) { |
2166
|
|
|
return []; |
2167
|
|
|
} |
2168
|
|
|
|
2169
|
|
|
$ids = is_array($ids) ? $ids : [$ids]; |
2170
|
|
|
$ids = array_map('intval', $ids); |
2171
|
|
|
$ids = implode(',', $ids); |
2172
|
|
|
|
2173
|
|
|
$tbl_user = Database::get_main_table(TABLE_MAIN_USER); |
2174
|
|
|
$sql = "SELECT * FROM $tbl_user WHERE id IN ($ids)"; |
2175
|
|
|
if (!is_null($active)) { |
2176
|
|
|
$sql .= ' AND active='.($active ? '1' : '0'); |
2177
|
|
|
} |
2178
|
|
|
|
2179
|
|
|
if (!is_null($order)) { |
2180
|
|
|
$order = Database::escape_string($order); |
2181
|
|
|
$sql .= ' ORDER BY '.$order; |
2182
|
|
|
} |
2183
|
|
|
|
2184
|
|
|
if (!is_null($limit)) { |
2185
|
|
|
$limit = Database::escape_string($limit); |
2186
|
|
|
$sql .= ' LIMIT '.$limit; |
2187
|
|
|
} |
2188
|
|
|
|
2189
|
|
|
$rs = Database::query($sql); |
2190
|
|
|
$result = []; |
2191
|
|
|
while ($row = Database::fetch_array($rs)) { |
2192
|
|
|
$result[] = $row; |
2193
|
|
|
} |
2194
|
|
|
|
2195
|
|
|
return $result; |
2196
|
|
|
} |
2197
|
|
|
|
2198
|
|
|
/** |
2199
|
|
|
* Get a list of users of which the given conditions match with an = 'cond'. |
2200
|
|
|
* |
2201
|
|
|
* @param array $conditions a list of condition (example : status=>STUDENT) |
2202
|
|
|
* @param array $order_by a list of fields on which sort |
2203
|
|
|
* |
2204
|
|
|
* @return array an array with all users of the platform |
2205
|
|
|
* |
2206
|
|
|
* @todo security filter order by |
2207
|
|
|
*/ |
2208
|
|
|
public static function get_user_list( |
2209
|
|
|
$conditions = [], |
2210
|
|
|
$order_by = [], |
2211
|
|
|
$limit_from = false, |
2212
|
|
|
$limit_to = false, |
2213
|
|
|
$idCampus = null, |
2214
|
|
|
$keyword = null, |
2215
|
|
|
$lastConnectionDate = null, |
2216
|
|
|
$getCount = false, |
2217
|
|
|
$filterUsers = null |
2218
|
|
|
) { |
2219
|
|
|
$user_table = Database::get_main_table(TABLE_MAIN_USER); |
2220
|
|
|
$userUrlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER); |
2221
|
|
|
$return_array = []; |
2222
|
|
|
|
2223
|
|
|
if ($getCount) { |
2224
|
|
|
$sql = "SELECT count(user.id) as nbUsers FROM $user_table user "; |
2225
|
|
|
} else { |
2226
|
|
|
$sql = "SELECT user.* FROM $user_table user "; |
2227
|
|
|
} |
2228
|
|
|
|
2229
|
|
|
if (api_is_multiple_url_enabled()) { |
2230
|
|
|
if ($idCampus) { |
2231
|
|
|
$urlId = $idCampus; |
2232
|
|
|
} else { |
2233
|
|
|
$urlId = api_get_current_access_url_id(); |
2234
|
|
|
} |
2235
|
|
|
$sql .= " INNER JOIN $userUrlTable url_user |
2236
|
|
|
ON (user.user_id = url_user.user_id) |
2237
|
|
|
WHERE url_user.access_url_id = $urlId"; |
2238
|
|
|
} else { |
2239
|
|
|
$sql .= " WHERE 1=1 "; |
2240
|
|
|
} |
2241
|
|
|
|
2242
|
|
|
if (!empty($keyword)) { |
2243
|
|
|
$keyword = trim(Database::escape_string($keyword)); |
2244
|
|
|
$keywordParts = array_filter(explode(' ', $keyword)); |
2245
|
|
|
$extraKeyword = ''; |
2246
|
|
|
if (!empty($keywordParts)) { |
2247
|
|
|
$keywordPartsFixed = Database::escape_string(implode('%', $keywordParts)); |
2248
|
|
|
if (!empty($keywordPartsFixed)) { |
2249
|
|
|
$extraKeyword .= " OR |
2250
|
|
|
CONCAT(user.firstname, ' ', user.lastname) LIKE '%$keywordPartsFixed%' OR |
2251
|
|
|
CONCAT(user.lastname, ' ', user.firstname) LIKE '%$keywordPartsFixed%' "; |
2252
|
|
|
} |
2253
|
|
|
} |
2254
|
|
|
|
2255
|
|
|
$sql .= " AND ( |
2256
|
|
|
user.username LIKE '%$keyword%' OR |
2257
|
|
|
user.firstname LIKE '%$keyword%' OR |
2258
|
|
|
user.lastname LIKE '%$keyword%' OR |
2259
|
|
|
user.official_code LIKE '%$keyword%' OR |
2260
|
|
|
user.email LIKE '%$keyword%' OR |
2261
|
|
|
CONCAT(user.firstname, ' ', user.lastname) LIKE '%$keyword%' OR |
2262
|
|
|
CONCAT(user.lastname, ' ', user.firstname) LIKE '%$keyword%' |
2263
|
|
|
$extraKeyword |
2264
|
|
|
)"; |
2265
|
|
|
} |
2266
|
|
|
|
2267
|
|
|
if (!empty($lastConnectionDate)) { |
2268
|
|
|
$lastConnectionDate = Database::escape_string($lastConnectionDate); |
2269
|
|
|
$sql .= " AND user.last_login <= '$lastConnectionDate' "; |
2270
|
|
|
} |
2271
|
|
|
|
2272
|
|
|
if (count($conditions) > 0) { |
2273
|
|
|
foreach ($conditions as $field => $value) { |
2274
|
|
|
$field = Database::escape_string($field); |
2275
|
|
|
$value = Database::escape_string($value); |
2276
|
|
|
$sql .= " AND $field = '$value'"; |
2277
|
|
|
} |
2278
|
|
|
} |
2279
|
|
|
|
2280
|
|
|
if (!empty($filterUsers)) { |
2281
|
|
|
$sql .= " AND user.id IN(".implode(',', $filterUsers).")"; |
2282
|
|
|
} |
2283
|
|
|
|
2284
|
|
|
if (count($order_by) > 0) { |
2285
|
|
|
$sql .= ' ORDER BY '.Database::escape_string(implode(',', $order_by)); |
2286
|
|
|
} |
2287
|
|
|
|
2288
|
|
|
if (is_numeric($limit_from) && is_numeric($limit_from)) { |
2289
|
|
|
$limit_from = (int) $limit_from; |
2290
|
|
|
$limit_to = (int) $limit_to; |
2291
|
|
|
$sql .= " LIMIT $limit_from, $limit_to"; |
2292
|
|
|
} |
2293
|
|
|
$sql_result = Database::query($sql); |
2294
|
|
|
|
2295
|
|
|
if ($getCount) { |
2296
|
|
|
$result = Database::fetch_array($sql_result); |
2297
|
|
|
|
2298
|
|
|
return $result['nbUsers']; |
2299
|
|
|
} |
2300
|
|
|
|
2301
|
|
|
while ($result = Database::fetch_array($sql_result)) { |
2302
|
|
|
$result['complete_name'] = api_get_person_name($result['firstname'], $result['lastname']); |
2303
|
|
|
$return_array[] = $result; |
2304
|
|
|
} |
2305
|
|
|
|
2306
|
|
|
return $return_array; |
2307
|
|
|
} |
2308
|
|
|
|
2309
|
|
|
public static function getUserListExtraConditions( |
2310
|
|
|
$conditions = [], |
2311
|
|
|
$order_by = [], |
2312
|
|
|
$limit_from = false, |
2313
|
|
|
$limit_to = false, |
2314
|
|
|
$idCampus = null, |
2315
|
|
|
$extraConditions = '', |
2316
|
|
|
$getCount = false |
2317
|
|
|
) { |
2318
|
|
|
$user_table = Database::get_main_table(TABLE_MAIN_USER); |
2319
|
|
|
$userUrlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER); |
2320
|
|
|
$return_array = []; |
2321
|
|
|
$sql = "SELECT user.* FROM $user_table user "; |
2322
|
|
|
|
2323
|
|
|
if ($getCount) { |
2324
|
|
|
$sql = "SELECT count(user.id) count FROM $user_table user "; |
2325
|
|
|
} |
2326
|
|
|
|
2327
|
|
|
if (api_is_multiple_url_enabled()) { |
2328
|
|
|
if ($idCampus) { |
2329
|
|
|
$urlId = $idCampus; |
2330
|
|
|
} else { |
2331
|
|
|
$urlId = api_get_current_access_url_id(); |
2332
|
|
|
} |
2333
|
|
|
$sql .= " INNER JOIN $userUrlTable url_user |
2334
|
|
|
ON (user.user_id = url_user.user_id) |
2335
|
|
|
WHERE url_user.access_url_id = $urlId"; |
2336
|
|
|
} else { |
2337
|
|
|
$sql .= " WHERE 1=1 "; |
2338
|
|
|
} |
2339
|
|
|
|
2340
|
|
|
$sql .= " AND status <> ".ANONYMOUS." "; |
2341
|
|
|
|
2342
|
|
|
if (count($conditions) > 0) { |
2343
|
|
|
foreach ($conditions as $field => $value) { |
2344
|
|
|
$field = Database::escape_string($field); |
2345
|
|
|
$value = Database::escape_string($value); |
2346
|
|
|
$sql .= " AND $field = '$value'"; |
2347
|
|
|
} |
2348
|
|
|
} |
2349
|
|
|
|
2350
|
|
|
$sql .= str_replace("\'", "'", Database::escape_string($extraConditions)); |
2351
|
|
|
|
2352
|
|
|
if (!empty($order_by) && count($order_by) > 0) { |
2353
|
|
|
$sql .= ' ORDER BY '.Database::escape_string(implode(',', $order_by)); |
2354
|
|
|
} |
2355
|
|
|
|
2356
|
|
|
if (is_numeric($limit_from) && is_numeric($limit_from)) { |
2357
|
|
|
$limit_from = (int) $limit_from; |
2358
|
|
|
$limit_to = (int) $limit_to; |
2359
|
|
|
$sql .= " LIMIT $limit_from, $limit_to"; |
2360
|
|
|
} |
2361
|
|
|
|
2362
|
|
|
$sql_result = Database::query($sql); |
2363
|
|
|
|
2364
|
|
|
if ($getCount) { |
2365
|
|
|
$result = Database::fetch_array($sql_result); |
2366
|
|
|
|
2367
|
|
|
return $result['count']; |
2368
|
|
|
} |
2369
|
|
|
|
2370
|
|
|
while ($result = Database::fetch_array($sql_result)) { |
2371
|
|
|
$result['complete_name'] = api_get_person_name($result['firstname'], $result['lastname']); |
2372
|
|
|
$return_array[] = $result; |
2373
|
|
|
} |
2374
|
|
|
|
2375
|
|
|
return $return_array; |
2376
|
|
|
} |
2377
|
|
|
|
2378
|
|
|
/** |
2379
|
|
|
* Get a list of users of which the given conditions match with a LIKE '%cond%'. |
2380
|
|
|
* |
2381
|
|
|
* @param array $conditions a list of condition (exemple : status=>STUDENT) |
2382
|
|
|
* @param array $order_by a list of fields on which sort |
2383
|
|
|
* @param bool $simple_like Whether we want a simple LIKE 'abc' or a LIKE '%abc%' |
2384
|
|
|
* @param string $condition Whether we want the filters to be combined by AND or OR |
2385
|
|
|
* @param array $onlyThisUserList |
2386
|
|
|
* |
2387
|
|
|
* @return array an array with all users of the platform |
2388
|
|
|
* |
2389
|
|
|
* @todo optional course code parameter, optional sorting parameters... |
2390
|
|
|
* @todo security filter order_by |
2391
|
|
|
*/ |
2392
|
|
|
public static function getUserListLike( |
2393
|
|
|
$conditions = [], |
2394
|
|
|
$order_by = [], |
2395
|
|
|
$simple_like = false, |
2396
|
|
|
$condition = 'AND', |
2397
|
|
|
$onlyThisUserList = [] |
2398
|
|
|
) { |
2399
|
|
|
$user_table = Database::get_main_table(TABLE_MAIN_USER); |
2400
|
|
|
$tblAccessUrlRelUser = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER); |
2401
|
|
|
$return_array = []; |
2402
|
|
|
$sql_query = "SELECT user.id FROM $user_table user "; |
2403
|
|
|
|
2404
|
|
|
if (api_is_multiple_url_enabled()) { |
2405
|
|
|
$sql_query .= " INNER JOIN $tblAccessUrlRelUser auru ON auru.user_id = user.id "; |
2406
|
|
|
} |
2407
|
|
|
|
2408
|
|
|
$sql_query .= ' WHERE 1 = 1 '; |
2409
|
|
|
if (count($conditions) > 0) { |
2410
|
|
|
$andActive = ""; |
2411
|
|
|
if (isset($conditions['active'])) { |
2412
|
|
|
$andActive = " AND active = ".(int) $conditions['active']; |
2413
|
|
|
unset($conditions['active']); |
2414
|
|
|
} |
2415
|
|
|
|
2416
|
|
|
$temp_conditions = []; |
2417
|
|
|
foreach ($conditions as $field => $value) { |
2418
|
|
|
$field = Database::escape_string($field); |
2419
|
|
|
$value = Database::escape_string($value); |
2420
|
|
|
if ($simple_like) { |
2421
|
|
|
$temp_conditions[] = $field." LIKE '$value%'"; |
2422
|
|
|
} else { |
2423
|
|
|
$temp_conditions[] = $field.' LIKE \'%'.$value.'%\''; |
2424
|
|
|
} |
2425
|
|
|
} |
2426
|
|
|
if (!empty($temp_conditions)) { |
2427
|
|
|
$sql_query .= ' AND ('.implode(' '.$condition.' ', $temp_conditions).') '; |
2428
|
|
|
} |
2429
|
|
|
|
2430
|
|
|
if (api_is_multiple_url_enabled()) { |
2431
|
|
|
$sql_query .= ' AND auru.access_url_id = '.api_get_current_access_url_id(); |
2432
|
|
|
} |
2433
|
|
|
$sql_query .= $andActive; |
2434
|
|
|
} else { |
2435
|
|
|
if (api_is_multiple_url_enabled()) { |
2436
|
|
|
$sql_query .= ' AND auru.access_url_id = '.api_get_current_access_url_id(); |
2437
|
|
|
} |
2438
|
|
|
} |
2439
|
|
|
|
2440
|
|
|
if (api_is_session_admin() && (api_get_setting('prevent_session_admins_to_manage_all_users') === 'true')) { |
2441
|
|
|
$sql_query .= ' AND user.creator_id = '.api_get_user_id(); |
2442
|
|
|
} |
2443
|
|
|
|
2444
|
|
|
if (!empty($onlyThisUserList)) { |
2445
|
|
|
$onlyThisUserListToString = implode("','", $onlyThisUserList); |
2446
|
|
|
$sql_query .= " AND user.id IN ('$onlyThisUserListToString') "; |
2447
|
|
|
} |
2448
|
|
|
|
2449
|
|
|
if (count($order_by) > 0) { |
2450
|
|
|
$sql_query .= ' ORDER BY '.Database::escape_string(implode(',', $order_by)); |
2451
|
|
|
} |
2452
|
|
|
|
2453
|
|
|
$sql_result = Database::query($sql_query); |
2454
|
|
|
while ($result = Database::fetch_array($sql_result)) { |
2455
|
|
|
$userInfo = api_get_user_info($result['id']); |
2456
|
|
|
$return_array[] = $userInfo; |
2457
|
|
|
} |
2458
|
|
|
|
2459
|
|
|
return $return_array; |
2460
|
|
|
} |
2461
|
|
|
|
2462
|
|
|
/** |
2463
|
|
|
* Get user picture URL or path from user ID (returns an array). |
2464
|
|
|
* The return format is a complete path, enabling recovery of the directory |
2465
|
|
|
* with dirname() or the file with basename(). This also works for the |
2466
|
|
|
* functions dealing with the user's productions, as they are located in |
2467
|
|
|
* the same directory. |
2468
|
|
|
* |
2469
|
|
|
* @param int $id User ID |
2470
|
|
|
* @param string $type Type of path to return (can be 'system', 'web') |
2471
|
|
|
* @param array $userInfo user information to avoid query the DB |
2472
|
|
|
* returns the /main/img/unknown.jpg image set it at true |
2473
|
|
|
* |
2474
|
|
|
* @return array Array of 2 elements: 'dir' and 'file' which contain |
2475
|
|
|
* the dir and file as the name implies if image does not exist it will |
2476
|
|
|
* return the unknow image if anonymous parameter is true if not it returns an empty array |
2477
|
|
|
*/ |
2478
|
|
|
public static function get_user_picture_path_by_id( |
2479
|
|
|
$id, |
2480
|
|
|
$type = 'web', |
2481
|
|
|
$userInfo = [] |
2482
|
|
|
) { |
2483
|
|
|
switch ($type) { |
2484
|
|
|
case 'system': // Base: absolute system path. |
2485
|
|
|
$base = api_get_path(SYS_CODE_PATH); |
2486
|
|
|
break; |
2487
|
|
|
case 'web': // Base: absolute web path. |
2488
|
|
|
default: |
2489
|
|
|
$base = api_get_path(WEB_CODE_PATH); |
2490
|
|
|
break; |
2491
|
|
|
} |
2492
|
|
|
|
2493
|
|
|
$anonymousPath = [ |
2494
|
|
|
'dir' => $base.'img/', |
2495
|
|
|
'file' => 'unknown.jpg', |
2496
|
|
|
'email' => '', |
2497
|
|
|
]; |
2498
|
|
|
|
2499
|
|
|
if (empty($id) || empty($type)) { |
2500
|
|
|
return $anonymousPath; |
2501
|
|
|
} |
2502
|
|
|
|
2503
|
|
|
$id = (int) $id; |
2504
|
|
|
if (empty($userInfo)) { |
2505
|
|
|
$user_table = Database::get_main_table(TABLE_MAIN_USER); |
2506
|
|
|
$sql = "SELECT email, picture_uri FROM $user_table |
2507
|
|
|
WHERE id = ".$id; |
2508
|
|
|
$res = Database::query($sql); |
2509
|
|
|
|
2510
|
|
|
if (!Database::num_rows($res)) { |
2511
|
|
|
return $anonymousPath; |
2512
|
|
|
} |
2513
|
|
|
$user = Database::fetch_array($res); |
2514
|
|
|
if (empty($user['picture_uri'])) { |
2515
|
|
|
return $anonymousPath; |
2516
|
|
|
} |
2517
|
|
|
} else { |
2518
|
|
|
$user = $userInfo; |
2519
|
|
|
} |
2520
|
|
|
|
2521
|
|
|
$pictureFilename = trim($user['picture_uri']); |
2522
|
|
|
|
2523
|
|
|
$dir = self::getUserPathById($id, $type); |
2524
|
|
|
|
2525
|
|
|
return [ |
2526
|
|
|
'dir' => $dir, |
2527
|
|
|
'file' => $pictureFilename, |
2528
|
|
|
'email' => $user['email'], |
2529
|
|
|
]; |
2530
|
|
|
} |
2531
|
|
|
|
2532
|
|
|
/** |
2533
|
|
|
* *** READ BEFORE REVIEW THIS FUNCTION *** |
2534
|
|
|
* This function is a exact copy from get_user_picture_path_by_id() and it was create it to avoid |
2535
|
|
|
* a recursive calls for get_user_picture_path_by_id() in another functions when you update a user picture |
2536
|
|
|
* in same script, so you can find this function usage in update_user_picture() function. |
2537
|
|
|
* |
2538
|
|
|
* @param int $id User ID |
2539
|
|
|
* @param string $type Type of path to return (can be 'system', 'web') |
2540
|
|
|
* @param array $userInfo user information to avoid query the DB |
2541
|
|
|
* returns the /main/img/unknown.jpg image set it at true |
2542
|
|
|
* |
2543
|
|
|
* @return array Array of 2 elements: 'dir' and 'file' which contain |
2544
|
|
|
* the dir and file as the name implies if image does not exist it will |
2545
|
|
|
* return the unknown image if anonymous parameter is true if not it returns an empty array |
2546
|
|
|
*/ |
2547
|
|
|
public static function getUserPicturePathById($id, $type = 'web', $userInfo = []) |
2548
|
|
|
{ |
2549
|
|
|
switch ($type) { |
2550
|
|
|
case 'system': // Base: absolute system path. |
2551
|
|
|
$base = api_get_path(SYS_CODE_PATH); |
2552
|
|
|
break; |
2553
|
|
|
case 'web': // Base: absolute web path. |
2554
|
|
|
default: |
2555
|
|
|
$base = api_get_path(WEB_CODE_PATH); |
2556
|
|
|
break; |
2557
|
|
|
} |
2558
|
|
|
|
2559
|
|
|
$anonymousPath = [ |
2560
|
|
|
'dir' => $base.'img/', |
2561
|
|
|
'file' => 'unknown.jpg', |
2562
|
|
|
'email' => '', |
2563
|
|
|
]; |
2564
|
|
|
|
2565
|
|
|
if (empty($id) || empty($type)) { |
2566
|
|
|
return $anonymousPath; |
2567
|
|
|
} |
2568
|
|
|
|
2569
|
|
|
$id = (int) $id; |
2570
|
|
|
if (empty($userInfo)) { |
2571
|
|
|
$user_table = Database::get_main_table(TABLE_MAIN_USER); |
2572
|
|
|
$sql = "SELECT email, picture_uri FROM $user_table WHERE id = $id"; |
2573
|
|
|
$res = Database::query($sql); |
2574
|
|
|
|
2575
|
|
|
if (!Database::num_rows($res)) { |
2576
|
|
|
return $anonymousPath; |
2577
|
|
|
} |
2578
|
|
|
$user = Database::fetch_array($res); |
2579
|
|
|
|
2580
|
|
|
if (empty($user['picture_uri'])) { |
2581
|
|
|
return $anonymousPath; |
2582
|
|
|
} |
2583
|
|
|
} else { |
2584
|
|
|
$user = $userInfo; |
2585
|
|
|
} |
2586
|
|
|
|
2587
|
|
|
$pictureFilename = trim($user['picture_uri']); |
2588
|
|
|
$dir = self::getUserPathById($id, $type); |
2589
|
|
|
|
2590
|
|
|
return [ |
2591
|
|
|
'dir' => $dir, |
2592
|
|
|
'file' => $pictureFilename, |
2593
|
|
|
'email' => $user['email'], |
2594
|
|
|
]; |
2595
|
|
|
} |
2596
|
|
|
|
2597
|
|
|
/** |
2598
|
|
|
* Get user path from user ID (returns an array). |
2599
|
|
|
* The return format is a complete path to a folder ending with "/" |
2600
|
|
|
* In case the first level of subdirectory of users/ does not exist, the |
2601
|
|
|
* function will attempt to create it. Probably not the right place to do it |
2602
|
|
|
* but at least it avoids headaches in many other places. |
2603
|
|
|
* |
2604
|
|
|
* @param int $id User ID |
2605
|
|
|
* @param string $type Type of path to return (can be 'system', 'web', 'last') |
2606
|
|
|
* |
2607
|
|
|
* @return string User folder path (i.e. /var/www/chamilo/app/upload/users/1/1/) |
2608
|
|
|
*/ |
2609
|
|
|
public static function getUserPathById($id, $type) |
2610
|
|
|
{ |
2611
|
|
|
$id = (int) $id; |
2612
|
|
|
if (!$id) { |
2613
|
|
|
return null; |
2614
|
|
|
} |
2615
|
|
|
|
2616
|
|
|
$userPath = "users/$id/"; |
2617
|
|
|
if (api_get_setting('split_users_upload_directory') === 'true') { |
2618
|
|
|
$userPath = 'users/'.substr((string) $id, 0, 1).'/'.$id.'/'; |
2619
|
|
|
// In exceptional cases, on some portals, the intermediate base user |
2620
|
|
|
// directory might not have been created. Make sure it is before |
2621
|
|
|
// going further. |
2622
|
|
|
|
2623
|
|
|
$rootPath = api_get_path(SYS_UPLOAD_PATH).'users/'.substr((string) $id, 0, 1); |
2624
|
|
|
if (!is_dir($rootPath)) { |
2625
|
|
|
$perm = api_get_permissions_for_new_directories(); |
2626
|
|
|
try { |
2627
|
|
|
mkdir($rootPath, $perm); |
2628
|
|
|
} catch (Exception $e) { |
2629
|
|
|
error_log($e->getMessage()); |
2630
|
|
|
} |
2631
|
|
|
} |
2632
|
|
|
} |
2633
|
|
|
switch ($type) { |
2634
|
|
|
case 'system': // Base: absolute system path. |
2635
|
|
|
$userPath = api_get_path(SYS_UPLOAD_PATH).$userPath; |
2636
|
|
|
break; |
2637
|
|
|
case 'web': // Base: absolute web path. |
2638
|
|
|
$userPath = api_get_path(WEB_UPLOAD_PATH).$userPath; |
2639
|
|
|
break; |
2640
|
|
|
case 'last': // Only the last part starting with users/ |
2641
|
|
|
break; |
2642
|
|
|
} |
2643
|
|
|
|
2644
|
|
|
return $userPath; |
2645
|
|
|
} |
2646
|
|
|
|
2647
|
|
|
/** |
2648
|
|
|
* Gets the current user image. |
2649
|
|
|
* |
2650
|
|
|
* @param string $user_id |
2651
|
|
|
* @param int $size it can be USER_IMAGE_SIZE_SMALL, |
2652
|
|
|
* USER_IMAGE_SIZE_MEDIUM, USER_IMAGE_SIZE_BIG or USER_IMAGE_SIZE_ORIGINAL |
2653
|
|
|
* @param bool $addRandomId |
2654
|
|
|
* @param array $userInfo to avoid query the DB |
2655
|
|
|
* |
2656
|
|
|
* @return string |
2657
|
|
|
*/ |
2658
|
|
|
public static function getUserPicture( |
2659
|
|
|
$user_id, |
2660
|
|
|
$size = USER_IMAGE_SIZE_MEDIUM, |
2661
|
|
|
$addRandomId = true, |
2662
|
|
|
$userInfo = [] |
2663
|
|
|
) { |
2664
|
|
|
// Make sure userInfo is defined. Otherwise, define it! |
2665
|
|
|
if (empty($userInfo) || !is_array($userInfo) || count($userInfo) == 0) { |
2666
|
|
|
if (empty($user_id)) { |
2667
|
|
|
return ''; |
2668
|
|
|
} else { |
2669
|
|
|
$userInfo = api_get_user_info($user_id); |
2670
|
|
|
} |
2671
|
|
|
} |
2672
|
|
|
|
2673
|
|
|
$imageWebPath = self::get_user_picture_path_by_id( |
2674
|
|
|
$user_id, |
2675
|
|
|
'web', |
2676
|
|
|
$userInfo |
2677
|
|
|
); |
2678
|
|
|
$pictureWebFile = $imageWebPath['file']; |
2679
|
|
|
$pictureWebDir = $imageWebPath['dir']; |
2680
|
|
|
|
2681
|
|
|
$pictureAnonymousSize = '128'; |
2682
|
|
|
$gravatarSize = 22; |
2683
|
|
|
$realSizeName = 'small_'; |
2684
|
|
|
|
2685
|
|
|
switch ($size) { |
2686
|
|
|
case USER_IMAGE_SIZE_SMALL: |
2687
|
|
|
$pictureAnonymousSize = '32'; |
2688
|
|
|
$realSizeName = 'small_'; |
2689
|
|
|
$gravatarSize = 32; |
2690
|
|
|
break; |
2691
|
|
|
case USER_IMAGE_SIZE_MEDIUM: |
2692
|
|
|
$pictureAnonymousSize = '64'; |
2693
|
|
|
$realSizeName = 'medium_'; |
2694
|
|
|
$gravatarSize = 64; |
2695
|
|
|
break; |
2696
|
|
|
case USER_IMAGE_SIZE_ORIGINAL: |
2697
|
|
|
$pictureAnonymousSize = '128'; |
2698
|
|
|
$realSizeName = ''; |
2699
|
|
|
$gravatarSize = 128; |
2700
|
|
|
break; |
2701
|
|
|
case USER_IMAGE_SIZE_BIG: |
2702
|
|
|
$pictureAnonymousSize = '128'; |
2703
|
|
|
$realSizeName = 'big_'; |
2704
|
|
|
$gravatarSize = 128; |
2705
|
|
|
break; |
2706
|
|
|
} |
2707
|
|
|
|
2708
|
|
|
$gravatarEnabled = api_get_setting('gravatar_enabled'); |
2709
|
|
|
$anonymousPath = Display::returnIconPath('unknown.png', $pictureAnonymousSize); |
2710
|
|
|
if ($pictureWebFile == 'unknown.jpg' || empty($pictureWebFile)) { |
2711
|
|
|
if ($gravatarEnabled === 'true') { |
2712
|
|
|
$file = self::getGravatar( |
2713
|
|
|
$imageWebPath['email'], |
2714
|
|
|
$gravatarSize, |
2715
|
|
|
api_get_setting('gravatar_type') |
2716
|
|
|
); |
2717
|
|
|
|
2718
|
|
|
if ($addRandomId) { |
2719
|
|
|
$file .= '&rand='.uniqid(); |
2720
|
|
|
} |
2721
|
|
|
|
2722
|
|
|
return $file; |
2723
|
|
|
} |
2724
|
|
|
|
2725
|
|
|
return $anonymousPath; |
2726
|
|
|
} |
2727
|
|
|
|
2728
|
|
|
$pictureSysPath = self::get_user_picture_path_by_id($user_id, 'system'); |
2729
|
|
|
$file = $pictureSysPath['dir'].$realSizeName.$pictureWebFile; |
2730
|
|
|
$picture = ''; |
2731
|
|
|
if (file_exists($file)) { |
2732
|
|
|
$picture = $pictureWebDir.$realSizeName.$pictureWebFile; |
2733
|
|
|
} else { |
2734
|
|
|
$file = $pictureSysPath['dir'].$pictureWebFile; |
2735
|
|
|
if (file_exists($file) && !is_dir($file)) { |
2736
|
|
|
$picture = $pictureWebFile['dir'].$pictureWebFile; |
2737
|
|
|
} |
2738
|
|
|
} |
2739
|
|
|
|
2740
|
|
|
if (empty($picture)) { |
2741
|
|
|
return $anonymousPath; |
2742
|
|
|
} |
2743
|
|
|
|
2744
|
|
|
if ($addRandomId) { |
2745
|
|
|
$picture .= '?rand='.uniqid(); |
2746
|
|
|
} |
2747
|
|
|
|
2748
|
|
|
return $picture; |
2749
|
|
|
} |
2750
|
|
|
|
2751
|
|
|
/** |
2752
|
|
|
* Creates new user photos in various sizes of a user, or deletes user photos. |
2753
|
|
|
* Note: This method relies on configuration setting from main/inc/conf/profile.conf.php. |
2754
|
|
|
* |
2755
|
|
|
* @param int $user_id the user internal identification number |
2756
|
|
|
* @param string $file The common file name for the newly created photos. |
2757
|
|
|
* It will be checked and modified for compatibility with the file system. |
2758
|
|
|
* If full name is provided, path component is ignored. |
2759
|
|
|
* If an empty name is provided, then old user photos are deleted only, |
2760
|
|
|
* |
2761
|
|
|
* @see UserManager::delete_user_picture() as the prefered way for deletion. |
2762
|
|
|
* |
2763
|
|
|
* @param string $source_file the full system name of the image from which user photos will be created |
2764
|
|
|
* @param string $cropParameters Optional string that contents "x,y,width,height" of a cropped image format |
2765
|
|
|
* |
2766
|
|
|
* @return bool Returns the resulting common file name of created images which usually should be stored in database. |
2767
|
|
|
* When deletion is requested returns empty string. |
2768
|
|
|
* In case of internal error or negative validation returns FALSE. |
2769
|
|
|
*/ |
2770
|
|
|
public static function update_user_picture( |
2771
|
|
|
$user_id, |
2772
|
|
|
$file = null, |
2773
|
|
|
$source_file = null, |
2774
|
|
|
$cropParameters = '' |
2775
|
|
|
) { |
2776
|
|
|
if (empty($user_id)) { |
2777
|
|
|
return false; |
2778
|
|
|
} |
2779
|
|
|
$delete = empty($file); |
2780
|
|
|
if (empty($source_file)) { |
2781
|
|
|
$source_file = $file; |
2782
|
|
|
} |
2783
|
|
|
|
2784
|
|
|
// User-reserved directory where photos have to be placed. |
2785
|
|
|
$path_info = self::getUserPicturePathById($user_id, 'system'); |
2786
|
|
|
$path = $path_info['dir']; |
2787
|
|
|
|
2788
|
|
|
// If this directory does not exist - we create it. |
2789
|
|
|
if (!file_exists($path)) { |
2790
|
|
|
mkdir($path, api_get_permissions_for_new_directories(), true); |
2791
|
|
|
} |
2792
|
|
|
|
2793
|
|
|
// The old photos (if any). |
2794
|
|
|
$old_file = $path_info['file']; |
2795
|
|
|
|
2796
|
|
|
// Let us delete them. |
2797
|
|
|
if ($old_file != 'unknown.jpg') { |
2798
|
|
|
if (KEEP_THE_OLD_IMAGE_AFTER_CHANGE) { |
|
|
|
|
2799
|
|
|
$prefix = 'saved_'.date('Y_m_d_H_i_s').'_'.uniqid('').'_'; |
2800
|
|
|
@rename($path.'small_'.$old_file, $path.$prefix.'small_'.$old_file); |
|
|
|
|
2801
|
|
|
@rename($path.'medium_'.$old_file, $path.$prefix.'medium_'.$old_file); |
2802
|
|
|
@rename($path.'big_'.$old_file, $path.$prefix.'big_'.$old_file); |
2803
|
|
|
@rename($path.$old_file, $path.$prefix.$old_file); |
2804
|
|
|
} else { |
2805
|
|
|
@unlink($path.'small_'.$old_file); |
|
|
|
|
2806
|
|
|
@unlink($path.'medium_'.$old_file); |
2807
|
|
|
@unlink($path.'big_'.$old_file); |
2808
|
|
|
@unlink($path.$old_file); |
2809
|
|
|
} |
2810
|
|
|
} |
2811
|
|
|
|
2812
|
|
|
// Exit if only deletion has been requested. Return an empty picture name. |
2813
|
|
|
if ($delete) { |
2814
|
|
|
return ''; |
2815
|
|
|
} |
2816
|
|
|
|
2817
|
|
|
// Validation 2. |
2818
|
|
|
$allowed_types = api_get_supported_image_extensions(); |
2819
|
|
|
$file = str_replace('\\', '/', $file); |
2820
|
|
|
$filename = (($pos = strrpos($file, '/')) !== false) ? substr($file, $pos + 1) : $file; |
2821
|
|
|
$extension = strtolower(substr(strrchr($filename, '.'), 1)); |
2822
|
|
|
if (!in_array($extension, $allowed_types)) { |
2823
|
|
|
return false; |
2824
|
|
|
} |
2825
|
|
|
|
2826
|
|
|
// This is the common name for the new photos. |
2827
|
|
|
if (KEEP_THE_NAME_WHEN_CHANGE_IMAGE && $old_file != 'unknown.jpg') { |
|
|
|
|
2828
|
|
|
$old_extension = strtolower(substr(strrchr($old_file, '.'), 1)); |
2829
|
|
|
$filename = in_array($old_extension, $allowed_types) ? substr($old_file, 0, -strlen($old_extension)) : $old_file; |
2830
|
|
|
$filename = (substr($filename, -1) == '.') ? $filename.$extension : $filename.'.'.$extension; |
2831
|
|
|
} else { |
2832
|
|
|
$filename = api_replace_dangerous_char($filename); |
2833
|
|
|
if (PREFIX_IMAGE_FILENAME_WITH_UID) { |
|
|
|
|
2834
|
|
|
$filename = uniqid('').'_'.$filename; |
2835
|
|
|
} |
2836
|
|
|
// We always prefix user photos with user ids, so on setting |
2837
|
|
|
// api_get_setting('split_users_upload_directory') === 'true' |
2838
|
|
|
// the correspondent directories to be found successfully. |
2839
|
|
|
$filename = $user_id.'_'.$filename; |
2840
|
|
|
} |
2841
|
|
|
|
2842
|
|
|
if (!file_exists($source_file)) { |
2843
|
|
|
return false; |
2844
|
|
|
} |
2845
|
|
|
|
2846
|
|
|
$mimeContentType = mime_content_type($source_file); |
2847
|
|
|
if (false === strpos($mimeContentType, 'image')) { |
2848
|
|
|
return false; |
2849
|
|
|
} |
2850
|
|
|
|
2851
|
|
|
//Crop the image to adjust 1:1 ratio |
2852
|
|
|
$image = new Image($source_file); |
2853
|
|
|
$image->crop($cropParameters); |
2854
|
|
|
|
2855
|
|
|
// Storing the new photos in 4 versions with various sizes. |
2856
|
|
|
$userPath = self::getUserPathById($user_id, 'system'); |
2857
|
|
|
|
2858
|
|
|
// If this path does not exist - we create it. |
2859
|
|
|
if (!file_exists($userPath)) { |
2860
|
|
|
mkdir($userPath, api_get_permissions_for_new_directories(), true); |
2861
|
|
|
} |
2862
|
|
|
$small = new Image($source_file); |
2863
|
|
|
$small->resize(32); |
2864
|
|
|
$small->send_image($userPath.'small_'.$filename); |
2865
|
|
|
$medium = new Image($source_file); |
2866
|
|
|
$medium->resize(85); |
2867
|
|
|
$medium->send_image($userPath.'medium_'.$filename); |
2868
|
|
|
$normal = new Image($source_file); |
2869
|
|
|
$normal->resize(200); |
2870
|
|
|
$normal->send_image($userPath.$filename); |
2871
|
|
|
|
2872
|
|
|
$big = new Image($source_file); // This is the original picture. |
2873
|
|
|
$big->send_image($userPath.'big_'.$filename); |
2874
|
|
|
|
2875
|
|
|
$result = $small && $medium && $normal && $big; |
|
|
|
|
2876
|
|
|
|
2877
|
|
|
return $result ? $filename : false; |
2878
|
|
|
} |
2879
|
|
|
|
2880
|
|
|
/** |
2881
|
|
|
* Update User extra field file type into {user_folder}/{$extra_field}. |
2882
|
|
|
* |
2883
|
|
|
* @param int $user_id The user internal identification number |
2884
|
|
|
* @param string $extra_field The $extra_field The extra field name |
2885
|
|
|
* @param null $file The filename |
|
|
|
|
2886
|
|
|
* @param null $source_file The temporal filename |
|
|
|
|
2887
|
|
|
* |
2888
|
|
|
* @return bool|null return filename if success, but false |
2889
|
|
|
*/ |
2890
|
|
|
public static function update_user_extra_file( |
2891
|
|
|
$user_id, |
2892
|
|
|
$extra_field = '', |
2893
|
|
|
$file = null, |
2894
|
|
|
$source_file = null |
2895
|
|
|
) { |
2896
|
|
|
// Add Filter |
2897
|
|
|
$source_file = Security::filter_filename($source_file); |
2898
|
|
|
$file = Security::filter_filename($file); |
2899
|
|
|
|
2900
|
|
|
if (empty($user_id)) { |
2901
|
|
|
return false; |
2902
|
|
|
} |
2903
|
|
|
|
2904
|
|
|
if (empty($source_file)) { |
2905
|
|
|
$source_file = $file; |
2906
|
|
|
} |
2907
|
|
|
|
2908
|
|
|
// User-reserved directory where extra file have to be placed. |
2909
|
|
|
$path_info = self::get_user_picture_path_by_id($user_id, 'system'); |
2910
|
|
|
$path = $path_info['dir']; |
2911
|
|
|
if (!empty($extra_field)) { |
2912
|
|
|
$path .= $extra_field.'/'; |
2913
|
|
|
} |
2914
|
|
|
// If this directory does not exist - we create it. |
2915
|
|
|
if (!file_exists($path)) { |
2916
|
|
|
@mkdir($path, api_get_permissions_for_new_directories(), true); |
|
|
|
|
2917
|
|
|
} |
2918
|
|
|
|
2919
|
|
|
if (filter_extension($file)) { |
2920
|
|
|
if (@move_uploaded_file($source_file, $path.$file)) { |
2921
|
|
|
if ($extra_field) { |
2922
|
|
|
return $extra_field.'/'.$file; |
2923
|
|
|
} else { |
2924
|
|
|
return $file; |
2925
|
|
|
} |
2926
|
|
|
} |
2927
|
|
|
} |
2928
|
|
|
|
2929
|
|
|
return false; // this should be returned if anything went wrong with the upload |
2930
|
|
|
} |
2931
|
|
|
|
2932
|
|
|
/** |
2933
|
|
|
* Deletes user photos. |
2934
|
|
|
* Note: This method relies on configuration setting from main/inc/conf/profile.conf.php. |
2935
|
|
|
* |
2936
|
|
|
* @param int $userId the user internal identification number |
2937
|
|
|
* |
2938
|
|
|
* @return mixed returns empty string on success, FALSE on error |
2939
|
|
|
*/ |
2940
|
|
|
public static function deleteUserPicture($userId) |
2941
|
|
|
{ |
2942
|
|
|
return self::update_user_picture($userId); |
2943
|
|
|
} |
2944
|
|
|
|
2945
|
|
|
/** |
2946
|
|
|
* Returns an XHTML formatted list of productions for a user, or FALSE if he |
2947
|
|
|
* doesn't have any. |
2948
|
|
|
* |
2949
|
|
|
* If there has been a request to remove a production, the function will return |
2950
|
|
|
* without building the list unless forced to do so by the optional second |
2951
|
|
|
* parameter. This increases performance by avoiding to read through the |
2952
|
|
|
* productions on the filesystem before the removal request has been carried |
2953
|
|
|
* out because they'll have to be re-read afterwards anyway. |
2954
|
|
|
* |
2955
|
|
|
* @param int $user_id User id |
2956
|
|
|
* @param bool $force Optional parameter to force building after a removal request |
2957
|
|
|
* @param bool $showDelete |
2958
|
|
|
* |
2959
|
|
|
* @return string A string containing the XHTML code to display the production list, or FALSE |
2960
|
|
|
*/ |
2961
|
|
|
public static function build_production_list($user_id, $force = false, $showDelete = false) |
2962
|
|
|
{ |
2963
|
|
|
if (!$force && !empty($_POST['remove_production'])) { |
2964
|
|
|
return true; // postpone reading from the filesystem |
2965
|
|
|
} |
2966
|
|
|
|
2967
|
|
|
$productions = self::get_user_productions($user_id); |
2968
|
|
|
|
2969
|
|
|
if (empty($productions)) { |
2970
|
|
|
return false; |
2971
|
|
|
} |
2972
|
|
|
|
2973
|
|
|
$production_dir = self::getUserPathById($user_id, 'web'); |
2974
|
|
|
$del_image = Display::returnIconPath('delete.png'); |
2975
|
|
|
$add_image = Display::returnIconPath('archive.png'); |
2976
|
|
|
$del_text = get_lang('Delete'); |
2977
|
|
|
$production_list = ''; |
2978
|
|
|
if (count($productions) > 0) { |
2979
|
|
|
$production_list = '<div class="files-production"><ul id="productions">'; |
2980
|
|
|
foreach ($productions as $file) { |
2981
|
|
|
$production_list .= '<li> |
2982
|
|
|
<img src="'.$add_image.'" /> |
2983
|
|
|
<a href="'.$production_dir.urlencode($file).'" target="_blank"> |
2984
|
|
|
'.htmlentities($file).' |
2985
|
|
|
</a>'; |
2986
|
|
|
if ($showDelete) { |
2987
|
|
|
$production_list .= ' |
2988
|
|
|
<input |
2989
|
|
|
style="width:16px;" |
2990
|
|
|
type="image" |
2991
|
|
|
name="remove_production['.urlencode($file).']" |
2992
|
|
|
src="'.$del_image.'" |
2993
|
|
|
alt="'.$del_text.'" |
2994
|
|
|
title="'.$del_text.' '.htmlentities($file).'" |
2995
|
|
|
onclick="javascript: return confirmation(\''.htmlentities($file).'\');" /></li>'; |
2996
|
|
|
} |
2997
|
|
|
} |
2998
|
|
|
$production_list .= '</ul></div>'; |
2999
|
|
|
} |
3000
|
|
|
|
3001
|
|
|
return $production_list; |
3002
|
|
|
} |
3003
|
|
|
|
3004
|
|
|
/** |
3005
|
|
|
* Returns an array with the user's productions. |
3006
|
|
|
* |
3007
|
|
|
* @param int $user_id User id |
3008
|
|
|
* |
3009
|
|
|
* @return array An array containing the user's productions |
3010
|
|
|
*/ |
3011
|
|
|
public static function get_user_productions($user_id) |
3012
|
|
|
{ |
3013
|
|
|
$production_repository = self::getUserPathById($user_id, 'system'); |
3014
|
|
|
$productions = []; |
3015
|
|
|
|
3016
|
|
|
if (is_dir($production_repository)) { |
3017
|
|
|
$handle = opendir($production_repository); |
3018
|
|
|
while ($file = readdir($handle)) { |
3019
|
|
|
if ($file == '.' || |
3020
|
|
|
$file == '..' || |
3021
|
|
|
$file == '.htaccess' || |
3022
|
|
|
is_dir($production_repository.$file) |
3023
|
|
|
) { |
3024
|
|
|
// skip current/parent directory and .htaccess |
3025
|
|
|
continue; |
3026
|
|
|
} |
3027
|
|
|
|
3028
|
|
|
if (preg_match('/('.$user_id.'|[0-9a-f]{13}|saved)_.+\.(png|jpg|jpeg|gif)$/i', $file)) { |
3029
|
|
|
// User's photos should not be listed as productions. |
3030
|
|
|
continue; |
3031
|
|
|
} |
3032
|
|
|
$productions[] = $file; |
3033
|
|
|
} |
3034
|
|
|
} |
3035
|
|
|
|
3036
|
|
|
return $productions; |
3037
|
|
|
} |
3038
|
|
|
|
3039
|
|
|
/** |
3040
|
|
|
* Remove a user production. |
3041
|
|
|
* |
3042
|
|
|
* @param int $user_id User id |
3043
|
|
|
* @param string $production The production to remove |
3044
|
|
|
* |
3045
|
|
|
* @return bool |
3046
|
|
|
*/ |
3047
|
|
|
public static function remove_user_production($user_id, $production) |
3048
|
|
|
{ |
3049
|
|
|
$production_path = self::get_user_picture_path_by_id($user_id, 'system'); |
3050
|
|
|
$production_file = $production_path['dir'].$production; |
3051
|
|
|
if (is_file($production_file)) { |
3052
|
|
|
unlink($production_file); |
3053
|
|
|
|
3054
|
|
|
return true; |
3055
|
|
|
} |
3056
|
|
|
|
3057
|
|
|
return false; |
3058
|
|
|
} |
3059
|
|
|
|
3060
|
|
|
/** |
3061
|
|
|
* Update an extra field value for a given user. |
3062
|
|
|
* |
3063
|
|
|
* @param int $userId User ID |
3064
|
|
|
* @param string $variable Field variable name |
3065
|
|
|
* @param string $value Field value |
3066
|
|
|
* |
3067
|
|
|
* @return bool true if field updated, false otherwise |
3068
|
|
|
*/ |
3069
|
|
|
public static function update_extra_field_value($userId, $variable, $value = '') |
3070
|
|
|
{ |
3071
|
|
|
$extraFieldValue = new ExtraFieldValue('user'); |
3072
|
|
|
$params = [ |
3073
|
|
|
'item_id' => $userId, |
3074
|
|
|
'variable' => $variable, |
3075
|
|
|
'value' => $value, |
3076
|
|
|
]; |
3077
|
|
|
|
3078
|
|
|
return $extraFieldValue->save($params); |
|
|
|
|
3079
|
|
|
} |
3080
|
|
|
|
3081
|
|
|
/** |
3082
|
|
|
* Get an array of extra fields with field details (type, default value and options). |
3083
|
|
|
* |
3084
|
|
|
* @param int Offset (from which row) |
3085
|
|
|
* @param int Number of items |
3086
|
|
|
* @param int Column on which sorting is made |
3087
|
|
|
* @param string Sorting direction |
3088
|
|
|
* @param bool Optional. Whether we get all the fields or just the visible ones |
|
|
|
|
3089
|
|
|
* @param int Optional. Whether we get all the fields with field_filter 1 or 0 or everything |
3090
|
|
|
* |
3091
|
|
|
* @return array Extra fields details (e.g. $list[2]['type'], $list[4]['options'][2]['title'] |
3092
|
|
|
*/ |
3093
|
|
|
public static function get_extra_fields( |
3094
|
|
|
$from = 0, |
3095
|
|
|
$number_of_items = 0, |
3096
|
|
|
$column = 5, |
3097
|
|
|
$direction = 'ASC', |
3098
|
|
|
$all_visibility = true, |
3099
|
|
|
$field_filter = null |
3100
|
|
|
) { |
3101
|
|
|
$fields = []; |
3102
|
|
|
$t_uf = Database::get_main_table(TABLE_EXTRA_FIELD); |
3103
|
|
|
$t_ufo = Database::get_main_table(TABLE_EXTRA_FIELD_OPTIONS); |
3104
|
|
|
$columns = [ |
3105
|
|
|
'id', |
3106
|
|
|
'variable', |
3107
|
|
|
'field_type', |
3108
|
|
|
'display_text', |
3109
|
|
|
'default_value', |
3110
|
|
|
'field_order', |
3111
|
|
|
'filter', |
3112
|
|
|
]; |
3113
|
|
|
$column = (int) $column; |
3114
|
|
|
$sort_direction = ''; |
3115
|
|
|
if (!empty($direction)) { |
3116
|
|
|
if (in_array(strtoupper($direction), ['ASC', 'DESC'])) { |
3117
|
|
|
$sort_direction = strtoupper($direction); |
3118
|
|
|
} |
3119
|
|
|
} |
3120
|
|
|
$extraFieldType = EntityExtraField::USER_FIELD_TYPE; |
3121
|
|
|
$sqlf = "SELECT * FROM $t_uf WHERE extra_field_type = $extraFieldType "; |
3122
|
|
|
if (!$all_visibility) { |
3123
|
|
|
$sqlf .= " AND visible_to_self = 1 "; |
3124
|
|
|
} |
3125
|
|
|
if (!is_null($field_filter)) { |
3126
|
|
|
$field_filter = (int) $field_filter; |
3127
|
|
|
$sqlf .= " AND filter = $field_filter "; |
3128
|
|
|
} |
3129
|
|
|
$sqlf .= " ORDER BY `".$columns[$column]."` $sort_direction "; |
3130
|
|
|
if ($number_of_items != 0) { |
3131
|
|
|
$sqlf .= " LIMIT ".intval($from).','.intval($number_of_items); |
3132
|
|
|
} |
3133
|
|
|
$resf = Database::query($sqlf); |
3134
|
|
|
if (Database::num_rows($resf) > 0) { |
3135
|
|
|
while ($rowf = Database::fetch_array($resf)) { |
3136
|
|
|
$fields[$rowf['id']] = [ |
3137
|
|
|
0 => $rowf['id'], |
3138
|
|
|
1 => $rowf['variable'], |
3139
|
|
|
2 => $rowf['field_type'], |
3140
|
|
|
3 => empty($rowf['display_text']) ? '' : $rowf['display_text'], |
3141
|
|
|
4 => $rowf['default_value'], |
3142
|
|
|
5 => $rowf['field_order'], |
3143
|
|
|
6 => $rowf['visible_to_self'], |
3144
|
|
|
7 => $rowf['changeable'], |
3145
|
|
|
8 => $rowf['filter'], |
3146
|
|
|
9 => [], |
3147
|
|
|
10 => '<a name="'.$rowf['id'].'"></a>', |
3148
|
|
|
]; |
3149
|
|
|
|
3150
|
|
|
$sqlo = "SELECT * FROM $t_ufo |
3151
|
|
|
WHERE field_id = ".$rowf['id']." |
3152
|
|
|
ORDER BY option_order ASC"; |
3153
|
|
|
$reso = Database::query($sqlo); |
3154
|
|
|
if (Database::num_rows($reso) > 0) { |
3155
|
|
|
while ($rowo = Database::fetch_array($reso)) { |
3156
|
|
|
$fields[$rowf['id']][9][$rowo['id']] = [ |
3157
|
|
|
0 => $rowo['id'], |
3158
|
|
|
1 => $rowo['option_value'], |
3159
|
|
|
2 => empty($rowo['display_text']) ? '' : $rowo['display_text'], |
3160
|
|
|
3 => $rowo['option_order'], |
3161
|
|
|
]; |
3162
|
|
|
} |
3163
|
|
|
} |
3164
|
|
|
} |
3165
|
|
|
} |
3166
|
|
|
|
3167
|
|
|
return $fields; |
3168
|
|
|
} |
3169
|
|
|
|
3170
|
|
|
/** |
3171
|
|
|
* Build a list of extra file already uploaded in $user_folder/{$extra_field}/. |
3172
|
|
|
* |
3173
|
|
|
* @param $user_id |
3174
|
|
|
* @param $extra_field |
3175
|
|
|
* @param bool $force |
3176
|
|
|
* @param bool $showDelete |
3177
|
|
|
* |
3178
|
|
|
* @return bool|string |
3179
|
|
|
*/ |
3180
|
|
|
public static function build_user_extra_file_list( |
3181
|
|
|
$user_id, |
3182
|
|
|
$extra_field, |
3183
|
|
|
$force = false, |
3184
|
|
|
$showDelete = false |
3185
|
|
|
) { |
3186
|
|
|
if (!$force && !empty($_POST['remove_'.$extra_field])) { |
3187
|
|
|
return true; // postpone reading from the filesystem |
3188
|
|
|
} |
3189
|
|
|
|
3190
|
|
|
$extra_files = self::get_user_extra_files($user_id, $extra_field); |
3191
|
|
|
if (empty($extra_files)) { |
3192
|
|
|
return false; |
3193
|
|
|
} |
3194
|
|
|
|
3195
|
|
|
$path_info = self::get_user_picture_path_by_id($user_id, 'web'); |
3196
|
|
|
$path = $path_info['dir']; |
3197
|
|
|
$del_image = Display::returnIconPath('delete.png'); |
3198
|
|
|
|
3199
|
|
|
$del_text = get_lang('Delete'); |
3200
|
|
|
$extra_file_list = ''; |
3201
|
|
|
if (count($extra_files) > 0) { |
3202
|
|
|
$extra_file_list = '<div class="files-production"><ul id="productions">'; |
3203
|
|
|
foreach ($extra_files as $file) { |
3204
|
|
|
$filename = substr($file, strlen($extra_field) + 1); |
3205
|
|
|
$extra_file_list .= '<li>'.Display::return_icon('archive.png'). |
3206
|
|
|
'<a href="'.$path.$extra_field.'/'.urlencode($filename).'" target="_blank"> |
3207
|
|
|
'.htmlentities($filename). |
3208
|
|
|
'</a> '; |
3209
|
|
|
if ($showDelete) { |
3210
|
|
|
$extra_file_list .= '<input |
3211
|
|
|
style="width:16px;" |
3212
|
|
|
type="image" |
3213
|
|
|
name="remove_extra_'.$extra_field.'['.urlencode($file).']" |
3214
|
|
|
src="'.$del_image.'" |
3215
|
|
|
alt="'.$del_text.'" |
3216
|
|
|
title="'.$del_text.' '.htmlentities($filename).'" |
3217
|
|
|
onclick="javascript: return confirmation(\''.htmlentities($filename).'\');" /></li>'; |
3218
|
|
|
} |
3219
|
|
|
} |
3220
|
|
|
$extra_file_list .= '</ul></div>'; |
3221
|
|
|
} |
3222
|
|
|
|
3223
|
|
|
return $extra_file_list; |
3224
|
|
|
} |
3225
|
|
|
|
3226
|
|
|
/** |
3227
|
|
|
* Get valid filenames in $user_folder/{$extra_field}/. |
3228
|
|
|
* |
3229
|
|
|
* @param $user_id |
3230
|
|
|
* @param $extra_field |
3231
|
|
|
* @param bool $full_path |
3232
|
|
|
* |
3233
|
|
|
* @return array |
3234
|
|
|
*/ |
3235
|
|
|
public static function get_user_extra_files($user_id, $extra_field, $full_path = false) |
3236
|
|
|
{ |
3237
|
|
|
if (!$full_path) { |
3238
|
|
|
// Nothing to do |
3239
|
|
|
} else { |
3240
|
|
|
$path_info = self::get_user_picture_path_by_id($user_id, 'system'); |
3241
|
|
|
$path = $path_info['dir']; |
3242
|
|
|
} |
3243
|
|
|
$extra_data = self::get_extra_user_data_by_field($user_id, $extra_field); |
3244
|
|
|
$extra_files = $extra_data[$extra_field]; |
3245
|
|
|
|
3246
|
|
|
$files = []; |
3247
|
|
|
if (is_array($extra_files)) { |
3248
|
|
|
foreach ($extra_files as $key => $value) { |
3249
|
|
|
if (!$full_path) { |
3250
|
|
|
// Relative path from user folder |
3251
|
|
|
$files[] = $value; |
3252
|
|
|
} else { |
3253
|
|
|
$files[] = $path.$value; |
|
|
|
|
3254
|
|
|
} |
3255
|
|
|
} |
3256
|
|
|
} elseif (!empty($extra_files)) { |
3257
|
|
|
if (!$full_path) { |
3258
|
|
|
// Relative path from user folder |
3259
|
|
|
$files[] = $extra_files; |
3260
|
|
|
} else { |
3261
|
|
|
$files[] = $path.$extra_files; |
3262
|
|
|
} |
3263
|
|
|
} |
3264
|
|
|
|
3265
|
|
|
return $files; // can be an empty array |
3266
|
|
|
} |
3267
|
|
|
|
3268
|
|
|
/** |
3269
|
|
|
* Remove an {$extra_file} from the user folder $user_folder/{$extra_field}/. |
3270
|
|
|
* |
3271
|
|
|
* @param int $user_id |
3272
|
|
|
* @param string $extra_field |
3273
|
|
|
* @param string $extra_file |
3274
|
|
|
* |
3275
|
|
|
* @return bool |
3276
|
|
|
*/ |
3277
|
|
|
public static function remove_user_extra_file($user_id, $extra_field, $extra_file) |
3278
|
|
|
{ |
3279
|
|
|
$extra_file = Security::filter_filename($extra_file); |
3280
|
|
|
$path_info = self::get_user_picture_path_by_id($user_id, 'system'); |
3281
|
|
|
if (strpos($extra_file, $extra_field) !== false) { |
3282
|
|
|
$path_extra_file = $path_info['dir'].$extra_file; |
3283
|
|
|
} else { |
3284
|
|
|
$path_extra_file = $path_info['dir'].$extra_field.'/'.$extra_file; |
3285
|
|
|
} |
3286
|
|
|
if (is_file($path_extra_file)) { |
3287
|
|
|
unlink($path_extra_file); |
3288
|
|
|
|
3289
|
|
|
return true; |
3290
|
|
|
} |
3291
|
|
|
|
3292
|
|
|
return false; |
3293
|
|
|
} |
3294
|
|
|
|
3295
|
|
|
/** |
3296
|
|
|
* Creates a new extra field. |
3297
|
|
|
* |
3298
|
|
|
* @param string $variable Field's internal variable name |
3299
|
|
|
* @param int $fieldType Field's type |
3300
|
|
|
* @param string $displayText Field's language var name |
3301
|
|
|
* @param string $default Field's default value |
3302
|
|
|
* |
3303
|
|
|
* @return int |
3304
|
|
|
*/ |
3305
|
|
|
public static function create_extra_field( |
3306
|
|
|
$variable, |
3307
|
|
|
$fieldType, |
3308
|
|
|
$displayText, |
3309
|
|
|
$default |
3310
|
|
|
) { |
3311
|
|
|
$extraField = new ExtraField('user'); |
3312
|
|
|
$params = [ |
3313
|
|
|
'variable' => $variable, |
3314
|
|
|
'field_type' => $fieldType, |
3315
|
|
|
'display_text' => $displayText, |
3316
|
|
|
'default_value' => $default, |
3317
|
|
|
]; |
3318
|
|
|
|
3319
|
|
|
return $extraField->save($params); |
|
|
|
|
3320
|
|
|
} |
3321
|
|
|
|
3322
|
|
|
/** |
3323
|
|
|
* Check if a field is available. |
3324
|
|
|
* |
3325
|
|
|
* @param string $variable |
3326
|
|
|
* |
3327
|
|
|
* @return bool |
3328
|
|
|
*/ |
3329
|
|
|
public static function is_extra_field_available($variable) |
3330
|
|
|
{ |
3331
|
|
|
$extraField = new ExtraField('user'); |
3332
|
|
|
$data = $extraField->get_handler_field_info_by_field_variable($variable); |
3333
|
|
|
|
3334
|
|
|
return !empty($data) ? true : false; |
3335
|
|
|
} |
3336
|
|
|
|
3337
|
|
|
/** |
3338
|
|
|
* Gets user extra fields data. |
3339
|
|
|
* |
3340
|
|
|
* @param int User ID |
3341
|
|
|
* @param bool Whether to prefix the fields indexes with "extra_" (might be used by formvalidator) |
3342
|
|
|
* @param bool Whether to return invisible fields as well |
3343
|
|
|
* @param bool Whether to split multiple-selection fields or not |
3344
|
|
|
* @param mixed Whether to filter on the value of filter |
3345
|
|
|
* |
3346
|
|
|
* @return array Array of fields => value for the given user |
3347
|
|
|
*/ |
3348
|
|
|
public static function get_extra_user_data( |
3349
|
|
|
$user_id, |
3350
|
|
|
$prefix = false, |
3351
|
|
|
$allVisibility = true, |
3352
|
|
|
$splitMultiple = false, |
3353
|
|
|
$fieldFilter = null |
3354
|
|
|
) { |
3355
|
|
|
$user_id = (int) $user_id; |
3356
|
|
|
|
3357
|
|
|
if (empty($user_id)) { |
3358
|
|
|
return []; |
3359
|
|
|
} |
3360
|
|
|
|
3361
|
|
|
$extra_data = []; |
3362
|
|
|
$t_uf = Database::get_main_table(TABLE_EXTRA_FIELD); |
3363
|
|
|
$t_ufv = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES); |
3364
|
|
|
$user_id = (int) $user_id; |
3365
|
|
|
$sql = "SELECT f.id as id, f.variable as fvar, f.field_type as type |
3366
|
|
|
FROM $t_uf f |
3367
|
|
|
WHERE |
3368
|
|
|
extra_field_type = ".EntityExtraField::USER_FIELD_TYPE." |
3369
|
|
|
"; |
3370
|
|
|
$filter_cond = ''; |
3371
|
|
|
|
3372
|
|
|
if (!$allVisibility) { |
3373
|
|
|
if (isset($fieldFilter)) { |
3374
|
|
|
$fieldFilter = (int) $fieldFilter; |
3375
|
|
|
$filter_cond .= " AND filter = $fieldFilter "; |
3376
|
|
|
} |
3377
|
|
|
$sql .= " AND f.visible_to_self = 1 $filter_cond "; |
3378
|
|
|
} else { |
3379
|
|
|
if (isset($fieldFilter)) { |
3380
|
|
|
$fieldFilter = (int) $fieldFilter; |
3381
|
|
|
$sql .= " AND filter = $fieldFilter "; |
3382
|
|
|
} |
3383
|
|
|
} |
3384
|
|
|
|
3385
|
|
|
$sql .= ' ORDER BY f.field_order'; |
3386
|
|
|
|
3387
|
|
|
$res = Database::query($sql); |
3388
|
|
|
if (Database::num_rows($res) > 0) { |
3389
|
|
|
while ($row = Database::fetch_array($res)) { |
3390
|
|
|
if ($row['type'] == self::USER_FIELD_TYPE_TAG) { |
3391
|
|
|
$tags = self::get_user_tags_to_string($user_id, $row['id'], false); |
3392
|
|
|
$extra_data['extra_'.$row['fvar']] = $tags; |
3393
|
|
|
} else { |
3394
|
|
|
$sqlu = "SELECT value as fval |
3395
|
|
|
FROM $t_ufv |
3396
|
|
|
WHERE field_id = ".$row['id']." AND item_id = ".$user_id; |
3397
|
|
|
$resu = Database::query($sqlu); |
3398
|
|
|
|
3399
|
|
|
if (Database::num_rows($resu) > 0) { |
3400
|
|
|
$rowu = Database::fetch_array($resu); |
3401
|
|
|
$fval = $rowu['fval']; |
3402
|
|
|
if ($row['type'] == self::USER_FIELD_TYPE_SELECT_MULTIPLE) { |
3403
|
|
|
$fval = explode(';', $rowu['fval']); |
3404
|
|
|
} |
3405
|
|
|
} else { |
3406
|
|
|
// get default value |
3407
|
|
|
$sql_df = "SELECT default_value as fval_df FROM $t_uf |
3408
|
|
|
WHERE id = ".$row['id']; |
3409
|
|
|
$res_df = Database::query($sql_df); |
3410
|
|
|
$row_df = Database::fetch_array($res_df); |
3411
|
|
|
$fval = $row_df['fval_df']; |
3412
|
|
|
} |
3413
|
|
|
// We get here (and fill the $extra_data array) even if there |
3414
|
|
|
// is no user with data (we fill it with default values) |
3415
|
|
|
if ($prefix) { |
3416
|
|
|
if ($row['type'] == self::USER_FIELD_TYPE_RADIO) { |
3417
|
|
|
$extra_data['extra_'.$row['fvar']]['extra_'.$row['fvar']] = $fval; |
3418
|
|
|
} else { |
3419
|
|
|
$extra_data['extra_'.$row['fvar']] = $fval; |
3420
|
|
|
} |
3421
|
|
|
} else { |
3422
|
|
|
if ($row['type'] == self::USER_FIELD_TYPE_RADIO) { |
3423
|
|
|
$extra_data['extra_'.$row['fvar']]['extra_'.$row['fvar']] = $fval; |
3424
|
|
|
} else { |
3425
|
|
|
$extra_data[$row['fvar']] = $fval; |
3426
|
|
|
} |
3427
|
|
|
} |
3428
|
|
|
} |
3429
|
|
|
} |
3430
|
|
|
} |
3431
|
|
|
|
3432
|
|
|
return $extra_data; |
3433
|
|
|
} |
3434
|
|
|
|
3435
|
|
|
/** |
3436
|
|
|
* Get extra user data by field. |
3437
|
|
|
* |
3438
|
|
|
* @param int user ID |
3439
|
|
|
* @param string the internal variable name of the field |
3440
|
|
|
* |
3441
|
|
|
* @return array with extra data info of a user i.e array('field_variable'=>'value'); |
3442
|
|
|
*/ |
3443
|
|
|
public static function get_extra_user_data_by_field( |
3444
|
|
|
$user_id, |
3445
|
|
|
$field_variable, |
3446
|
|
|
$prefix = false, |
3447
|
|
|
$all_visibility = true, |
3448
|
|
|
$splitmultiple = false |
3449
|
|
|
) { |
3450
|
|
|
$user_id = (int) $user_id; |
3451
|
|
|
|
3452
|
|
|
if (empty($user_id)) { |
3453
|
|
|
return []; |
3454
|
|
|
} |
3455
|
|
|
|
3456
|
|
|
$extra_data = []; |
3457
|
|
|
$t_uf = Database::get_main_table(TABLE_EXTRA_FIELD); |
3458
|
|
|
$t_ufv = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES); |
3459
|
|
|
|
3460
|
|
|
$sql = "SELECT f.id as id, f.variable as fvar, f.field_type as type |
3461
|
|
|
FROM $t_uf f |
3462
|
|
|
WHERE f.variable = '$field_variable' "; |
3463
|
|
|
|
3464
|
|
|
if (!$all_visibility) { |
3465
|
|
|
$sql .= " AND f.visible_to_self = 1 "; |
3466
|
|
|
} |
3467
|
|
|
|
3468
|
|
|
$sql .= " AND extra_field_type = ".EntityExtraField::USER_FIELD_TYPE; |
3469
|
|
|
$sql .= " ORDER BY f.field_order "; |
3470
|
|
|
|
3471
|
|
|
$res = Database::query($sql); |
3472
|
|
|
if (Database::num_rows($res) > 0) { |
3473
|
|
|
while ($row = Database::fetch_array($res)) { |
3474
|
|
|
$sqlu = "SELECT value as fval FROM $t_ufv v |
3475
|
|
|
INNER JOIN $t_uf f |
3476
|
|
|
ON (v.field_id = f.id) |
3477
|
|
|
WHERE |
3478
|
|
|
extra_field_type = ".EntityExtraField::USER_FIELD_TYPE." AND |
3479
|
|
|
field_id = ".$row['id']." AND |
3480
|
|
|
item_id = ".$user_id; |
3481
|
|
|
$resu = Database::query($sqlu); |
3482
|
|
|
$fval = ''; |
3483
|
|
|
if (Database::num_rows($resu) > 0) { |
3484
|
|
|
$rowu = Database::fetch_array($resu); |
3485
|
|
|
$fval = $rowu['fval']; |
3486
|
|
|
if ($row['type'] == self::USER_FIELD_TYPE_SELECT_MULTIPLE) { |
3487
|
|
|
$fval = explode(';', $rowu['fval']); |
3488
|
|
|
} |
3489
|
|
|
} |
3490
|
|
|
if ($prefix) { |
3491
|
|
|
$extra_data['extra_'.$row['fvar']] = $fval; |
3492
|
|
|
} else { |
3493
|
|
|
$extra_data[$row['fvar']] = $fval; |
3494
|
|
|
} |
3495
|
|
|
} |
3496
|
|
|
} |
3497
|
|
|
|
3498
|
|
|
return $extra_data; |
3499
|
|
|
} |
3500
|
|
|
|
3501
|
|
|
/** |
3502
|
|
|
* Get the extra field information for a certain field (the options as well). |
3503
|
|
|
* |
3504
|
|
|
* @param string $variable The name of the field we want to know everything about |
3505
|
|
|
* |
3506
|
|
|
* @return array Array containing all the information about the extra profile field |
3507
|
|
|
* (first level of array contains field details, then 'options' sub-array contains options details, |
3508
|
|
|
* as returned by the database) |
3509
|
|
|
* |
3510
|
|
|
* @author Julio Montoya |
3511
|
|
|
* |
3512
|
|
|
* @since v1.8.6 |
3513
|
|
|
*/ |
3514
|
|
|
public static function get_extra_field_information_by_name($variable) |
3515
|
|
|
{ |
3516
|
|
|
$extraField = new ExtraField('user'); |
3517
|
|
|
|
3518
|
|
|
return $extraField->get_handler_field_info_by_field_variable($variable); |
|
|
|
|
3519
|
|
|
} |
3520
|
|
|
|
3521
|
|
|
/** |
3522
|
|
|
* Get the extra field information for user tag (the options as well). |
3523
|
|
|
* |
3524
|
|
|
* @param int $variable The name of the field we want to know everything about |
3525
|
|
|
* |
3526
|
|
|
* @return array Array containing all the information about the extra profile field |
3527
|
|
|
* (first level of array contains field details, then 'options' sub-array contains options details, |
3528
|
|
|
* as returned by the database) |
3529
|
|
|
* |
3530
|
|
|
* @author José Loguercio |
3531
|
|
|
* |
3532
|
|
|
* @since v1.11.0 |
3533
|
|
|
*/ |
3534
|
|
|
public static function get_extra_field_tags_information_by_name($variable) |
3535
|
|
|
{ |
3536
|
|
|
$extraField = new ExtraField('user'); |
3537
|
|
|
|
3538
|
|
|
return $extraField->get_handler_field_info_by_tags($variable); |
|
|
|
|
3539
|
|
|
} |
3540
|
|
|
|
3541
|
|
|
/** |
3542
|
|
|
* @param string $type |
3543
|
|
|
* |
3544
|
|
|
* @return array |
3545
|
|
|
*/ |
3546
|
|
|
public static function get_all_extra_field_by_type($type) |
3547
|
|
|
{ |
3548
|
|
|
$extraField = new ExtraField('user'); |
3549
|
|
|
|
3550
|
|
|
return $extraField->get_all_extra_field_by_type($type); |
3551
|
|
|
} |
3552
|
|
|
|
3553
|
|
|
/** |
3554
|
|
|
* Get all the extra field information of a certain field (also the options). |
3555
|
|
|
* |
3556
|
|
|
* @param int $fieldId the ID of the field we want to know everything of |
3557
|
|
|
* |
3558
|
|
|
* @return array $return containing all th information about the extra profile field |
3559
|
|
|
* |
3560
|
|
|
* @author Julio Montoya |
3561
|
|
|
* |
3562
|
|
|
* @deprecated |
3563
|
|
|
* @since v1.8.6 |
3564
|
|
|
*/ |
3565
|
|
|
public static function get_extra_field_information($fieldId) |
3566
|
|
|
{ |
3567
|
|
|
$extraField = new ExtraField('user'); |
3568
|
|
|
|
3569
|
|
|
return $extraField->getFieldInfoByFieldId($fieldId); |
|
|
|
|
3570
|
|
|
} |
3571
|
|
|
|
3572
|
|
|
/** |
3573
|
|
|
* Get extra user data by value. |
3574
|
|
|
* |
3575
|
|
|
* @param string $variable the internal variable name of the field |
3576
|
|
|
* @param string $value the internal value of the field |
3577
|
|
|
* @param bool $useLike |
3578
|
|
|
* |
3579
|
|
|
* @return array with extra data info of a user i.e array('field_variable'=>'value'); |
3580
|
|
|
*/ |
3581
|
|
|
public static function get_extra_user_data_by_value($variable, $value, $useLike = false) |
3582
|
|
|
{ |
3583
|
|
|
$extraFieldValue = new ExtraFieldValue('user'); |
3584
|
|
|
$extraField = new ExtraField('user'); |
3585
|
|
|
|
3586
|
|
|
$info = $extraField->get_handler_field_info_by_field_variable($variable); |
3587
|
|
|
|
3588
|
|
|
if (false === $info) { |
3589
|
|
|
return []; |
3590
|
|
|
} |
3591
|
|
|
|
3592
|
|
|
$data = $extraFieldValue->get_item_id_from_field_variable_and_field_value( |
3593
|
|
|
$variable, |
3594
|
|
|
$value, |
3595
|
|
|
false, |
3596
|
|
|
false, |
3597
|
|
|
true, |
3598
|
|
|
$useLike |
3599
|
|
|
); |
3600
|
|
|
|
3601
|
|
|
$result = []; |
3602
|
|
|
if (!empty($data)) { |
3603
|
|
|
foreach ($data as $item) { |
3604
|
|
|
$result[] = $item['item_id']; |
3605
|
|
|
} |
3606
|
|
|
} |
3607
|
|
|
|
3608
|
|
|
return $result; |
3609
|
|
|
} |
3610
|
|
|
|
3611
|
|
|
/** |
3612
|
|
|
* Get extra user data by tags value. |
3613
|
|
|
* |
3614
|
|
|
* @param int $fieldId the ID of the field we want to know everything of |
3615
|
|
|
* @param string $tag the tag name for search |
3616
|
|
|
* |
3617
|
|
|
* @return array with extra data info of a user |
3618
|
|
|
* |
3619
|
|
|
* @author José Loguercio |
3620
|
|
|
* |
3621
|
|
|
* @since v1.11.0 |
3622
|
|
|
*/ |
3623
|
|
|
public static function get_extra_user_data_by_tags($fieldId, $tag) |
3624
|
|
|
{ |
3625
|
|
|
$extraField = new ExtraField('user'); |
3626
|
|
|
$result = $extraField->getAllUserPerTag($fieldId, $tag); |
3627
|
|
|
$array = []; |
3628
|
|
|
foreach ($result as $index => $user) { |
3629
|
|
|
$array[] = $user['user_id']; |
3630
|
|
|
} |
3631
|
|
|
|
3632
|
|
|
return $array; |
3633
|
|
|
} |
3634
|
|
|
|
3635
|
|
|
/** |
3636
|
|
|
* Get extra user data by field variable. |
3637
|
|
|
* |
3638
|
|
|
* @param string $variable field variable |
3639
|
|
|
* |
3640
|
|
|
* @return array data |
3641
|
|
|
*/ |
3642
|
|
|
public static function get_extra_user_data_by_field_variable($variable) |
3643
|
|
|
{ |
3644
|
|
|
$extraInfo = self::get_extra_field_information_by_name($variable); |
3645
|
|
|
$field_id = (int) $extraInfo['id']; |
3646
|
|
|
|
3647
|
|
|
$extraField = new ExtraFieldValue('user'); |
3648
|
|
|
$data = $extraField->getValuesByFieldId($field_id); |
3649
|
|
|
|
3650
|
|
|
if (!empty($data)) { |
3651
|
|
|
foreach ($data as $row) { |
3652
|
|
|
$user_id = $row['item_id']; |
3653
|
|
|
$data[$user_id] = $row; |
3654
|
|
|
} |
3655
|
|
|
} |
3656
|
|
|
|
3657
|
|
|
return $data; |
|
|
|
|
3658
|
|
|
} |
3659
|
|
|
|
3660
|
|
|
/** |
3661
|
|
|
* Get extra user data tags by field variable. |
3662
|
|
|
* |
3663
|
|
|
* @param string $variable field variable |
3664
|
|
|
* |
3665
|
|
|
* @return array |
3666
|
|
|
*/ |
3667
|
|
|
public static function get_extra_user_data_for_tags($variable) |
3668
|
|
|
{ |
3669
|
|
|
$data = self::get_extra_field_tags_information_by_name($variable); |
3670
|
|
|
|
3671
|
|
|
return $data; |
3672
|
|
|
} |
3673
|
|
|
|
3674
|
|
|
/** |
3675
|
|
|
* Gives a list of [session_category][session_id] for the current user. |
3676
|
|
|
* |
3677
|
|
|
* @param int $user_id |
3678
|
|
|
* @param bool $is_time_over whether to fill the first element or not |
3679
|
|
|
* (to give space for courses out of categories) |
3680
|
|
|
* @param bool $ignore_visibility_for_admins optional true if limit time from session is over, false otherwise |
3681
|
|
|
* @param bool $ignoreTimeLimit ignore time start/end |
3682
|
|
|
* @param bool $getCount |
3683
|
|
|
* |
3684
|
|
|
* @return array list of statuses [session_category][session_id] |
3685
|
|
|
* |
3686
|
|
|
* @todo ensure multiple access urls are managed correctly |
3687
|
|
|
*/ |
3688
|
|
|
public static function get_sessions_by_category( |
3689
|
|
|
$user_id, |
3690
|
|
|
$is_time_over = true, |
3691
|
|
|
$ignore_visibility_for_admins = false, |
3692
|
|
|
$ignoreTimeLimit = false, |
3693
|
|
|
$getCount = false |
3694
|
|
|
) { |
3695
|
|
|
$user_id = (int) $user_id; |
3696
|
|
|
|
3697
|
|
|
if (empty($user_id)) { |
3698
|
|
|
return []; |
3699
|
|
|
} |
3700
|
|
|
|
3701
|
|
|
$allowOrder = api_get_configuration_value('session_list_order'); |
3702
|
|
|
$position = ''; |
3703
|
|
|
if ($allowOrder) { |
3704
|
|
|
$position = ', s.position AS position '; |
3705
|
|
|
} |
3706
|
|
|
|
3707
|
|
|
// Get the list of sessions per user |
3708
|
|
|
$now = new DateTime('now', new DateTimeZone('UTC')); |
3709
|
|
|
|
3710
|
|
|
// LEFT JOIN is used for session_rel_course_rel_user because an inner |
3711
|
|
|
// join would not catch session-courses where the user is general |
3712
|
|
|
// session coach but which do not have students nor coaches registered |
3713
|
|
|
$dqlSelect = ' COUNT(DISTINCT s.id) '; |
3714
|
|
|
|
3715
|
|
|
if (!$getCount) { |
3716
|
|
|
$dqlSelect = " DISTINCT |
3717
|
|
|
s.id, |
3718
|
|
|
s.name, |
3719
|
|
|
s.accessStartDate AS access_start_date, |
3720
|
|
|
s.accessEndDate AS access_end_date, |
3721
|
|
|
s.duration, |
3722
|
|
|
sc.id AS session_category_id, |
3723
|
|
|
sc.name AS session_category_name, |
3724
|
|
|
sc.dateStart AS session_category_date_start, |
3725
|
|
|
sc.dateEnd AS session_category_date_end, |
3726
|
|
|
s.coachAccessStartDate AS coach_access_start_date, |
3727
|
|
|
s.coachAccessEndDate AS coach_access_end_date, |
3728
|
|
|
CASE WHEN s.accessEndDate IS NULL THEN 1 ELSE 0 END HIDDEN _isFieldNull |
3729
|
|
|
$position |
3730
|
|
|
"; |
3731
|
|
|
} |
3732
|
|
|
|
3733
|
|
|
$dql = "SELECT $dqlSelect |
3734
|
|
|
FROM ChamiloCoreBundle:Session AS s |
3735
|
|
|
LEFT JOIN ChamiloCoreBundle:SessionRelCourseRelUser AS scu WITH scu.session = s |
3736
|
|
|
INNER JOIN ChamiloCoreBundle:AccessUrlRelSession AS url WITH url.sessionId = s.id |
3737
|
|
|
LEFT JOIN ChamiloCoreBundle:SessionCategory AS sc WITH s.category = sc "; |
3738
|
|
|
|
3739
|
|
|
// A single OR operation on scu.user = :user OR s.generalCoach = :user |
3740
|
|
|
// is awfully inefficient for large sets of data (1m25s for 58K |
3741
|
|
|
// sessions, BT#14115) but executing a similar query twice and grouping |
3742
|
|
|
// the results afterwards in PHP takes about 1/1000th of the time |
3743
|
|
|
// (0.1s + 0.0s) for the same set of data, so we do it this way... |
3744
|
|
|
$dqlStudent = $dql.' WHERE scu.user = :user AND url.accessUrlId = :url '; |
3745
|
|
|
$dqlCoach = $dql.' WHERE s.generalCoach = :user AND url.accessUrlId = :url '; |
3746
|
|
|
|
3747
|
|
|
// Default order |
3748
|
|
|
$order = 'ORDER BY sc.name, s.name'; |
3749
|
|
|
|
3750
|
|
|
// Order by date if showing all sessions |
3751
|
|
|
$showAllSessions = api_get_configuration_value('show_all_sessions_on_my_course_page') === true; |
3752
|
|
|
if ($showAllSessions) { |
3753
|
|
|
$order = 'ORDER BY s.accessStartDate'; |
3754
|
|
|
} |
3755
|
|
|
|
3756
|
|
|
// Order by position |
3757
|
|
|
if ($allowOrder) { |
3758
|
|
|
$order = 'ORDER BY s.position'; |
3759
|
|
|
} |
3760
|
|
|
|
3761
|
|
|
// Order by dates according to settings |
3762
|
|
|
$orderBySettings = api_get_configuration_value('my_courses_session_order'); |
3763
|
|
|
if (!empty($orderBySettings) && isset($orderBySettings['field']) && isset($orderBySettings['order'])) { |
3764
|
|
|
$field = $orderBySettings['field']; |
3765
|
|
|
$orderSetting = $orderBySettings['order']; |
3766
|
|
|
switch ($field) { |
3767
|
|
|
case 'start_date': |
3768
|
|
|
$order = " ORDER BY s.accessStartDate $orderSetting"; |
3769
|
|
|
break; |
3770
|
|
|
case 'end_date': |
3771
|
|
|
$order = " ORDER BY s.accessEndDate $orderSetting "; |
3772
|
|
|
if ($orderSetting === 'asc') { |
3773
|
|
|
// Put null values at the end |
3774
|
|
|
// https://stackoverflow.com/questions/12652034/how-can-i-order-by-null-in-dql |
3775
|
|
|
$order = ' ORDER BY _isFieldNull asc, s.accessEndDate asc'; |
3776
|
|
|
} |
3777
|
|
|
break; |
3778
|
|
|
case 'name': |
3779
|
|
|
$order = " ORDER BY s.name $orderSetting "; |
3780
|
|
|
break; |
3781
|
|
|
} |
3782
|
|
|
} |
3783
|
|
|
|
3784
|
|
|
$dqlStudent .= $order; |
3785
|
|
|
$dqlCoach .= $order; |
3786
|
|
|
|
3787
|
|
|
$accessUrlId = api_get_current_access_url_id(); |
3788
|
|
|
$dqlStudent = Database::getManager() |
3789
|
|
|
->createQuery($dqlStudent) |
3790
|
|
|
->setParameters( |
3791
|
|
|
['user' => $user_id, 'url' => $accessUrlId] |
3792
|
|
|
) |
3793
|
|
|
; |
3794
|
|
|
$dqlCoach = Database::getManager() |
3795
|
|
|
->createQuery($dqlCoach) |
3796
|
|
|
->setParameters( |
3797
|
|
|
['user' => $user_id, 'url' => $accessUrlId] |
3798
|
|
|
) |
3799
|
|
|
; |
3800
|
|
|
|
3801
|
|
|
if ($getCount) { |
3802
|
|
|
return $dqlStudent->getSingleScalarResult() + $dqlCoach->getSingleScalarResult(); |
3803
|
|
|
} |
3804
|
|
|
|
3805
|
|
|
$sessionDataStudent = $dqlStudent->getResult(); |
3806
|
|
|
$sessionDataCoach = $dqlCoach->getResult(); |
3807
|
|
|
|
3808
|
|
|
$sessionData = []; |
3809
|
|
|
// First fill $sessionData with student sessions |
3810
|
|
|
if (!empty($sessionDataStudent)) { |
3811
|
|
|
foreach ($sessionDataStudent as $row) { |
3812
|
|
|
$sessionData[$row['id']] = $row; |
3813
|
|
|
} |
3814
|
|
|
} |
3815
|
|
|
|
3816
|
|
|
// Overwrite session data of the user as a student with session data |
3817
|
|
|
// of the user as a coach. |
3818
|
|
|
// There shouldn't be such duplicate rows, but just in case... |
3819
|
|
|
if (!empty($sessionDataCoach)) { |
3820
|
|
|
foreach ($sessionDataCoach as $row) { |
3821
|
|
|
$sessionData[$row['id']] = $row; |
3822
|
|
|
} |
3823
|
|
|
} |
3824
|
|
|
|
3825
|
|
|
$collapsable = api_get_configuration_value('allow_user_session_collapsable'); |
3826
|
|
|
$extraField = new ExtraFieldValue('session'); |
3827
|
|
|
$collapsableLink = api_get_path(WEB_PATH).'user_portal.php?action=collapse_session'; |
3828
|
|
|
|
3829
|
|
|
if (empty($sessionData)) { |
3830
|
|
|
return []; |
3831
|
|
|
} |
3832
|
|
|
|
3833
|
|
|
$categories = []; |
3834
|
|
|
foreach ($sessionData as $row) { |
3835
|
|
|
$session_id = $row['id']; |
3836
|
|
|
$coachList = SessionManager::getCoachesBySession($session_id); |
3837
|
|
|
$categoryStart = $row['session_category_date_start'] ? $row['session_category_date_start']->format('Y-m-d') : ''; |
3838
|
|
|
$categoryEnd = $row['session_category_date_end'] ? $row['session_category_date_end']->format('Y-m-d') : ''; |
3839
|
|
|
$courseList = self::get_courses_list_by_session($user_id, $session_id); |
3840
|
|
|
|
3841
|
|
|
$daysLeft = SessionManager::getDayLeftInSession($row, $user_id); |
3842
|
|
|
|
3843
|
|
|
// User portal filters: |
3844
|
|
|
if (false === $ignoreTimeLimit) { |
3845
|
|
|
if ($is_time_over) { |
3846
|
|
|
// History |
3847
|
|
|
if ($row['duration']) { |
3848
|
|
|
if ($daysLeft >= 0) { |
3849
|
|
|
continue; |
3850
|
|
|
} |
3851
|
|
|
} else { |
3852
|
|
|
if (empty($row['access_end_date'])) { |
3853
|
|
|
continue; |
3854
|
|
|
} else { |
3855
|
|
|
if ($row['access_end_date'] > $now) { |
3856
|
|
|
continue; |
3857
|
|
|
} |
3858
|
|
|
} |
3859
|
|
|
} |
3860
|
|
|
} else { |
3861
|
|
|
// Current user portal |
3862
|
|
|
$isGeneralCoach = SessionManager::user_is_general_coach($user_id, $row['id']); |
3863
|
|
|
$isCoachOfCourse = in_array($user_id, $coachList); |
3864
|
|
|
|
3865
|
|
|
if (api_is_platform_admin() || $isGeneralCoach || $isCoachOfCourse) { |
3866
|
|
|
// Teachers can access the session depending in the access_coach date |
3867
|
|
|
} else { |
3868
|
|
|
if ($row['duration']) { |
3869
|
|
|
if ($daysLeft <= 0) { |
3870
|
|
|
continue; |
3871
|
|
|
} |
3872
|
|
|
} else { |
3873
|
|
|
if (isset($row['access_end_date']) && |
3874
|
|
|
!empty($row['access_end_date']) |
3875
|
|
|
) { |
3876
|
|
|
if ($row['access_end_date'] <= $now) { |
3877
|
|
|
continue; |
3878
|
|
|
} |
3879
|
|
|
} |
3880
|
|
|
} |
3881
|
|
|
} |
3882
|
|
|
} |
3883
|
|
|
} |
3884
|
|
|
|
3885
|
|
|
$categories[$row['session_category_id']]['session_category'] = [ |
3886
|
|
|
'id' => $row['session_category_id'], |
3887
|
|
|
'name' => $row['session_category_name'], |
3888
|
|
|
'date_start' => $categoryStart, |
3889
|
|
|
'date_end' => $categoryEnd, |
3890
|
|
|
]; |
3891
|
|
|
|
3892
|
|
|
$visibility = api_get_session_visibility( |
3893
|
|
|
$session_id, |
3894
|
|
|
null, |
3895
|
|
|
$ignore_visibility_for_admins |
3896
|
|
|
); |
3897
|
|
|
|
3898
|
|
|
if ($visibility != SESSION_VISIBLE) { |
3899
|
|
|
// Course Coach session visibility. |
3900
|
|
|
$blockedCourseCount = 0; |
3901
|
|
|
$closedVisibilityList = [ |
3902
|
|
|
COURSE_VISIBILITY_CLOSED, |
3903
|
|
|
COURSE_VISIBILITY_HIDDEN, |
3904
|
|
|
]; |
3905
|
|
|
|
3906
|
|
|
foreach ($courseList as $course) { |
3907
|
|
|
// Checking session visibility |
3908
|
|
|
$sessionCourseVisibility = api_get_session_visibility( |
3909
|
|
|
$session_id, |
3910
|
|
|
$course['real_id'], |
3911
|
|
|
$ignore_visibility_for_admins |
3912
|
|
|
); |
3913
|
|
|
|
3914
|
|
|
$courseIsVisible = !in_array($course['visibility'], $closedVisibilityList); |
3915
|
|
|
if ($courseIsVisible === false || $sessionCourseVisibility == SESSION_INVISIBLE) { |
3916
|
|
|
$blockedCourseCount++; |
3917
|
|
|
} |
3918
|
|
|
} |
3919
|
|
|
|
3920
|
|
|
// If all courses are blocked then no show in the list. |
3921
|
|
|
if ($blockedCourseCount === count($courseList)) { |
3922
|
|
|
$visibility = SESSION_INVISIBLE; |
3923
|
|
|
} else { |
3924
|
|
|
$visibility = $sessionCourseVisibility; |
|
|
|
|
3925
|
|
|
} |
3926
|
|
|
} |
3927
|
|
|
|
3928
|
|
|
switch ($visibility) { |
3929
|
|
|
case SESSION_VISIBLE_READ_ONLY: |
3930
|
|
|
case SESSION_VISIBLE: |
3931
|
|
|
case SESSION_AVAILABLE: |
3932
|
|
|
break; |
3933
|
|
|
case SESSION_INVISIBLE: |
3934
|
|
|
if ($ignore_visibility_for_admins === false) { |
3935
|
|
|
continue 2; |
3936
|
|
|
} |
3937
|
|
|
} |
3938
|
|
|
|
3939
|
|
|
$collapsed = ''; |
3940
|
|
|
$collapsedAction = ''; |
3941
|
|
|
if ($collapsable) { |
3942
|
|
|
$collapsableData = SessionManager::getCollapsableData( |
3943
|
|
|
$user_id, |
3944
|
|
|
$session_id, |
3945
|
|
|
$extraField, |
3946
|
|
|
$collapsableLink |
3947
|
|
|
); |
3948
|
|
|
$collapsed = $collapsableData['collapsed']; |
3949
|
|
|
$collapsedAction = $collapsableData['collapsable_link']; |
3950
|
|
|
} |
3951
|
|
|
|
3952
|
|
|
$categories[$row['session_category_id']]['sessions'][] = [ |
3953
|
|
|
'session_name' => $row['name'], |
3954
|
|
|
'session_id' => $row['id'], |
3955
|
|
|
'access_start_date' => $row['access_start_date'] ? $row['access_start_date']->format('Y-m-d H:i:s') : null, |
3956
|
|
|
'access_end_date' => $row['access_end_date'] ? $row['access_end_date']->format('Y-m-d H:i:s') : null, |
3957
|
|
|
'coach_access_start_date' => $row['coach_access_start_date'] ? $row['coach_access_start_date']->format('Y-m-d H:i:s') : null, |
3958
|
|
|
'coach_access_end_date' => $row['coach_access_end_date'] ? $row['coach_access_end_date']->format('Y-m-d H:i:s') : null, |
3959
|
|
|
'courses' => $courseList, |
3960
|
|
|
'collapsed' => $collapsed, |
3961
|
|
|
'collapsable_link' => $collapsedAction, |
3962
|
|
|
'duration' => $row['duration'], |
3963
|
|
|
]; |
3964
|
|
|
} |
3965
|
|
|
|
3966
|
|
|
return $categories; |
3967
|
|
|
} |
3968
|
|
|
|
3969
|
|
|
/** |
3970
|
|
|
* Gives a list of [session_id-course_code] => [status] for the current user. |
3971
|
|
|
* |
3972
|
|
|
* @param int $user_id |
3973
|
|
|
* @param int $sessionLimit |
3974
|
|
|
* |
3975
|
|
|
* @return array list of statuses (session_id-course_code => status) |
3976
|
|
|
*/ |
3977
|
|
|
public static function get_personal_session_course_list($user_id, $sessionLimit = null) |
3978
|
|
|
{ |
3979
|
|
|
// Database Table Definitions |
3980
|
|
|
$tbl_course = Database::get_main_table(TABLE_MAIN_COURSE); |
3981
|
|
|
$tbl_user = Database::get_main_table(TABLE_MAIN_USER); |
3982
|
|
|
$tbl_session = Database::get_main_table(TABLE_MAIN_SESSION); |
3983
|
|
|
$tbl_session_user = Database::get_main_table(TABLE_MAIN_SESSION_USER); |
3984
|
|
|
$tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER); |
3985
|
|
|
$tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER); |
3986
|
|
|
|
3987
|
|
|
$user_id = (int) $user_id; |
3988
|
|
|
|
3989
|
|
|
if (empty($user_id)) { |
3990
|
|
|
return []; |
3991
|
|
|
} |
3992
|
|
|
|
3993
|
|
|
// We filter the courses from the URL |
3994
|
|
|
$join_access_url = $where_access_url = ''; |
3995
|
|
|
if (api_get_multiple_access_url()) { |
3996
|
|
|
$access_url_id = api_get_current_access_url_id(); |
3997
|
|
|
if ($access_url_id != -1) { |
3998
|
|
|
$tbl_url_course = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE); |
3999
|
|
|
$join_access_url = "LEFT JOIN $tbl_url_course url_rel_course ON url_rel_course.c_id = course.id"; |
4000
|
|
|
$where_access_url = " AND access_url_id = $access_url_id "; |
4001
|
|
|
} |
4002
|
|
|
} |
4003
|
|
|
|
4004
|
|
|
// Courses in which we subscribed out of any session |
4005
|
|
|
$tbl_user_course_category = Database::get_main_table(TABLE_USER_COURSE_CATEGORY); |
4006
|
|
|
|
4007
|
|
|
$sql = "SELECT |
4008
|
|
|
course.code, |
4009
|
|
|
course_rel_user.status course_rel_status, |
4010
|
|
|
course_rel_user.sort sort, |
4011
|
|
|
course_rel_user.user_course_cat user_course_cat |
4012
|
|
|
FROM $tbl_course_user course_rel_user |
4013
|
|
|
LEFT JOIN $tbl_course course |
4014
|
|
|
ON course.id = course_rel_user.c_id |
4015
|
|
|
LEFT JOIN $tbl_user_course_category user_course_category |
4016
|
|
|
ON course_rel_user.user_course_cat = user_course_category.id |
4017
|
|
|
$join_access_url |
4018
|
|
|
WHERE |
4019
|
|
|
course_rel_user.user_id = '".$user_id."' AND |
4020
|
|
|
course_rel_user.relation_type <> ".COURSE_RELATION_TYPE_RRHH." |
4021
|
|
|
$where_access_url |
4022
|
|
|
ORDER BY user_course_category.sort, course_rel_user.sort, course.title ASC"; |
4023
|
|
|
|
4024
|
|
|
$course_list_sql_result = Database::query($sql); |
4025
|
|
|
|
4026
|
|
|
$personal_course_list = []; |
4027
|
|
|
if (Database::num_rows($course_list_sql_result) > 0) { |
4028
|
|
|
while ($result_row = Database::fetch_array($course_list_sql_result, 'ASSOC')) { |
4029
|
|
|
$course_info = api_get_course_info($result_row['code']); |
4030
|
|
|
$result_row['course_info'] = $course_info; |
4031
|
|
|
$personal_course_list[] = $result_row; |
4032
|
|
|
} |
4033
|
|
|
} |
4034
|
|
|
|
4035
|
|
|
$coachCourseConditions = ''; |
4036
|
|
|
// Getting sessions that are related to a coach in the session_rel_course_rel_user table |
4037
|
|
|
if (api_is_allowed_to_create_course()) { |
4038
|
|
|
$sessionListFromCourseCoach = []; |
4039
|
|
|
$sql = " SELECT DISTINCT session_id |
4040
|
|
|
FROM $tbl_session_course_user |
4041
|
|
|
WHERE user_id = $user_id AND status = 2 "; |
4042
|
|
|
|
4043
|
|
|
$result = Database::query($sql); |
4044
|
|
|
if (Database::num_rows($result)) { |
4045
|
|
|
$result = Database::store_result($result); |
4046
|
|
|
foreach ($result as $session) { |
4047
|
|
|
$sessionListFromCourseCoach[] = $session['session_id']; |
4048
|
|
|
} |
4049
|
|
|
} |
4050
|
|
|
if (!empty($sessionListFromCourseCoach)) { |
4051
|
|
|
$condition = implode("','", $sessionListFromCourseCoach); |
4052
|
|
|
$coachCourseConditions = " OR ( s.id IN ('$condition'))"; |
4053
|
|
|
} |
4054
|
|
|
} |
4055
|
|
|
|
4056
|
|
|
// Get the list of sessions where the user is subscribed |
4057
|
|
|
// This is divided into two different queries |
4058
|
|
|
$sessions = []; |
4059
|
|
|
$sessionLimitRestriction = ''; |
4060
|
|
|
if (!empty($sessionLimit)) { |
4061
|
|
|
$sessionLimit = (int) $sessionLimit; |
4062
|
|
|
$sessionLimitRestriction = "LIMIT $sessionLimit"; |
4063
|
|
|
} |
4064
|
|
|
|
4065
|
|
|
$sql = "SELECT DISTINCT s.id, name, access_start_date, access_end_date |
4066
|
|
|
FROM $tbl_session_user su INNER JOIN $tbl_session s |
4067
|
|
|
ON (s.id = su.session_id) |
4068
|
|
|
WHERE ( |
4069
|
|
|
su.user_id = $user_id AND |
4070
|
|
|
su.relation_type <> ".SESSION_RELATION_TYPE_RRHH." |
4071
|
|
|
) |
4072
|
|
|
$coachCourseConditions |
4073
|
|
|
ORDER BY access_start_date, access_end_date, name |
4074
|
|
|
$sessionLimitRestriction |
4075
|
|
|
"; |
4076
|
|
|
|
4077
|
|
|
$result = Database::query($sql); |
4078
|
|
|
if (Database::num_rows($result) > 0) { |
4079
|
|
|
while ($row = Database::fetch_assoc($result)) { |
4080
|
|
|
$sessions[$row['id']] = $row; |
4081
|
|
|
} |
4082
|
|
|
} |
4083
|
|
|
|
4084
|
|
|
$sql = "SELECT DISTINCT |
4085
|
|
|
id, name, access_start_date, access_end_date |
4086
|
|
|
FROM $tbl_session s |
4087
|
|
|
WHERE ( |
4088
|
|
|
id_coach = $user_id |
4089
|
|
|
) |
4090
|
|
|
$coachCourseConditions |
4091
|
|
|
ORDER BY access_start_date, access_end_date, name"; |
4092
|
|
|
|
4093
|
|
|
$result = Database::query($sql); |
4094
|
|
|
if (Database::num_rows($result) > 0) { |
4095
|
|
|
while ($row = Database::fetch_assoc($result)) { |
4096
|
|
|
if (empty($sessions[$row['id']])) { |
4097
|
|
|
$sessions[$row['id']] = $row; |
4098
|
|
|
} |
4099
|
|
|
} |
4100
|
|
|
} |
4101
|
|
|
|
4102
|
|
|
if (api_is_allowed_to_create_course()) { |
4103
|
|
|
foreach ($sessions as $enreg) { |
4104
|
|
|
$session_id = $enreg['id']; |
4105
|
|
|
$session_visibility = api_get_session_visibility($session_id); |
4106
|
|
|
|
4107
|
|
|
if ($session_visibility == SESSION_INVISIBLE) { |
4108
|
|
|
continue; |
4109
|
|
|
} |
4110
|
|
|
|
4111
|
|
|
// This query is horribly slow when more than a few thousand |
4112
|
|
|
// users and just a few sessions to which they are subscribed |
4113
|
|
|
$sql = "SELECT DISTINCT |
4114
|
|
|
course.code code, |
4115
|
|
|
course.title i, |
4116
|
|
|
".(api_is_western_name_order() ? "CONCAT(user.firstname,' ',user.lastname)" : "CONCAT(user.lastname,' ',user.firstname)")." t, |
4117
|
|
|
email, course.course_language l, |
4118
|
|
|
1 sort, |
4119
|
|
|
category_code user_course_cat, |
4120
|
|
|
access_start_date, |
4121
|
|
|
access_end_date, |
4122
|
|
|
session.id as session_id, |
4123
|
|
|
session.name as session_name |
4124
|
|
|
FROM $tbl_session_course_user as session_course_user |
4125
|
|
|
INNER JOIN $tbl_course AS course |
4126
|
|
|
ON course.id = session_course_user.c_id |
4127
|
|
|
INNER JOIN $tbl_session as session |
4128
|
|
|
ON session.id = session_course_user.session_id |
4129
|
|
|
LEFT JOIN $tbl_user as user |
4130
|
|
|
ON user.id = session_course_user.user_id OR session.id_coach = user.id |
4131
|
|
|
WHERE |
4132
|
|
|
session_course_user.session_id = $session_id AND ( |
4133
|
|
|
(session_course_user.user_id = $user_id AND session_course_user.status = 2) |
4134
|
|
|
OR session.id_coach = $user_id |
4135
|
|
|
) |
4136
|
|
|
ORDER BY i"; |
4137
|
|
|
$course_list_sql_result = Database::query($sql); |
4138
|
|
|
while ($result_row = Database::fetch_array($course_list_sql_result, 'ASSOC')) { |
4139
|
|
|
$result_row['course_info'] = api_get_course_info($result_row['code']); |
4140
|
|
|
$key = $result_row['session_id'].' - '.$result_row['code']; |
4141
|
|
|
$personal_course_list[$key] = $result_row; |
4142
|
|
|
} |
4143
|
|
|
} |
4144
|
|
|
} |
4145
|
|
|
|
4146
|
|
|
foreach ($sessions as $enreg) { |
4147
|
|
|
$session_id = $enreg['id']; |
4148
|
|
|
$session_visibility = api_get_session_visibility($session_id); |
4149
|
|
|
if ($session_visibility == SESSION_INVISIBLE) { |
4150
|
|
|
continue; |
4151
|
|
|
} |
4152
|
|
|
|
4153
|
|
|
/* This query is very similar to the above query, |
4154
|
|
|
but it will check the session_rel_course_user table if there are courses registered to our user or not */ |
4155
|
|
|
$sql = "SELECT DISTINCT |
4156
|
|
|
course.code code, |
4157
|
|
|
course.title i, CONCAT(user.lastname,' ',user.firstname) t, |
4158
|
|
|
email, |
4159
|
|
|
course.course_language l, |
4160
|
|
|
1 sort, |
4161
|
|
|
category_code user_course_cat, |
4162
|
|
|
access_start_date, |
4163
|
|
|
access_end_date, |
4164
|
|
|
session.id as session_id, |
4165
|
|
|
session.name as session_name, |
4166
|
|
|
IF((session_course_user.user_id = 3 AND session_course_user.status=2),'2', '5') |
4167
|
|
|
FROM $tbl_session_course_user as session_course_user |
4168
|
|
|
INNER JOIN $tbl_course AS course |
4169
|
|
|
ON course.id = session_course_user.c_id AND session_course_user.session_id = $session_id |
4170
|
|
|
INNER JOIN $tbl_session as session |
4171
|
|
|
ON session_course_user.session_id = session.id |
4172
|
|
|
LEFT JOIN $tbl_user as user ON user.id = session_course_user.user_id |
4173
|
|
|
WHERE session_course_user.user_id = $user_id |
4174
|
|
|
ORDER BY i"; |
4175
|
|
|
|
4176
|
|
|
$course_list_sql_result = Database::query($sql); |
4177
|
|
|
while ($result_row = Database::fetch_array($course_list_sql_result, 'ASSOC')) { |
4178
|
|
|
$result_row['course_info'] = api_get_course_info($result_row['code']); |
4179
|
|
|
$key = $result_row['session_id'].' - '.$result_row['code']; |
4180
|
|
|
if (!isset($personal_course_list[$key])) { |
4181
|
|
|
$personal_course_list[$key] = $result_row; |
4182
|
|
|
} |
4183
|
|
|
} |
4184
|
|
|
} |
4185
|
|
|
|
4186
|
|
|
return $personal_course_list; |
4187
|
|
|
} |
4188
|
|
|
|
4189
|
|
|
/** |
4190
|
|
|
* Gives a list of courses for the given user in the given session. |
4191
|
|
|
* |
4192
|
|
|
* @param int $user_id |
4193
|
|
|
* @param int $session_id |
4194
|
|
|
* |
4195
|
|
|
* @return array list of statuses (session_id-course_code => status) |
4196
|
|
|
*/ |
4197
|
|
|
public static function get_courses_list_by_session($user_id, $session_id) |
4198
|
|
|
{ |
4199
|
|
|
// Database Table Definitions |
4200
|
|
|
$tbl_session = Database::get_main_table(TABLE_MAIN_SESSION); |
4201
|
|
|
$tableCourse = Database::get_main_table(TABLE_MAIN_COURSE); |
4202
|
|
|
$tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER); |
4203
|
|
|
$tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE); |
4204
|
|
|
|
4205
|
|
|
$user_id = (int) $user_id; |
4206
|
|
|
$session_id = (int) $session_id; |
4207
|
|
|
// We filter the courses from the URL |
4208
|
|
|
$join_access_url = $where_access_url = ''; |
4209
|
|
|
if (api_get_multiple_access_url()) { |
4210
|
|
|
$urlId = api_get_current_access_url_id(); |
4211
|
|
|
if (-1 != $urlId) { |
4212
|
|
|
$tbl_url_session = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION); |
4213
|
|
|
$join_access_url = " , $tbl_url_session url_rel_session "; |
4214
|
|
|
$where_access_url = " AND access_url_id = $urlId AND url_rel_session.session_id = $session_id "; |
4215
|
|
|
} |
4216
|
|
|
} |
4217
|
|
|
|
4218
|
|
|
$exlearnerCondition = ""; |
4219
|
|
|
if (false !== api_get_configuration_value('user_edition_extra_field_to_check')) { |
4220
|
|
|
$exlearnerCondition = " AND scu.status NOT IN(".COURSE_EXLEARNER.")"; |
4221
|
|
|
} |
4222
|
|
|
|
4223
|
|
|
/* This query is very similar to the query below, but it will check the |
4224
|
|
|
session_rel_course_user table if there are courses registered |
4225
|
|
|
to our user or not */ |
4226
|
|
|
$sql = "SELECT DISTINCT |
4227
|
|
|
c.title, |
4228
|
|
|
c.visibility, |
4229
|
|
|
c.id as real_id, |
4230
|
|
|
c.code as course_code, |
4231
|
|
|
c.course_language, |
4232
|
|
|
sc.position, |
4233
|
|
|
c.unsubscribe |
4234
|
|
|
FROM $tbl_session_course_user as scu |
4235
|
|
|
INNER JOIN $tbl_session_course sc |
4236
|
|
|
ON (scu.session_id = sc.session_id AND scu.c_id = sc.c_id) |
4237
|
|
|
INNER JOIN $tableCourse as c |
4238
|
|
|
ON (scu.c_id = c.id) |
4239
|
|
|
$join_access_url |
4240
|
|
|
WHERE |
4241
|
|
|
scu.user_id = $user_id AND |
4242
|
|
|
scu.session_id = $session_id |
4243
|
|
|
$where_access_url |
4244
|
|
|
$exlearnerCondition |
4245
|
|
|
ORDER BY sc.position ASC"; |
4246
|
|
|
|
4247
|
|
|
$myCourseList = []; |
4248
|
|
|
$courses = []; |
4249
|
|
|
$result = Database::query($sql); |
4250
|
|
|
if (Database::num_rows($result) > 0) { |
4251
|
|
|
while ($result_row = Database::fetch_array($result, 'ASSOC')) { |
4252
|
|
|
$result_row['status'] = 5; |
4253
|
|
|
if (!in_array($result_row['real_id'], $courses)) { |
4254
|
|
|
$position = $result_row['position']; |
4255
|
|
|
if (!isset($myCourseList[$position])) { |
4256
|
|
|
$myCourseList[$position] = $result_row; |
4257
|
|
|
} else { |
4258
|
|
|
$myCourseList[] = $result_row; |
4259
|
|
|
} |
4260
|
|
|
$courses[] = $result_row['real_id']; |
4261
|
|
|
} |
4262
|
|
|
} |
4263
|
|
|
} |
4264
|
|
|
|
4265
|
|
|
if (api_is_allowed_to_create_course()) { |
4266
|
|
|
$sql = "SELECT DISTINCT |
4267
|
|
|
c.title, |
4268
|
|
|
c.visibility, |
4269
|
|
|
c.id as real_id, |
4270
|
|
|
c.code as course_code, |
4271
|
|
|
c.course_language, |
4272
|
|
|
sc.position, |
4273
|
|
|
c.unsubscribe |
4274
|
|
|
FROM $tbl_session_course_user as scu |
4275
|
|
|
INNER JOIN $tbl_session as s |
4276
|
|
|
ON (scu.session_id = s.id) |
4277
|
|
|
INNER JOIN $tbl_session_course sc |
4278
|
|
|
ON (scu.session_id = sc.session_id AND scu.c_id = sc.c_id) |
4279
|
|
|
INNER JOIN $tableCourse as c |
4280
|
|
|
ON (scu.c_id = c.id) |
4281
|
|
|
$join_access_url |
4282
|
|
|
WHERE |
4283
|
|
|
s.id = $session_id AND |
4284
|
|
|
( |
4285
|
|
|
(scu.user_id = $user_id AND scu.status = 2) OR |
4286
|
|
|
s.id_coach = $user_id |
4287
|
|
|
) |
4288
|
|
|
$where_access_url |
4289
|
|
|
$exlearnerCondition |
4290
|
|
|
ORDER BY sc.position ASC"; |
4291
|
|
|
$result = Database::query($sql); |
4292
|
|
|
|
4293
|
|
|
if (Database::num_rows($result) > 0) { |
4294
|
|
|
while ($result_row = Database::fetch_array($result, 'ASSOC')) { |
4295
|
|
|
$result_row['status'] = 2; |
4296
|
|
|
if (!in_array($result_row['real_id'], $courses)) { |
4297
|
|
|
$position = $result_row['position']; |
4298
|
|
|
if (!isset($myCourseList[$position])) { |
4299
|
|
|
$myCourseList[$position] = $result_row; |
4300
|
|
|
} else { |
4301
|
|
|
$myCourseList[] = $result_row; |
4302
|
|
|
} |
4303
|
|
|
$courses[] = $result_row['real_id']; |
4304
|
|
|
} |
4305
|
|
|
} |
4306
|
|
|
} |
4307
|
|
|
} |
4308
|
|
|
|
4309
|
|
|
if (api_is_drh()) { |
4310
|
|
|
$sessionList = SessionManager::get_sessions_followed_by_drh($user_id); |
4311
|
|
|
$sessionList = array_keys($sessionList); |
4312
|
|
|
if (in_array($session_id, $sessionList)) { |
4313
|
|
|
$courseList = SessionManager::get_course_list_by_session_id($session_id); |
4314
|
|
|
if (!empty($courseList)) { |
4315
|
|
|
foreach ($courseList as $course) { |
4316
|
|
|
if (!in_array($course['id'], $courses)) { |
4317
|
|
|
$position = $course['position']; |
4318
|
|
|
if (!isset($myCourseList[$position])) { |
4319
|
|
|
$myCourseList[$position] = $course; |
4320
|
|
|
} else { |
4321
|
|
|
$myCourseList[] = $course; |
4322
|
|
|
} |
4323
|
|
|
} |
4324
|
|
|
} |
4325
|
|
|
} |
4326
|
|
|
} |
4327
|
|
|
} else { |
4328
|
|
|
//check if user is general coach for this session |
4329
|
|
|
$sessionInfo = api_get_session_info($session_id); |
4330
|
|
|
if ($sessionInfo['id_coach'] == $user_id) { |
4331
|
|
|
$courseList = SessionManager::get_course_list_by_session_id($session_id); |
4332
|
|
|
if (!empty($courseList)) { |
4333
|
|
|
foreach ($courseList as $course) { |
4334
|
|
|
if (!in_array($course['id'], $courses)) { |
4335
|
|
|
$position = $course['position']; |
4336
|
|
|
if (!isset($myCourseList[$position])) { |
4337
|
|
|
$myCourseList[$position] = $course; |
4338
|
|
|
} else { |
4339
|
|
|
$myCourseList[] = $course; |
4340
|
|
|
} |
4341
|
|
|
} |
4342
|
|
|
} |
4343
|
|
|
} |
4344
|
|
|
} |
4345
|
|
|
} |
4346
|
|
|
|
4347
|
|
|
if (!empty($myCourseList)) { |
4348
|
|
|
ksort($myCourseList); |
4349
|
|
|
$checkPosition = array_filter(array_column($myCourseList, 'position')); |
4350
|
|
|
if (empty($checkPosition)) { |
4351
|
|
|
// The session course list doesn't have any position, |
4352
|
|
|
// then order the course list by course code. |
4353
|
|
|
$orderByCode = array_column($myCourseList, 'course_code'); |
4354
|
|
|
sort($orderByCode, SORT_NATURAL); |
4355
|
|
|
$newCourseList = []; |
4356
|
|
|
foreach ($orderByCode as $code) { |
4357
|
|
|
foreach ($myCourseList as $course) { |
4358
|
|
|
if ($code === $course['course_code']) { |
4359
|
|
|
$newCourseList[] = $course; |
4360
|
|
|
break; |
4361
|
|
|
} |
4362
|
|
|
} |
4363
|
|
|
} |
4364
|
|
|
$myCourseList = $newCourseList; |
4365
|
|
|
} |
4366
|
|
|
} |
4367
|
|
|
|
4368
|
|
|
return $myCourseList; |
4369
|
|
|
} |
4370
|
|
|
|
4371
|
|
|
/** |
4372
|
|
|
* Get user id from a username. |
4373
|
|
|
* |
4374
|
|
|
* @param string $username |
4375
|
|
|
* |
4376
|
|
|
* @return int User ID (or false if not found) |
4377
|
|
|
*/ |
4378
|
|
|
public static function get_user_id_from_username($username) |
4379
|
|
|
{ |
4380
|
|
|
if (empty($username)) { |
4381
|
|
|
return false; |
4382
|
|
|
} |
4383
|
|
|
$username = trim($username); |
4384
|
|
|
$username = Database::escape_string($username); |
4385
|
|
|
$t_user = Database::get_main_table(TABLE_MAIN_USER); |
4386
|
|
|
$sql = "SELECT id FROM $t_user WHERE username = '$username'"; |
4387
|
|
|
$res = Database::query($sql); |
4388
|
|
|
|
4389
|
|
|
if ($res === false) { |
4390
|
|
|
return false; |
4391
|
|
|
} |
4392
|
|
|
if (Database::num_rows($res) !== 1) { |
4393
|
|
|
return false; |
4394
|
|
|
} |
4395
|
|
|
$row = Database::fetch_array($res); |
4396
|
|
|
|
4397
|
|
|
return $row['id']; |
4398
|
|
|
} |
4399
|
|
|
|
4400
|
|
|
/** |
4401
|
|
|
* Get the users files upload from his share_folder. |
4402
|
|
|
* |
4403
|
|
|
* @param string $user_id User ID |
4404
|
|
|
* @param string $course course directory |
4405
|
|
|
* @param string $resourceType resource type: images, all |
4406
|
|
|
* |
4407
|
|
|
* @return string |
4408
|
|
|
*/ |
4409
|
|
|
public static function get_user_upload_files_by_course( |
4410
|
|
|
$user_id, |
4411
|
|
|
$course, |
4412
|
|
|
$resourceType = 'all' |
4413
|
|
|
) { |
4414
|
|
|
$return = ''; |
4415
|
|
|
$user_id = (int) $user_id; |
4416
|
|
|
|
4417
|
|
|
if (!empty($user_id) && !empty($course)) { |
4418
|
|
|
$path = api_get_path(SYS_COURSE_PATH).$course.'/document/shared_folder/sf_user_'.$user_id.'/'; |
4419
|
|
|
$web_path = api_get_path(WEB_COURSE_PATH).$course.'/document/shared_folder/sf_user_'.$user_id.'/'; |
4420
|
|
|
$file_list = []; |
4421
|
|
|
|
4422
|
|
|
if (is_dir($path)) { |
4423
|
|
|
$handle = opendir($path); |
4424
|
|
|
while ($file = readdir($handle)) { |
4425
|
|
|
if ($file == '.' || $file == '..' || $file == '.htaccess' || is_dir($path.$file)) { |
4426
|
|
|
continue; // skip current/parent directory and .htaccess |
4427
|
|
|
} |
4428
|
|
|
$file_list[] = $file; |
4429
|
|
|
} |
4430
|
|
|
if (count($file_list) > 0) { |
4431
|
|
|
$return = "<h4>$course</h4>"; |
4432
|
|
|
$return .= '<ul class="thumbnails">'; |
4433
|
|
|
} |
4434
|
|
|
$extensionList = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'tif']; |
4435
|
|
|
foreach ($file_list as $file) { |
4436
|
|
|
if ($resourceType == 'all') { |
4437
|
|
|
$return .= '<li> |
4438
|
|
|
<a href="'.$web_path.urlencode($file).'" target="_blank">'.htmlentities($file).'</a></li>'; |
4439
|
|
|
} elseif ($resourceType == 'images') { |
4440
|
|
|
//get extension |
4441
|
|
|
$ext = explode('.', $file); |
4442
|
|
|
if (isset($ext[1]) && in_array($ext[1], $extensionList)) { |
4443
|
|
|
$return .= '<li class="span2"> |
4444
|
|
|
<a class="thumbnail" href="'.$web_path.urlencode($file).'" target="_blank"> |
4445
|
|
|
<img src="'.$web_path.urlencode($file).'" > |
4446
|
|
|
</a> |
4447
|
|
|
</li>'; |
4448
|
|
|
} |
4449
|
|
|
} |
4450
|
|
|
} |
4451
|
|
|
if (count($file_list) > 0) { |
4452
|
|
|
$return .= '</ul>'; |
4453
|
|
|
} |
4454
|
|
|
} |
4455
|
|
|
} |
4456
|
|
|
|
4457
|
|
|
return $return; |
4458
|
|
|
} |
4459
|
|
|
|
4460
|
|
|
/** |
4461
|
|
|
* Gets the API key (or keys) and return them into an array. |
4462
|
|
|
* |
4463
|
|
|
* @param int Optional user id (defaults to the result of api_get_user_id()) |
4464
|
|
|
* @param string $api_service |
4465
|
|
|
* |
4466
|
|
|
* @return mixed Non-indexed array containing the list of API keys for this user, or FALSE on error |
4467
|
|
|
*/ |
4468
|
|
|
public static function get_api_keys($user_id = null, $api_service = 'dokeos') |
4469
|
|
|
{ |
4470
|
|
|
if ($user_id != strval(intval($user_id))) { |
4471
|
|
|
return false; |
4472
|
|
|
} |
4473
|
|
|
if (empty($user_id)) { |
4474
|
|
|
$user_id = api_get_user_id(); |
4475
|
|
|
} |
4476
|
|
|
if ($user_id === false) { |
4477
|
|
|
return false; |
4478
|
|
|
} |
4479
|
|
|
$service_name = Database::escape_string($api_service); |
4480
|
|
|
if (is_string($service_name) === false) { |
4481
|
|
|
return false; |
4482
|
|
|
} |
4483
|
|
|
$t_api = Database::get_main_table(TABLE_MAIN_USER_API_KEY); |
4484
|
|
|
$sql = "SELECT * FROM $t_api WHERE user_id = $user_id AND api_service='$api_service';"; |
4485
|
|
|
$res = Database::query($sql); |
4486
|
|
|
if ($res === false) { |
4487
|
|
|
return false; |
4488
|
|
|
} //error during query |
4489
|
|
|
$num = Database::num_rows($res); |
4490
|
|
|
if ($num == 0) { |
4491
|
|
|
return false; |
4492
|
|
|
} |
4493
|
|
|
$list = []; |
4494
|
|
|
while ($row = Database::fetch_array($res)) { |
4495
|
|
|
$list[$row['id']] = $row['api_key']; |
4496
|
|
|
} |
4497
|
|
|
|
4498
|
|
|
return $list; |
4499
|
|
|
} |
4500
|
|
|
|
4501
|
|
|
/** |
4502
|
|
|
* Adds a new API key to the users' account. |
4503
|
|
|
* |
4504
|
|
|
* @param int Optional user ID (defaults to the results of api_get_user_id()) |
4505
|
|
|
* @param string $api_service |
4506
|
|
|
* |
4507
|
|
|
* @return bool True on success, false on failure |
4508
|
|
|
*/ |
4509
|
|
|
public static function add_api_key($user_id = null, $api_service = 'dokeos') |
4510
|
|
|
{ |
4511
|
|
|
if ($user_id != strval(intval($user_id))) { |
4512
|
|
|
return false; |
4513
|
|
|
} |
4514
|
|
|
if (empty($user_id)) { |
4515
|
|
|
$user_id = api_get_user_id(); |
4516
|
|
|
} |
4517
|
|
|
if ($user_id === false) { |
4518
|
|
|
return false; |
4519
|
|
|
} |
4520
|
|
|
$service_name = Database::escape_string($api_service); |
4521
|
|
|
if (is_string($service_name) === false) { |
4522
|
|
|
return false; |
4523
|
|
|
} |
4524
|
|
|
$t_api = Database::get_main_table(TABLE_MAIN_USER_API_KEY); |
4525
|
|
|
$md5 = md5((time() + ($user_id * 5)) - rand(10000, 10000)); //generate some kind of random key |
4526
|
|
|
$sql = "INSERT INTO $t_api (user_id, api_key,api_service) VALUES ($user_id,'$md5','$service_name')"; |
4527
|
|
|
$res = Database::query($sql); |
4528
|
|
|
if ($res === false) { |
4529
|
|
|
return false; |
4530
|
|
|
} //error during query |
4531
|
|
|
$num = Database::insert_id(); |
4532
|
|
|
|
4533
|
|
|
return $num == 0 ? false : $num; |
|
|
|
|
4534
|
|
|
} |
4535
|
|
|
|
4536
|
|
|
/** |
4537
|
|
|
* Deletes an API key from the user's account. |
4538
|
|
|
* |
4539
|
|
|
* @param int API key's internal ID |
4540
|
|
|
* |
4541
|
|
|
* @return bool True on success, false on failure |
4542
|
|
|
*/ |
4543
|
|
|
public static function delete_api_key($key_id) |
4544
|
|
|
{ |
4545
|
|
|
if ($key_id != strval(intval($key_id))) { |
4546
|
|
|
return false; |
4547
|
|
|
} |
4548
|
|
|
if ($key_id === false) { |
4549
|
|
|
return false; |
4550
|
|
|
} |
4551
|
|
|
$t_api = Database::get_main_table(TABLE_MAIN_USER_API_KEY); |
4552
|
|
|
$sql = "SELECT * FROM $t_api WHERE id = ".$key_id; |
4553
|
|
|
$res = Database::query($sql); |
4554
|
|
|
if ($res === false) { |
4555
|
|
|
return false; |
4556
|
|
|
} //error during query |
4557
|
|
|
$num = Database::num_rows($res); |
4558
|
|
|
if ($num !== 1) { |
4559
|
|
|
return false; |
4560
|
|
|
} |
4561
|
|
|
$sql = "DELETE FROM $t_api WHERE id = ".$key_id; |
4562
|
|
|
$res = Database::query($sql); |
4563
|
|
|
if ($res === false) { |
4564
|
|
|
return false; |
4565
|
|
|
} //error during query |
4566
|
|
|
|
4567
|
|
|
return true; |
4568
|
|
|
} |
4569
|
|
|
|
4570
|
|
|
/** |
4571
|
|
|
* Regenerate an API key from the user's account. |
4572
|
|
|
* |
4573
|
|
|
* @param int user ID (defaults to the results of api_get_user_id()) |
4574
|
|
|
* @param string API key's internal ID |
4575
|
|
|
* |
4576
|
|
|
* @return int num |
4577
|
|
|
*/ |
4578
|
|
|
public static function update_api_key($user_id, $api_service) |
4579
|
|
|
{ |
4580
|
|
|
if ($user_id != strval(intval($user_id))) { |
4581
|
|
|
return false; |
4582
|
|
|
} |
4583
|
|
|
if ($user_id === false) { |
4584
|
|
|
return false; |
4585
|
|
|
} |
4586
|
|
|
$service_name = Database::escape_string($api_service); |
4587
|
|
|
if (is_string($service_name) === false) { |
4588
|
|
|
return false; |
4589
|
|
|
} |
4590
|
|
|
$t_api = Database::get_main_table(TABLE_MAIN_USER_API_KEY); |
4591
|
|
|
$sql = "SELECT id FROM $t_api |
4592
|
|
|
WHERE user_id=".$user_id." AND api_service='".$api_service."'"; |
4593
|
|
|
$res = Database::query($sql); |
4594
|
|
|
$num = Database::num_rows($res); |
4595
|
|
|
if ($num == 1) { |
4596
|
|
|
$id_key = Database::fetch_array($res, 'ASSOC'); |
4597
|
|
|
self::delete_api_key($id_key['id']); |
4598
|
|
|
$num = self::add_api_key($user_id, $api_service); |
4599
|
|
|
} elseif ($num == 0) { |
4600
|
|
|
$num = self::add_api_key($user_id, $api_service); |
4601
|
|
|
} |
4602
|
|
|
|
4603
|
|
|
return $num; |
|
|
|
|
4604
|
|
|
} |
4605
|
|
|
|
4606
|
|
|
/** |
4607
|
|
|
* @param int user ID (defaults to the results of api_get_user_id()) |
4608
|
|
|
* @param string API key's internal ID |
4609
|
|
|
* |
4610
|
|
|
* @return int row ID, or return false if not found |
4611
|
|
|
*/ |
4612
|
|
|
public static function get_api_key_id($user_id, $api_service) |
4613
|
|
|
{ |
4614
|
|
|
if ($user_id != strval(intval($user_id))) { |
4615
|
|
|
return false; |
4616
|
|
|
} |
4617
|
|
|
if ($user_id === false) { |
4618
|
|
|
return false; |
4619
|
|
|
} |
4620
|
|
|
if (empty($api_service)) { |
4621
|
|
|
return false; |
4622
|
|
|
} |
4623
|
|
|
$t_api = Database::get_main_table(TABLE_MAIN_USER_API_KEY); |
4624
|
|
|
$api_service = Database::escape_string($api_service); |
4625
|
|
|
$sql = "SELECT id FROM $t_api |
4626
|
|
|
WHERE user_id=".$user_id." AND api_service='".$api_service."'"; |
4627
|
|
|
$res = Database::query($sql); |
4628
|
|
|
if (Database::num_rows($res) < 1) { |
4629
|
|
|
return false; |
4630
|
|
|
} |
4631
|
|
|
$row = Database::fetch_array($res, 'ASSOC'); |
4632
|
|
|
|
4633
|
|
|
return $row['id']; |
4634
|
|
|
} |
4635
|
|
|
|
4636
|
|
|
/** |
4637
|
|
|
* Checks if a user_id is platform admin. |
4638
|
|
|
* |
4639
|
|
|
* @param int user ID |
4640
|
|
|
* |
4641
|
|
|
* @return bool True if is admin, false otherwise |
4642
|
|
|
* |
4643
|
|
|
* @see main_api.lib.php::api_is_platform_admin() for a context-based check |
4644
|
|
|
*/ |
4645
|
|
|
public static function is_admin($user_id) |
4646
|
|
|
{ |
4647
|
|
|
$user_id = (int) $user_id; |
4648
|
|
|
if (empty($user_id)) { |
4649
|
|
|
return false; |
4650
|
|
|
} |
4651
|
|
|
$admin_table = Database::get_main_table(TABLE_MAIN_ADMIN); |
4652
|
|
|
$sql = "SELECT * FROM $admin_table WHERE user_id = $user_id"; |
4653
|
|
|
$res = Database::query($sql); |
4654
|
|
|
|
4655
|
|
|
return Database::num_rows($res) === 1; |
4656
|
|
|
} |
4657
|
|
|
|
4658
|
|
|
/** |
4659
|
|
|
* Get the total count of users. |
4660
|
|
|
* |
4661
|
|
|
* @param int|null $status Status of users to be counted |
4662
|
|
|
* @param int|null $access_url_id Access URL ID (optional) |
4663
|
|
|
* |
4664
|
|
|
* @return mixed Number of users or false on error |
4665
|
|
|
*/ |
4666
|
|
|
public static function get_number_of_users( |
4667
|
|
|
int $status = null, |
4668
|
|
|
int $access_url_id = null, |
4669
|
|
|
int $active = null, |
4670
|
|
|
string $dateFrom = null, |
4671
|
|
|
string $dateUntil = null |
4672
|
|
|
) { |
4673
|
|
|
$tableUser = Database::get_main_table(TABLE_MAIN_USER); |
4674
|
|
|
$tableAccessUrlRelUser = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER); |
4675
|
|
|
|
4676
|
|
|
if (empty($access_url_id)) { |
4677
|
|
|
$access_url_id = api_get_current_access_url_id(); |
4678
|
|
|
} |
4679
|
|
|
|
4680
|
|
|
if (api_is_multiple_url_enabled()) { |
4681
|
|
|
$sql = "SELECT count(u.id) |
4682
|
|
|
FROM $tableUser u |
4683
|
|
|
INNER JOIN $tableAccessUrlRelUser url_user |
4684
|
|
|
ON (u.id = url_user.user_id) |
4685
|
|
|
WHERE url_user.access_url_id = $access_url_id |
4686
|
|
|
"; |
4687
|
|
|
} else { |
4688
|
|
|
$sql = "SELECT count(u.id) |
4689
|
|
|
FROM $tableUser u |
4690
|
|
|
WHERE 1 = 1 "; |
4691
|
|
|
} |
4692
|
|
|
|
4693
|
|
|
if (is_int($status) && $status > 0) { |
4694
|
|
|
$status = (int) $status; |
4695
|
|
|
$sql .= " AND u.status = $status "; |
4696
|
|
|
} |
4697
|
|
|
|
4698
|
|
|
if (isset($active)) { |
4699
|
|
|
$active = (int) $active; |
4700
|
|
|
$sql .= " AND u.active = $active "; |
4701
|
|
|
} |
4702
|
|
|
|
4703
|
|
|
if (!empty($dateFrom)) { |
4704
|
|
|
$dateFrom = api_get_utc_datetime("$dateFrom 00:00:00"); |
4705
|
|
|
$sql .= " AND u.registration_date >= '$dateFrom' "; |
4706
|
|
|
} |
4707
|
|
|
|
4708
|
|
|
if (!empty($dateUntil)) { |
4709
|
|
|
$dateUntil = api_get_utc_datetime("$dateUntil 23:59:59"); |
4710
|
|
|
$sql .= " AND u.registration_date <= '$dateUntil' "; |
4711
|
|
|
} |
4712
|
|
|
|
4713
|
|
|
$res = Database::query($sql); |
4714
|
|
|
if (Database::num_rows($res) === 1) { |
4715
|
|
|
return (int) Database::result($res, 0, 0); |
4716
|
|
|
} |
4717
|
|
|
|
4718
|
|
|
return false; |
4719
|
|
|
} |
4720
|
|
|
|
4721
|
|
|
/** |
4722
|
|
|
* Gets the tags of a specific field_id |
4723
|
|
|
* USER TAGS. |
4724
|
|
|
* |
4725
|
|
|
* Instructions to create a new user tag by Julio Montoya <[email protected]> |
4726
|
|
|
* |
4727
|
|
|
* 1. Create a new extra field in main/admin/user_fields.php with the "TAG" field type make it available and visible. |
4728
|
|
|
* Called it "books" for example. |
4729
|
|
|
* 2. Go to profile main/auth/profile.php There you will see a special input (facebook style) that will show suggestions of tags. |
4730
|
|
|
* 3. All the tags are registered in the user_tag table and the relationship between user and tags is in the user_rel_tag table |
4731
|
|
|
* 4. Tags are independent this means that tags can't be shared between tags + book + hobbies. |
4732
|
|
|
* 5. Test and enjoy. |
4733
|
|
|
* |
4734
|
|
|
* @param string $tag |
4735
|
|
|
* @param int $field_id field_id |
4736
|
|
|
* @param string $return_format how we are going to result value in array or in a string (json) |
4737
|
|
|
* @param $limit |
4738
|
|
|
* |
4739
|
|
|
* @return mixed |
4740
|
|
|
*/ |
4741
|
|
|
public static function get_tags($tag, $field_id, $return_format = 'json', $limit = 10) |
4742
|
|
|
{ |
4743
|
|
|
// database table definition |
4744
|
|
|
$table_user_tag = Database::get_main_table(TABLE_MAIN_TAG); |
4745
|
|
|
$field_id = (int) $field_id; |
4746
|
|
|
$limit = (int) $limit; |
4747
|
|
|
$tag = trim(Database::escape_string($tag)); |
4748
|
|
|
|
4749
|
|
|
// all the information of the field |
4750
|
|
|
$sql = "SELECT DISTINCT id, tag from $table_user_tag |
4751
|
|
|
WHERE field_id = $field_id AND tag LIKE '$tag%' |
4752
|
|
|
ORDER BY tag |
4753
|
|
|
LIMIT $limit"; |
4754
|
|
|
$result = Database::query($sql); |
4755
|
|
|
$return = []; |
4756
|
|
|
if (Database::num_rows($result) > 0) { |
4757
|
|
|
while ($row = Database::fetch_array($result, 'ASSOC')) { |
4758
|
|
|
$return[] = ['id' => $row['tag'], 'text' => $row['tag']]; |
4759
|
|
|
} |
4760
|
|
|
} |
4761
|
|
|
if ($return_format === 'json') { |
4762
|
|
|
$return = json_encode($return); |
4763
|
|
|
} |
4764
|
|
|
|
4765
|
|
|
return $return; |
4766
|
|
|
} |
4767
|
|
|
|
4768
|
|
|
/** |
4769
|
|
|
* @param int $field_id |
4770
|
|
|
* @param int $limit |
4771
|
|
|
* |
4772
|
|
|
* @return array |
4773
|
|
|
*/ |
4774
|
|
|
public static function get_top_tags($field_id, $limit = 100) |
4775
|
|
|
{ |
4776
|
|
|
// database table definition |
4777
|
|
|
$table_user_tag = Database::get_main_table(TABLE_MAIN_TAG); |
4778
|
|
|
$table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG); |
4779
|
|
|
$field_id = (int) $field_id; |
4780
|
|
|
$limit = (int) $limit; |
4781
|
|
|
// all the information of the field |
4782
|
|
|
$sql = "SELECT count(*) count, tag FROM $table_user_tag_values uv |
4783
|
|
|
INNER JOIN $table_user_tag ut |
4784
|
|
|
ON (ut.id = uv.tag_id) |
4785
|
|
|
WHERE field_id = $field_id |
4786
|
|
|
GROUP BY tag_id |
4787
|
|
|
ORDER BY count DESC |
4788
|
|
|
LIMIT $limit"; |
4789
|
|
|
$result = Database::query($sql); |
4790
|
|
|
$return = []; |
4791
|
|
|
if (Database::num_rows($result) > 0) { |
4792
|
|
|
while ($row = Database::fetch_array($result, 'ASSOC')) { |
4793
|
|
|
$return[] = $row; |
4794
|
|
|
} |
4795
|
|
|
} |
4796
|
|
|
|
4797
|
|
|
return $return; |
4798
|
|
|
} |
4799
|
|
|
|
4800
|
|
|
/** |
4801
|
|
|
* Get user's tags. |
4802
|
|
|
* |
4803
|
|
|
* @param int $user_id |
4804
|
|
|
* @param int $field_id |
4805
|
|
|
* |
4806
|
|
|
* @return array |
4807
|
|
|
*/ |
4808
|
|
|
public static function get_user_tags($user_id, $field_id) |
4809
|
|
|
{ |
4810
|
|
|
// database table definition |
4811
|
|
|
$table_user_tag = Database::get_main_table(TABLE_MAIN_TAG); |
4812
|
|
|
$table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG); |
4813
|
|
|
$field_id = (int) $field_id; |
4814
|
|
|
$user_id = (int) $user_id; |
4815
|
|
|
|
4816
|
|
|
// all the information of the field |
4817
|
|
|
$sql = "SELECT ut.id, tag, count |
4818
|
|
|
FROM $table_user_tag ut |
4819
|
|
|
INNER JOIN $table_user_tag_values uv |
4820
|
|
|
ON (uv.tag_id=ut.ID) |
4821
|
|
|
WHERE field_id = $field_id AND user_id = $user_id |
4822
|
|
|
ORDER BY tag"; |
4823
|
|
|
$result = Database::query($sql); |
4824
|
|
|
$return = []; |
4825
|
|
|
if (Database::num_rows($result) > 0) { |
4826
|
|
|
while ($row = Database::fetch_array($result, 'ASSOC')) { |
4827
|
|
|
$return[$row['id']] = ['tag' => $row['tag'], 'count' => $row['count']]; |
4828
|
|
|
} |
4829
|
|
|
} |
4830
|
|
|
|
4831
|
|
|
return $return; |
4832
|
|
|
} |
4833
|
|
|
|
4834
|
|
|
/** |
4835
|
|
|
* Get user's tags. |
4836
|
|
|
* |
4837
|
|
|
* @param int $user_id |
4838
|
|
|
* @param int $field_id |
4839
|
|
|
* @param bool $show_links show links or not |
4840
|
|
|
* |
4841
|
|
|
* @return string |
4842
|
|
|
*/ |
4843
|
|
|
public static function get_user_tags_to_string($user_id, $field_id, $show_links = true) |
4844
|
|
|
{ |
4845
|
|
|
// database table definition |
4846
|
|
|
$table_user_tag = Database::get_main_table(TABLE_MAIN_TAG); |
4847
|
|
|
$table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG); |
4848
|
|
|
$field_id = (int) $field_id; |
4849
|
|
|
$user_id = (int) $user_id; |
4850
|
|
|
|
4851
|
|
|
// all the information of the field |
4852
|
|
|
$sql = "SELECT ut.id, tag,count FROM $table_user_tag ut |
4853
|
|
|
INNER JOIN $table_user_tag_values uv |
4854
|
|
|
ON (uv.tag_id = ut.id) |
4855
|
|
|
WHERE field_id = $field_id AND user_id = $user_id |
4856
|
|
|
ORDER BY tag"; |
4857
|
|
|
|
4858
|
|
|
$result = Database::query($sql); |
4859
|
|
|
$return = []; |
4860
|
|
|
if (Database::num_rows($result) > 0) { |
4861
|
|
|
while ($row = Database::fetch_array($result, 'ASSOC')) { |
4862
|
|
|
$return[$row['id']] = ['tag' => $row['tag'], 'count' => $row['count']]; |
4863
|
|
|
} |
4864
|
|
|
} |
4865
|
|
|
$user_tags = $return; |
4866
|
|
|
$tag_tmp = []; |
4867
|
|
|
foreach ($user_tags as $tag) { |
4868
|
|
|
if ($show_links) { |
4869
|
|
|
$tag_tmp[] = '<a href="'.api_get_path(WEB_PATH).'main/search/index.php?q='.$tag['tag'].'">'. |
4870
|
|
|
$tag['tag']. |
4871
|
|
|
'</a>'; |
4872
|
|
|
} else { |
4873
|
|
|
$tag_tmp[] = $tag['tag']; |
4874
|
|
|
} |
4875
|
|
|
} |
4876
|
|
|
|
4877
|
|
|
if (is_array($user_tags) && count($user_tags) > 0) { |
4878
|
|
|
return implode(', ', $tag_tmp); |
4879
|
|
|
} else { |
4880
|
|
|
return ''; |
4881
|
|
|
} |
4882
|
|
|
} |
4883
|
|
|
|
4884
|
|
|
/** |
4885
|
|
|
* Get the tag id. |
4886
|
|
|
* |
4887
|
|
|
* @param int $tag |
4888
|
|
|
* @param int $field_id |
4889
|
|
|
* |
4890
|
|
|
* @return int returns 0 if fails otherwise the tag id |
4891
|
|
|
*/ |
4892
|
|
|
public static function get_tag_id($tag, $field_id) |
4893
|
|
|
{ |
4894
|
|
|
$table_user_tag = Database::get_main_table(TABLE_MAIN_TAG); |
4895
|
|
|
$tag = Database::escape_string($tag); |
4896
|
|
|
$field_id = (int) $field_id; |
4897
|
|
|
//with COLLATE latin1_bin to select query in a case sensitive mode |
4898
|
|
|
$sql = "SELECT id FROM $table_user_tag |
4899
|
|
|
WHERE tag LIKE '$tag' AND field_id = $field_id"; |
4900
|
|
|
$result = Database::query($sql); |
4901
|
|
|
if (Database::num_rows($result) > 0) { |
4902
|
|
|
$row = Database::fetch_array($result, 'ASSOC'); |
4903
|
|
|
|
4904
|
|
|
return $row['id']; |
4905
|
|
|
} else { |
4906
|
|
|
return 0; |
4907
|
|
|
} |
4908
|
|
|
} |
4909
|
|
|
|
4910
|
|
|
/** |
4911
|
|
|
* Get the tag id. |
4912
|
|
|
* |
4913
|
|
|
* @param int $tag_id |
4914
|
|
|
* @param int $field_id |
4915
|
|
|
* |
4916
|
|
|
* @return int 0 if fails otherwise the tag id |
4917
|
|
|
*/ |
4918
|
|
|
public static function get_tag_id_from_id($tag_id, $field_id) |
4919
|
|
|
{ |
4920
|
|
|
$table_user_tag = Database::get_main_table(TABLE_MAIN_TAG); |
4921
|
|
|
$tag_id = (int) $tag_id; |
4922
|
|
|
$field_id = (int) $field_id; |
4923
|
|
|
$sql = "SELECT id FROM $table_user_tag |
4924
|
|
|
WHERE id = '$tag_id' AND field_id = $field_id"; |
4925
|
|
|
$result = Database::query($sql); |
4926
|
|
|
if (Database::num_rows($result) > 0) { |
4927
|
|
|
$row = Database::fetch_array($result, 'ASSOC'); |
4928
|
|
|
|
4929
|
|
|
return $row['id']; |
4930
|
|
|
} else { |
4931
|
|
|
return false; |
4932
|
|
|
} |
4933
|
|
|
} |
4934
|
|
|
|
4935
|
|
|
/** |
4936
|
|
|
* Adds a user-tag value. |
4937
|
|
|
* |
4938
|
|
|
* @param mixed $tag |
4939
|
|
|
* @param int $user_id |
4940
|
|
|
* @param int $field_id field id of the tag |
4941
|
|
|
* |
4942
|
|
|
* @return bool True if the tag was inserted or updated. False otherwise. |
4943
|
|
|
* The return value doesn't take into account *values* added to the tag. |
4944
|
|
|
* Only the creation/update of the tag field itself. |
4945
|
|
|
*/ |
4946
|
|
|
public static function add_tag($tag, $user_id, $field_id) |
4947
|
|
|
{ |
4948
|
|
|
// database table definition |
4949
|
|
|
$table_user_tag = Database::get_main_table(TABLE_MAIN_TAG); |
4950
|
|
|
$table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG); |
4951
|
|
|
$tag = trim(Database::escape_string($tag)); |
4952
|
|
|
$user_id = (int) $user_id; |
4953
|
|
|
$field_id = (int) $field_id; |
4954
|
|
|
|
4955
|
|
|
$tag_id = self::get_tag_id($tag, $field_id); |
4956
|
|
|
|
4957
|
|
|
/* IMPORTANT |
4958
|
|
|
* @todo we don't create tags with numbers |
4959
|
|
|
* |
4960
|
|
|
*/ |
4961
|
|
|
if (is_numeric($tag)) { |
4962
|
|
|
//the form is sending an id this means that the user select it from the list so it MUST exists |
4963
|
|
|
/* $new_tag_id = self::get_tag_id_from_id($tag,$field_id); |
4964
|
|
|
if ($new_tag_id !== false) { |
4965
|
|
|
$sql = "UPDATE $table_user_tag SET count = count + 1 WHERE id = $new_tag_id"; |
4966
|
|
|
$result = Database::query($sql); |
4967
|
|
|
$last_insert_id = $new_tag_id; |
4968
|
|
|
} else { |
4969
|
|
|
$sql = "INSERT INTO $table_user_tag (tag, field_id,count) VALUES ('$tag','$field_id', count + 1)"; |
4970
|
|
|
$result = Database::query($sql); |
4971
|
|
|
$last_insert_id = Database::insert_id(); |
4972
|
|
|
} */ |
4973
|
|
|
} |
4974
|
|
|
|
4975
|
|
|
//this is a new tag |
4976
|
|
|
if ($tag_id == 0) { |
4977
|
|
|
//the tag doesn't exist |
4978
|
|
|
$sql = "INSERT INTO $table_user_tag (tag, field_id,count) VALUES ('$tag','$field_id', count + 1)"; |
4979
|
|
|
Database::query($sql); |
4980
|
|
|
$last_insert_id = Database::insert_id(); |
4981
|
|
|
} else { |
4982
|
|
|
//the tag exists we update it |
4983
|
|
|
$sql = "UPDATE $table_user_tag SET count = count + 1 WHERE id = $tag_id"; |
4984
|
|
|
Database::query($sql); |
4985
|
|
|
$last_insert_id = $tag_id; |
4986
|
|
|
} |
4987
|
|
|
|
4988
|
|
|
if (!empty($last_insert_id) && ($last_insert_id != 0)) { |
4989
|
|
|
//we insert the relationship user-tag |
4990
|
|
|
$sql = "SELECT tag_id FROM $table_user_tag_values |
4991
|
|
|
WHERE user_id = $user_id AND tag_id = $last_insert_id "; |
4992
|
|
|
$result = Database::query($sql); |
4993
|
|
|
//if the relationship does not exist we create it |
4994
|
|
|
if (Database::num_rows($result) == 0) { |
4995
|
|
|
$sql = "INSERT INTO $table_user_tag_values SET user_id = $user_id, tag_id = $last_insert_id"; |
4996
|
|
|
Database::query($sql); |
4997
|
|
|
} |
4998
|
|
|
|
4999
|
|
|
return true; |
5000
|
|
|
} |
5001
|
|
|
|
5002
|
|
|
return false; |
5003
|
|
|
} |
5004
|
|
|
|
5005
|
|
|
/** |
5006
|
|
|
* Deletes an user tag. |
5007
|
|
|
* |
5008
|
|
|
* @param int $user_id |
5009
|
|
|
* @param int $field_id |
5010
|
|
|
*/ |
5011
|
|
|
public static function delete_user_tags($user_id, $field_id) |
5012
|
|
|
{ |
5013
|
|
|
// database table definition |
5014
|
|
|
$table_user_tag = Database::get_main_table(TABLE_MAIN_TAG); |
5015
|
|
|
$table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG); |
5016
|
|
|
$user_id = (int) $user_id; |
5017
|
|
|
|
5018
|
|
|
$tags = self::get_user_tags($user_id, $field_id); |
5019
|
|
|
if (is_array($tags) && count($tags) > 0) { |
5020
|
|
|
foreach ($tags as $key => $tag) { |
5021
|
|
|
if ($tag['count'] > '0') { |
5022
|
|
|
$sql = "UPDATE $table_user_tag SET count = count - 1 WHERE id = $key "; |
5023
|
|
|
Database::query($sql); |
5024
|
|
|
} |
5025
|
|
|
$sql = "DELETE FROM $table_user_tag_values |
5026
|
|
|
WHERE user_id = $user_id AND tag_id = $key"; |
5027
|
|
|
Database::query($sql); |
5028
|
|
|
} |
5029
|
|
|
} |
5030
|
|
|
} |
5031
|
|
|
|
5032
|
|
|
/** |
5033
|
|
|
* Process the tag list comes from the UserManager::update_extra_field_value() function. |
5034
|
|
|
* |
5035
|
|
|
* @param array $tags the tag list that will be added |
5036
|
|
|
* @param int $user_id |
5037
|
|
|
* @param int $field_id |
5038
|
|
|
* |
5039
|
|
|
* @return bool |
5040
|
|
|
*/ |
5041
|
|
|
public static function process_tags($tags, $user_id, $field_id) |
5042
|
|
|
{ |
5043
|
|
|
// We loop the tags and add it to the DB |
5044
|
|
|
if (is_array($tags)) { |
5045
|
|
|
foreach ($tags as $tag) { |
5046
|
|
|
self::add_tag($tag, $user_id, $field_id); |
5047
|
|
|
} |
5048
|
|
|
} else { |
5049
|
|
|
self::add_tag($tags, $user_id, $field_id); |
5050
|
|
|
} |
5051
|
|
|
|
5052
|
|
|
return true; |
5053
|
|
|
} |
5054
|
|
|
|
5055
|
|
|
/** |
5056
|
|
|
* Returns a list of all administrators. |
5057
|
|
|
* |
5058
|
|
|
* @return array |
5059
|
|
|
*/ |
5060
|
|
|
public static function get_all_administrators() |
5061
|
|
|
{ |
5062
|
|
|
$table_user = Database::get_main_table(TABLE_MAIN_USER); |
5063
|
|
|
$table_admin = Database::get_main_table(TABLE_MAIN_ADMIN); |
5064
|
|
|
$tbl_url_rel_user = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER); |
5065
|
|
|
$access_url_id = api_get_current_access_url_id(); |
5066
|
|
|
if (api_get_multiple_access_url()) { |
5067
|
|
|
$sql = "SELECT admin.user_id, username, firstname, lastname, email, active |
5068
|
|
|
FROM $tbl_url_rel_user as url |
5069
|
|
|
INNER JOIN $table_admin as admin |
5070
|
|
|
ON (admin.user_id=url.user_id) |
5071
|
|
|
INNER JOIN $table_user u |
5072
|
|
|
ON (u.id=admin.user_id) |
5073
|
|
|
WHERE access_url_id ='".$access_url_id."'"; |
5074
|
|
|
} else { |
5075
|
|
|
$sql = "SELECT admin.user_id, username, firstname, lastname, email, active |
5076
|
|
|
FROM $table_admin as admin |
5077
|
|
|
INNER JOIN $table_user u |
5078
|
|
|
ON (u.id=admin.user_id)"; |
5079
|
|
|
} |
5080
|
|
|
$result = Database::query($sql); |
5081
|
|
|
$return = []; |
5082
|
|
|
if (Database::num_rows($result) > 0) { |
5083
|
|
|
while ($row = Database::fetch_array($result, 'ASSOC')) { |
5084
|
|
|
$return[$row['user_id']] = $row; |
5085
|
|
|
} |
5086
|
|
|
} |
5087
|
|
|
|
5088
|
|
|
return $return; |
5089
|
|
|
} |
5090
|
|
|
|
5091
|
|
|
/** |
5092
|
|
|
* Search an user (tags, first name, last name and email ). |
5093
|
|
|
* |
5094
|
|
|
* @param string $tag |
5095
|
|
|
* @param int $field_id field id of the tag |
5096
|
|
|
* @param int $from where to start in the query |
5097
|
|
|
* @param int $number_of_items |
5098
|
|
|
* @param bool $getCount get count or not |
5099
|
|
|
* |
5100
|
|
|
* @return array |
5101
|
|
|
*/ |
5102
|
|
|
public static function get_all_user_tags( |
5103
|
|
|
$tag, |
5104
|
|
|
$field_id = 0, |
5105
|
|
|
$from = 0, |
5106
|
|
|
$number_of_items = 10, |
5107
|
|
|
$getCount = false |
5108
|
|
|
) { |
5109
|
|
|
$user_table = Database::get_main_table(TABLE_MAIN_USER); |
5110
|
|
|
$table_user_tag = Database::get_main_table(TABLE_MAIN_TAG); |
5111
|
|
|
$table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG); |
5112
|
|
|
$access_url_rel_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER); |
5113
|
|
|
|
5114
|
|
|
$field_id = intval($field_id); |
5115
|
|
|
$from = intval($from); |
5116
|
|
|
$number_of_items = intval($number_of_items); |
5117
|
|
|
|
5118
|
|
|
$where_field = ""; |
5119
|
|
|
$where_extra_fields = self::get_search_form_where_extra_fields(); |
5120
|
|
|
if ($field_id != 0) { |
5121
|
|
|
$where_field = " field_id = $field_id AND "; |
5122
|
|
|
} |
5123
|
|
|
|
5124
|
|
|
// all the information of the field |
5125
|
|
|
if ($getCount) { |
5126
|
|
|
$select = "SELECT count(DISTINCT u.id) count"; |
5127
|
|
|
} else { |
5128
|
|
|
$select = "SELECT DISTINCT u.id, u.username, firstname, lastname, email, picture_uri"; |
5129
|
|
|
} |
5130
|
|
|
|
5131
|
|
|
$sql = " $select |
5132
|
|
|
FROM $user_table u |
5133
|
|
|
INNER JOIN $access_url_rel_user_table url_rel_user |
5134
|
|
|
ON (u.id = url_rel_user.user_id) |
5135
|
|
|
LEFT JOIN $table_user_tag_values uv |
5136
|
|
|
ON (u.id AND uv.user_id AND uv.user_id = url_rel_user.user_id) |
5137
|
|
|
LEFT JOIN $table_user_tag ut ON (uv.tag_id = ut.id) |
5138
|
|
|
WHERE |
5139
|
|
|
($where_field tag LIKE '".Database::escape_string($tag."%")."') OR |
5140
|
|
|
( |
5141
|
|
|
u.firstname LIKE '".Database::escape_string("%".$tag."%")."' OR |
5142
|
|
|
u.lastname LIKE '".Database::escape_string("%".$tag."%")."' OR |
5143
|
|
|
u.username LIKE '".Database::escape_string("%".$tag."%")."' OR |
5144
|
|
|
concat(u.firstname, ' ', u.lastname) LIKE '".Database::escape_string("%".$tag."%")."' OR |
5145
|
|
|
concat(u.lastname, ' ', u.firstname) LIKE '".Database::escape_string("%".$tag."%")."' |
5146
|
|
|
) |
5147
|
|
|
".(!empty($where_extra_fields) ? $where_extra_fields : '')." |
5148
|
|
|
AND url_rel_user.access_url_id=".api_get_current_access_url_id(); |
5149
|
|
|
|
5150
|
|
|
$keyword_active = true; |
5151
|
|
|
// only active users |
5152
|
|
|
if ($keyword_active) { |
5153
|
|
|
$sql .= " AND u.active='1'"; |
5154
|
|
|
} |
5155
|
|
|
// avoid anonymous |
5156
|
|
|
$sql .= " AND u.status <> 6 "; |
5157
|
|
|
$sql .= " ORDER BY username"; |
5158
|
|
|
$sql .= " LIMIT $from , $number_of_items"; |
5159
|
|
|
|
5160
|
|
|
$result = Database::query($sql); |
5161
|
|
|
$return = []; |
5162
|
|
|
|
5163
|
|
|
if (Database::num_rows($result) > 0) { |
5164
|
|
|
if ($getCount) { |
5165
|
|
|
$row = Database::fetch_array($result, 'ASSOC'); |
5166
|
|
|
|
5167
|
|
|
return $row['count']; |
5168
|
|
|
} |
5169
|
|
|
while ($row = Database::fetch_array($result, 'ASSOC')) { |
5170
|
|
|
$return[$row['id']] = $row; |
5171
|
|
|
} |
5172
|
|
|
} |
5173
|
|
|
|
5174
|
|
|
return $return; |
5175
|
|
|
} |
5176
|
|
|
|
5177
|
|
|
/** |
5178
|
|
|
* Get extra filterable user fields (only type select). |
5179
|
|
|
* |
5180
|
|
|
* @return array Array of extra fields as [int => ['name' => ..., 'variable' => ..., 'data' => ...]] ( |
5181
|
|
|
* or empty array if no extra field) |
5182
|
|
|
*/ |
5183
|
|
|
public static function getExtraFilterableFields() |
5184
|
|
|
{ |
5185
|
|
|
$extraFieldList = self::get_extra_fields(); |
5186
|
|
|
$fields = []; |
5187
|
|
|
if (is_array($extraFieldList)) { |
5188
|
|
|
foreach ($extraFieldList as $extraField) { |
5189
|
|
|
// If is enabled to filter and is a "<select>" field type |
5190
|
|
|
if ($extraField[8] == 1 && $extraField[2] == 4) { |
5191
|
|
|
$fields[] = [ |
5192
|
|
|
'name' => $extraField[3], |
5193
|
|
|
'variable' => $extraField[1], |
5194
|
|
|
'data' => $extraField[9], |
5195
|
|
|
]; |
5196
|
|
|
} |
5197
|
|
|
} |
5198
|
|
|
} |
5199
|
|
|
|
5200
|
|
|
return $fields; |
5201
|
|
|
} |
5202
|
|
|
|
5203
|
|
|
/** |
5204
|
|
|
* Get extra where clauses for finding users based on extra filterable user fields (type select). |
5205
|
|
|
* |
5206
|
|
|
* @return string With AND clauses based on user's ID which have the values to search in extra user fields |
5207
|
|
|
* (or empty if no extra field exists) |
5208
|
|
|
*/ |
5209
|
|
|
public static function get_search_form_where_extra_fields() |
5210
|
|
|
{ |
5211
|
|
|
$useExtraFields = false; |
5212
|
|
|
$extraFields = self::getExtraFilterableFields(); |
5213
|
|
|
$extraFieldResult = []; |
5214
|
|
|
if (is_array($extraFields) && count($extraFields) > 0) { |
5215
|
|
|
foreach ($extraFields as $extraField) { |
5216
|
|
|
$varName = 'field_'.$extraField['variable']; |
5217
|
|
|
if (self::is_extra_field_available($extraField['variable'])) { |
5218
|
|
|
if (isset($_GET[$varName]) && $_GET[$varName] != '0') { |
5219
|
|
|
$useExtraFields = true; |
5220
|
|
|
$extraFieldResult[] = self::get_extra_user_data_by_value( |
5221
|
|
|
$extraField['variable'], |
5222
|
|
|
$_GET[$varName] |
5223
|
|
|
); |
5224
|
|
|
} |
5225
|
|
|
} |
5226
|
|
|
} |
5227
|
|
|
} |
5228
|
|
|
|
5229
|
|
|
if ($useExtraFields) { |
5230
|
|
|
$finalResult = []; |
5231
|
|
|
if (count($extraFieldResult) > 1) { |
5232
|
|
|
for ($i = 0; $i < count($extraFieldResult) - 1; $i++) { |
5233
|
|
|
if (is_array($extraFieldResult[$i]) && is_array($extraFieldResult[$i + 1])) { |
5234
|
|
|
$finalResult = array_intersect($extraFieldResult[$i], $extraFieldResult[$i + 1]); |
5235
|
|
|
} |
5236
|
|
|
} |
5237
|
|
|
} else { |
5238
|
|
|
$finalResult = $extraFieldResult[0]; |
5239
|
|
|
} |
5240
|
|
|
|
5241
|
|
|
if (is_array($finalResult) && count($finalResult) > 0) { |
5242
|
|
|
$whereFilter = " AND u.id IN ('".implode("','", $finalResult)."') "; |
5243
|
|
|
} else { |
5244
|
|
|
//no results |
5245
|
|
|
$whereFilter = " AND u.id = -1 "; |
5246
|
|
|
} |
5247
|
|
|
|
5248
|
|
|
return $whereFilter; |
5249
|
|
|
} |
5250
|
|
|
|
5251
|
|
|
return ''; |
5252
|
|
|
} |
5253
|
|
|
|
5254
|
|
|
/** |
5255
|
|
|
* Show the search form. |
5256
|
|
|
* |
5257
|
|
|
* @param string $query the value of the search box |
5258
|
|
|
* |
5259
|
|
|
* @throws Exception |
5260
|
|
|
* |
5261
|
|
|
* @return string HTML form |
5262
|
|
|
*/ |
5263
|
|
|
public static function get_search_form($query, $defaultParams = []) |
5264
|
|
|
{ |
5265
|
|
|
$searchType = isset($_GET['search_type']) ? $_GET['search_type'] : null; |
5266
|
|
|
$form = new FormValidator( |
5267
|
|
|
'search_user', |
5268
|
|
|
'get', |
5269
|
|
|
api_get_path(WEB_PATH).'main/social/search.php', |
5270
|
|
|
'', |
5271
|
|
|
[], |
5272
|
|
|
FormValidator::LAYOUT_HORIZONTAL |
5273
|
|
|
); |
5274
|
|
|
|
5275
|
|
|
$query = Security::remove_XSS($query); |
5276
|
|
|
|
5277
|
|
|
if (!empty($query)) { |
5278
|
|
|
$form->addHeader(get_lang('Results').' "'.$query.'"'); |
5279
|
|
|
} |
5280
|
|
|
|
5281
|
|
|
$form->addText( |
5282
|
|
|
'q', |
5283
|
|
|
get_lang('UsersGroups'), |
5284
|
|
|
false, |
5285
|
|
|
[ |
5286
|
|
|
'id' => 'q', |
5287
|
|
|
] |
5288
|
|
|
); |
5289
|
|
|
$options = [ |
5290
|
|
|
0 => get_lang('Select'), |
5291
|
|
|
1 => get_lang('User'), |
5292
|
|
|
2 => get_lang('Group'), |
5293
|
|
|
]; |
5294
|
|
|
$form->addSelect( |
5295
|
|
|
'search_type', |
5296
|
|
|
get_lang('Type'), |
5297
|
|
|
$options, |
5298
|
|
|
['onchange' => 'javascript: extra_field_toogle();', 'id' => 'search_type'] |
5299
|
|
|
); |
5300
|
|
|
|
5301
|
|
|
// Extra fields |
5302
|
|
|
$extraFields = self::getExtraFilterableFields(); |
5303
|
|
|
$defaults = []; |
5304
|
|
|
if (is_array($extraFields) && count($extraFields) > 0) { |
5305
|
|
|
foreach ($extraFields as $extraField) { |
5306
|
|
|
$varName = 'field_'.$extraField['variable']; |
5307
|
|
|
$options = [ |
5308
|
|
|
0 => get_lang('Select'), |
5309
|
|
|
]; |
5310
|
|
|
foreach ($extraField['data'] as $option) { |
5311
|
|
|
if (isset($_GET[$varName])) { |
5312
|
|
|
if ($_GET[$varName] == $option[1]) { |
5313
|
|
|
$defaults[$option[1]] = true; |
5314
|
|
|
} |
5315
|
|
|
} |
5316
|
|
|
|
5317
|
|
|
$options[$option[1]] = $option[1]; |
5318
|
|
|
} |
5319
|
|
|
$form->addSelect($varName, $extraField['name'], $options); |
5320
|
|
|
} |
5321
|
|
|
} |
5322
|
|
|
|
5323
|
|
|
$defaults['search_type'] = (int) $searchType; |
5324
|
|
|
$defaults['q'] = $query; |
5325
|
|
|
|
5326
|
|
|
if (!empty($defaultParams)) { |
5327
|
|
|
$defaults = array_merge($defaults, $defaultParams); |
5328
|
|
|
} |
5329
|
|
|
$form->setDefaults($defaults); |
5330
|
|
|
$form->addButtonSearch(get_lang('Search')); |
5331
|
|
|
|
5332
|
|
|
$js = '<script> |
5333
|
|
|
extra_field_toogle(); |
5334
|
|
|
function extra_field_toogle() { |
5335
|
|
|
if (jQuery("select[name=search_type]").val() != "1") { |
5336
|
|
|
jQuery(".extra_field").hide(); |
5337
|
|
|
} else { |
5338
|
|
|
jQuery(".extra_field").show(); |
5339
|
|
|
} |
5340
|
|
|
} |
5341
|
|
|
</script>'; |
5342
|
|
|
|
5343
|
|
|
return $js.$form->returnForm(); |
5344
|
|
|
} |
5345
|
|
|
|
5346
|
|
|
/** |
5347
|
|
|
* Shows the user menu. |
5348
|
|
|
*/ |
5349
|
|
|
public static function show_menu() |
5350
|
|
|
{ |
5351
|
|
|
echo '<div class="actions">'; |
5352
|
|
|
echo '<a href="/main/auth/profile.php">'. |
5353
|
|
|
Display::return_icon('profile.png').' '.get_lang('PersonalData').'</a>'; |
5354
|
|
|
echo '<a href="/main/messages/inbox.php">'. |
5355
|
|
|
Display::return_icon('inbox.png').' '.get_lang('Inbox').'</a>'; |
5356
|
|
|
echo '<a href="/main/messages/outbox.php">'. |
5357
|
|
|
Display::return_icon('outbox.png').' '.get_lang('Outbox').'</a>'; |
5358
|
|
|
echo '<span style="float:right; padding-top:7px;">'. |
5359
|
|
|
'<a href="/main/auth/profile.php?show=1">'. |
5360
|
|
|
Display::return_icon('edit.gif').' '.get_lang('Configuration').'</a>'; |
5361
|
|
|
echo '</span>'; |
5362
|
|
|
echo '</div>'; |
5363
|
|
|
} |
5364
|
|
|
|
5365
|
|
|
/** |
5366
|
|
|
* Allow to register contact to social network. |
5367
|
|
|
* |
5368
|
|
|
* @param int $friend_id user friend id |
5369
|
|
|
* @param int $my_user_id user id |
5370
|
|
|
* @param int $relation_type relation between users see constants definition |
5371
|
|
|
* |
5372
|
|
|
* @return bool |
5373
|
|
|
*/ |
5374
|
|
|
public static function relate_users($friend_id, $my_user_id, $relation_type) |
5375
|
|
|
{ |
5376
|
|
|
$tbl_my_friend = Database::get_main_table(TABLE_MAIN_USER_REL_USER); |
5377
|
|
|
|
5378
|
|
|
$friend_id = (int) $friend_id; |
5379
|
|
|
$my_user_id = (int) $my_user_id; |
5380
|
|
|
$relation_type = (int) $relation_type; |
5381
|
|
|
|
5382
|
|
|
$sql = 'SELECT COUNT(*) as count FROM '.$tbl_my_friend.' |
5383
|
|
|
WHERE |
5384
|
|
|
friend_user_id='.$friend_id.' AND |
5385
|
|
|
user_id='.$my_user_id.' AND |
5386
|
|
|
relation_type NOT IN('.USER_RELATION_TYPE_RRHH.', '.USER_RELATION_TYPE_BOSS.') '; |
5387
|
|
|
$result = Database::query($sql); |
5388
|
|
|
$row = Database::fetch_array($result, 'ASSOC'); |
5389
|
|
|
$current_date = api_get_utc_datetime(); |
5390
|
|
|
|
5391
|
|
|
if ($row['count'] == 0) { |
5392
|
|
|
$sql = 'INSERT INTO '.$tbl_my_friend.'(friend_user_id,user_id,relation_type,last_edit) |
5393
|
|
|
VALUES ('.$friend_id.','.$my_user_id.','.$relation_type.',"'.$current_date.'")'; |
5394
|
|
|
Database::query($sql); |
5395
|
|
|
|
5396
|
|
|
return true; |
5397
|
|
|
} |
5398
|
|
|
|
5399
|
|
|
$sql = 'SELECT COUNT(*) as count, relation_type FROM '.$tbl_my_friend.' |
5400
|
|
|
WHERE |
5401
|
|
|
friend_user_id='.$friend_id.' AND |
5402
|
|
|
user_id='.$my_user_id.' AND |
5403
|
|
|
relation_type NOT IN('.USER_RELATION_TYPE_RRHH.', '.USER_RELATION_TYPE_BOSS.') '; |
5404
|
|
|
$result = Database::query($sql); |
5405
|
|
|
$row = Database::fetch_array($result, 'ASSOC'); |
5406
|
|
|
|
5407
|
|
|
if ($row['count'] == 1) { |
5408
|
|
|
//only for the case of a RRHH or a Student BOSS |
5409
|
|
|
if ($row['relation_type'] != $relation_type && |
5410
|
|
|
($relation_type == USER_RELATION_TYPE_RRHH || $relation_type == USER_RELATION_TYPE_BOSS) |
5411
|
|
|
) { |
5412
|
|
|
$sql = 'INSERT INTO '.$tbl_my_friend.'(friend_user_id,user_id,relation_type,last_edit) |
5413
|
|
|
VALUES ('.$friend_id.','.$my_user_id.','.$relation_type.',"'.$current_date.'")'; |
5414
|
|
|
} else { |
5415
|
|
|
$sql = 'UPDATE '.$tbl_my_friend.' SET relation_type='.$relation_type.' |
5416
|
|
|
WHERE friend_user_id='.$friend_id.' AND user_id='.$my_user_id; |
5417
|
|
|
} |
5418
|
|
|
Database::query($sql); |
5419
|
|
|
|
5420
|
|
|
return true; |
5421
|
|
|
} |
5422
|
|
|
|
5423
|
|
|
return false; |
5424
|
|
|
} |
5425
|
|
|
|
5426
|
|
|
/** |
5427
|
|
|
* Deletes a contact. |
5428
|
|
|
* |
5429
|
|
|
* @param bool $friend_id |
5430
|
|
|
* @param bool $real_removed true will delete ALL friends relationship |
5431
|
|
|
* @param string $with_status_condition |
5432
|
|
|
* |
5433
|
|
|
* @author isaac flores paz <[email protected]> |
5434
|
|
|
* @author Julio Montoya <[email protected]> Cleaning code |
5435
|
|
|
*/ |
5436
|
|
|
public static function remove_user_rel_user( |
5437
|
|
|
$friend_id, |
5438
|
|
|
$real_removed = false, |
5439
|
|
|
$with_status_condition = '' |
5440
|
|
|
) { |
5441
|
|
|
$tbl_my_friend = Database::get_main_table(TABLE_MAIN_USER_REL_USER); |
5442
|
|
|
$tbl_my_message = Database::get_main_table(TABLE_MESSAGE); |
5443
|
|
|
$friend_id = (int) $friend_id; |
5444
|
|
|
$user_id = api_get_user_id(); |
5445
|
|
|
|
5446
|
|
|
if ($real_removed) { |
5447
|
|
|
$extra_condition = ''; |
5448
|
|
|
if ($with_status_condition != '') { |
5449
|
|
|
$extra_condition = ' AND relation_type = '.intval($with_status_condition); |
5450
|
|
|
} |
5451
|
|
|
$sql = 'DELETE FROM '.$tbl_my_friend.' |
5452
|
|
|
WHERE |
5453
|
|
|
relation_type <> '.USER_RELATION_TYPE_RRHH.' AND |
5454
|
|
|
friend_user_id='.$friend_id.' '.$extra_condition; |
5455
|
|
|
Database::query($sql); |
5456
|
|
|
$sql = 'DELETE FROM '.$tbl_my_friend.' |
5457
|
|
|
WHERE |
5458
|
|
|
relation_type <> '.USER_RELATION_TYPE_RRHH.' AND |
5459
|
|
|
user_id='.$friend_id.' '.$extra_condition; |
5460
|
|
|
Database::query($sql); |
5461
|
|
|
} else { |
5462
|
|
|
$sql = 'SELECT COUNT(*) as count FROM '.$tbl_my_friend.' |
5463
|
|
|
WHERE |
5464
|
|
|
user_id='.$user_id.' AND |
5465
|
|
|
relation_type NOT IN('.USER_RELATION_TYPE_DELETED.', '.USER_RELATION_TYPE_RRHH.') AND |
5466
|
|
|
friend_user_id='.$friend_id; |
5467
|
|
|
$result = Database::query($sql); |
5468
|
|
|
$row = Database::fetch_array($result, 'ASSOC'); |
5469
|
|
|
if ($row['count'] == 1) { |
5470
|
|
|
//Delete user rel user |
5471
|
|
|
$sql_i = 'UPDATE '.$tbl_my_friend.' SET relation_type='.USER_RELATION_TYPE_DELETED.' |
5472
|
|
|
WHERE user_id='.$user_id.' AND friend_user_id='.$friend_id; |
5473
|
|
|
|
5474
|
|
|
$sql_j = 'UPDATE '.$tbl_my_message.' SET msg_status='.MESSAGE_STATUS_INVITATION_DENIED.' |
5475
|
|
|
WHERE |
5476
|
|
|
user_receiver_id='.$user_id.' AND |
5477
|
|
|
user_sender_id='.$friend_id.' AND update_date="0000-00-00 00:00:00" '; |
5478
|
|
|
// Delete user |
5479
|
|
|
$sql_ij = 'UPDATE '.$tbl_my_friend.' SET relation_type='.USER_RELATION_TYPE_DELETED.' |
5480
|
|
|
WHERE user_id='.$friend_id.' AND friend_user_id='.$user_id; |
5481
|
|
|
$sql_ji = 'UPDATE '.$tbl_my_message.' SET msg_status='.MESSAGE_STATUS_INVITATION_DENIED.' |
5482
|
|
|
WHERE |
5483
|
|
|
user_receiver_id='.$friend_id.' AND |
5484
|
|
|
user_sender_id='.$user_id.' AND |
5485
|
|
|
update_date="0000-00-00 00:00:00" '; |
5486
|
|
|
Database::query($sql_i); |
5487
|
|
|
Database::query($sql_j); |
5488
|
|
|
Database::query($sql_ij); |
5489
|
|
|
Database::query($sql_ji); |
5490
|
|
|
} |
5491
|
|
|
} |
5492
|
|
|
|
5493
|
|
|
// Delete accepted invitations |
5494
|
|
|
$sql = "DELETE FROM $tbl_my_message |
5495
|
|
|
WHERE |
5496
|
|
|
msg_status = ".MESSAGE_STATUS_INVITATION_ACCEPTED." AND |
5497
|
|
|
( |
5498
|
|
|
user_receiver_id = $user_id AND |
5499
|
|
|
user_sender_id = $friend_id |
5500
|
|
|
) OR |
5501
|
|
|
( |
5502
|
|
|
user_sender_id = $user_id AND |
5503
|
|
|
user_receiver_id = $friend_id |
5504
|
|
|
) |
5505
|
|
|
"; |
5506
|
|
|
Database::query($sql); |
5507
|
|
|
} |
5508
|
|
|
|
5509
|
|
|
/** |
5510
|
|
|
* @param int $userId |
5511
|
|
|
* |
5512
|
|
|
* @return array |
5513
|
|
|
*/ |
5514
|
|
|
public static function getDrhListFromUser($userId) |
5515
|
|
|
{ |
5516
|
|
|
$tblUser = Database::get_main_table(TABLE_MAIN_USER); |
5517
|
|
|
$tblUserRelUser = Database::get_main_table(TABLE_MAIN_USER_REL_USER); |
5518
|
|
|
$tblUserRelAccessUrl = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER); |
5519
|
|
|
$userId = (int) $userId; |
5520
|
|
|
|
5521
|
|
|
$orderBy = null; |
5522
|
|
|
if (api_is_western_name_order()) { |
5523
|
|
|
$orderBy .= ' ORDER BY firstname, lastname '; |
5524
|
|
|
} else { |
5525
|
|
|
$orderBy .= ' ORDER BY lastname, firstname '; |
5526
|
|
|
} |
5527
|
|
|
|
5528
|
|
|
$sql = "SELECT u.id, username, u.firstname, u.lastname |
5529
|
|
|
FROM $tblUser u |
5530
|
|
|
INNER JOIN $tblUserRelUser uru ON (uru.friend_user_id = u.id) |
5531
|
|
|
INNER JOIN $tblUserRelAccessUrl a ON (a.user_id = u.id) |
5532
|
|
|
WHERE |
5533
|
|
|
access_url_id = ".api_get_current_access_url_id()." AND |
5534
|
|
|
uru.user_id = '$userId' AND |
5535
|
|
|
relation_type = '".USER_RELATION_TYPE_RRHH."' |
5536
|
|
|
$orderBy |
5537
|
|
|
"; |
5538
|
|
|
$result = Database::query($sql); |
5539
|
|
|
|
5540
|
|
|
return Database::store_result($result); |
5541
|
|
|
} |
5542
|
|
|
|
5543
|
|
|
/** |
5544
|
|
|
* get users followed by human resource manager. |
5545
|
|
|
* |
5546
|
|
|
* @param int $userId |
5547
|
|
|
* @param int $userStatus (STUDENT, COURSEMANAGER, etc) |
5548
|
|
|
* @param bool $getOnlyUserId |
5549
|
|
|
* @param bool $getSql |
5550
|
|
|
* @param bool $getCount |
5551
|
|
|
* @param int $from |
5552
|
|
|
* @param int $numberItems |
5553
|
|
|
* @param int $column |
5554
|
|
|
* @param string $direction |
5555
|
|
|
* @param int $active |
5556
|
|
|
* @param string $lastConnectionDate |
5557
|
|
|
* |
5558
|
|
|
* @return array users |
5559
|
|
|
*/ |
5560
|
|
|
public static function get_users_followed_by_drh( |
5561
|
|
|
$userId, |
5562
|
|
|
$userStatus = 0, |
5563
|
|
|
$getOnlyUserId = false, |
5564
|
|
|
$getSql = false, |
5565
|
|
|
$getCount = false, |
5566
|
|
|
$from = null, |
5567
|
|
|
$numberItems = null, |
5568
|
|
|
$column = null, |
5569
|
|
|
$direction = null, |
5570
|
|
|
$active = null, |
5571
|
|
|
$lastConnectionDate = null |
5572
|
|
|
) { |
5573
|
|
|
return self::getUsersFollowedByUser( |
|
|
|
|
5574
|
|
|
$userId, |
5575
|
|
|
$userStatus, |
5576
|
|
|
$getOnlyUserId, |
5577
|
|
|
$getSql, |
5578
|
|
|
$getCount, |
5579
|
|
|
$from, |
5580
|
|
|
$numberItems, |
5581
|
|
|
$column, |
5582
|
|
|
$direction, |
5583
|
|
|
$active, |
5584
|
|
|
$lastConnectionDate, |
5585
|
|
|
DRH |
5586
|
|
|
); |
5587
|
|
|
} |
5588
|
|
|
|
5589
|
|
|
/** |
5590
|
|
|
* Get users followed by human resource manager. |
5591
|
|
|
* |
5592
|
|
|
* @param int $userId |
5593
|
|
|
* @param int $userStatus Filter users by status (STUDENT, COURSEMANAGER, etc) |
5594
|
|
|
* @param bool $getOnlyUserId |
5595
|
|
|
* @param bool $getSql |
5596
|
|
|
* @param bool $getCount |
5597
|
|
|
* @param int $from |
5598
|
|
|
* @param int $numberItems |
5599
|
|
|
* @param int $column |
5600
|
|
|
* @param string $direction |
5601
|
|
|
* @param int $active |
5602
|
|
|
* @param string $lastConnectionDate |
5603
|
|
|
* @param int $status the function is called by who? COURSEMANAGER, DRH? |
5604
|
|
|
* @param string $keyword |
5605
|
|
|
* @param bool $checkSessionVisibility |
5606
|
|
|
* |
5607
|
|
|
* @return mixed Users list (array) or the SQL query if $getSQL was set to true |
5608
|
|
|
*/ |
5609
|
|
|
public static function getUsersFollowedByUser( |
5610
|
|
|
$userId, |
5611
|
|
|
$userStatus = null, |
5612
|
|
|
$getOnlyUserId = false, |
5613
|
|
|
$getSql = false, |
5614
|
|
|
$getCount = false, |
5615
|
|
|
$from = null, |
5616
|
|
|
$numberItems = null, |
5617
|
|
|
$column = null, |
5618
|
|
|
$direction = null, |
5619
|
|
|
$active = null, |
5620
|
|
|
$lastConnectionDate = null, |
5621
|
|
|
$status = null, |
5622
|
|
|
$keyword = null, |
5623
|
|
|
$checkSessionVisibility = false, |
5624
|
|
|
$filterUsers = null |
5625
|
|
|
) { |
5626
|
|
|
// Database Table Definitions |
5627
|
|
|
$tbl_user = Database::get_main_table(TABLE_MAIN_USER); |
5628
|
|
|
$tbl_user_rel_user = Database::get_main_table(TABLE_MAIN_USER_REL_USER); |
5629
|
|
|
$tbl_user_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER); |
5630
|
|
|
$tbl_session = Database::get_main_table(TABLE_MAIN_SESSION); |
5631
|
|
|
$tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER); |
5632
|
|
|
$tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER); |
5633
|
|
|
$tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION); |
5634
|
|
|
$tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER); |
5635
|
|
|
|
5636
|
|
|
$userId = (int) $userId; |
5637
|
|
|
$limitCondition = ''; |
5638
|
|
|
|
5639
|
|
|
if (isset($from) && isset($numberItems)) { |
5640
|
|
|
$from = (int) $from; |
5641
|
|
|
$numberItems = (int) $numberItems; |
5642
|
|
|
$limitCondition = "LIMIT $from, $numberItems"; |
5643
|
|
|
} |
5644
|
|
|
|
5645
|
|
|
$column = Database::escape_string($column); |
5646
|
|
|
$direction = in_array(strtolower($direction), ['asc', 'desc']) ? $direction : null; |
5647
|
|
|
|
5648
|
|
|
$userConditions = ''; |
5649
|
|
|
if (!empty($userStatus)) { |
5650
|
|
|
$userConditions .= ' AND u.status = '.intval($userStatus); |
5651
|
|
|
} |
5652
|
|
|
|
5653
|
|
|
$select = " SELECT DISTINCT u.id user_id, u.username, u.lastname, u.firstname, u.email "; |
5654
|
|
|
if ($getOnlyUserId) { |
5655
|
|
|
$select = " SELECT DISTINCT u.id user_id"; |
5656
|
|
|
} |
5657
|
|
|
|
5658
|
|
|
$masterSelect = "SELECT DISTINCT * FROM "; |
5659
|
|
|
|
5660
|
|
|
if ($getCount) { |
5661
|
|
|
$masterSelect = "SELECT COUNT(DISTINCT(user_id)) as count FROM "; |
5662
|
|
|
$select = " SELECT DISTINCT(u.id) user_id"; |
5663
|
|
|
} |
5664
|
|
|
|
5665
|
|
|
if (!is_null($active)) { |
5666
|
|
|
$active = intval($active); |
5667
|
|
|
$userConditions .= " AND u.active = $active "; |
5668
|
|
|
} |
5669
|
|
|
|
5670
|
|
|
if (!empty($keyword)) { |
5671
|
|
|
$keyword = trim(Database::escape_string($keyword)); |
5672
|
|
|
$keywordParts = array_filter(explode(' ', $keyword)); |
5673
|
|
|
$extraKeyword = ''; |
5674
|
|
|
if (!empty($keywordParts)) { |
5675
|
|
|
$keywordPartsFixed = Database::escape_string(implode('%', $keywordParts)); |
5676
|
|
|
if (!empty($keywordPartsFixed)) { |
5677
|
|
|
$extraKeyword .= " OR |
5678
|
|
|
CONCAT(u.firstname, ' ', u.lastname) LIKE '%$keywordPartsFixed%' OR |
5679
|
|
|
CONCAT(u.lastname, ' ', u.firstname) LIKE '%$keywordPartsFixed%' "; |
5680
|
|
|
} |
5681
|
|
|
} |
5682
|
|
|
|
5683
|
|
|
$userConditions .= " AND ( |
5684
|
|
|
u.username LIKE '%$keyword%' OR |
5685
|
|
|
u.firstname LIKE '%$keyword%' OR |
5686
|
|
|
u.lastname LIKE '%$keyword%' OR |
5687
|
|
|
u.official_code LIKE '%$keyword%' OR |
5688
|
|
|
u.email LIKE '%$keyword%' OR |
5689
|
|
|
CONCAT(u.firstname, ' ', u.lastname) LIKE '%$keyword%' OR |
5690
|
|
|
CONCAT(u.lastname, ' ', u.firstname) LIKE '%$keyword%' |
5691
|
|
|
$extraKeyword |
5692
|
|
|
)"; |
5693
|
|
|
} |
5694
|
|
|
|
5695
|
|
|
if (!empty($lastConnectionDate)) { |
5696
|
|
|
$lastConnectionDate = Database::escape_string($lastConnectionDate); |
5697
|
|
|
$userConditions .= " AND u.last_login <= '$lastConnectionDate' "; |
5698
|
|
|
} |
5699
|
|
|
|
5700
|
|
|
if (!empty($filterUsers)) { |
5701
|
|
|
$userConditions .= " AND u.id IN(".implode(',', $filterUsers).")"; |
5702
|
|
|
} |
5703
|
|
|
|
5704
|
|
|
$sessionConditionsCoach = null; |
5705
|
|
|
$dateCondition = ''; |
5706
|
|
|
$drhConditions = null; |
5707
|
|
|
$teacherSelect = null; |
5708
|
|
|
|
5709
|
|
|
$urlId = api_get_current_access_url_id(); |
5710
|
|
|
|
5711
|
|
|
switch ($status) { |
5712
|
|
|
case DRH: |
5713
|
|
|
$drhConditions .= " AND |
5714
|
|
|
friend_user_id = '$userId' AND |
5715
|
|
|
relation_type = '".USER_RELATION_TYPE_RRHH."' |
5716
|
|
|
"; |
5717
|
|
|
break; |
5718
|
|
|
case COURSEMANAGER: |
5719
|
|
|
$drhConditions .= " AND |
5720
|
|
|
friend_user_id = '$userId' AND |
5721
|
|
|
relation_type = '".USER_RELATION_TYPE_RRHH."' |
5722
|
|
|
"; |
5723
|
|
|
|
5724
|
|
|
$sessionConditionsCoach .= " AND |
5725
|
|
|
(s.id_coach = '$userId') |
5726
|
|
|
"; |
5727
|
|
|
|
5728
|
|
|
$sessionConditionsTeacher = " AND |
5729
|
|
|
(scu.status = 2 AND scu.user_id = '$userId') |
5730
|
|
|
"; |
5731
|
|
|
|
5732
|
|
|
if ($checkSessionVisibility) { |
5733
|
|
|
$today = api_strtotime('now', 'UTC'); |
5734
|
|
|
$today = date('Y-m-d', $today); |
5735
|
|
|
$dateCondition = " |
5736
|
|
|
AND |
5737
|
|
|
( |
5738
|
|
|
(s.access_start_date <= '$today' AND '$today' <= s.access_end_date) OR |
5739
|
|
|
(s.access_start_date IS NULL AND s.access_end_date IS NULL) OR |
5740
|
|
|
(s.access_start_date <= '$today' AND s.access_end_date IS NULL) OR |
5741
|
|
|
('$today' <= s.access_end_date AND s.access_start_date IS NULL) |
5742
|
|
|
) |
5743
|
|
|
"; |
5744
|
|
|
} |
5745
|
|
|
|
5746
|
|
|
// Use $tbl_session_rel_course_rel_user instead of $tbl_session_rel_user |
5747
|
|
|
/* |
5748
|
|
|
INNER JOIN $tbl_session_rel_user sru |
5749
|
|
|
ON (sru.user_id = u.id) |
5750
|
|
|
INNER JOIN $tbl_session_rel_course_rel_user scu |
5751
|
|
|
ON (scu.user_id = u.id AND scu.c_id IS NOT NULL AND visibility = 1)*/ |
5752
|
|
|
$teacherSelect = |
5753
|
|
|
"UNION ALL ( |
5754
|
|
|
$select |
5755
|
|
|
FROM $tbl_user u |
5756
|
|
|
INNER JOIN $tbl_session_rel_user sru ON (sru.user_id = u.id) |
5757
|
|
|
WHERE |
5758
|
|
|
( |
5759
|
|
|
sru.session_id IN ( |
5760
|
|
|
SELECT DISTINCT(s.id) FROM $tbl_session s INNER JOIN |
5761
|
|
|
$tbl_session_rel_access_url session_rel_access_rel_user |
5762
|
|
|
ON session_rel_access_rel_user.session_id = s.id |
5763
|
|
|
WHERE access_url_id = ".$urlId." |
5764
|
|
|
$sessionConditionsCoach |
5765
|
|
|
) OR sru.session_id IN ( |
5766
|
|
|
SELECT DISTINCT(s.id) FROM $tbl_session s |
5767
|
|
|
INNER JOIN $tbl_session_rel_access_url url |
5768
|
|
|
ON (url.session_id = s.id) |
5769
|
|
|
INNER JOIN $tbl_session_rel_course_rel_user scu |
5770
|
|
|
ON (scu.session_id = s.id) |
5771
|
|
|
WHERE access_url_id = ".$urlId." |
5772
|
|
|
$sessionConditionsTeacher |
5773
|
|
|
$dateCondition |
5774
|
|
|
) |
5775
|
|
|
) |
5776
|
|
|
$userConditions |
5777
|
|
|
) |
5778
|
|
|
UNION ALL( |
5779
|
|
|
$select |
5780
|
|
|
FROM $tbl_user u |
5781
|
|
|
INNER JOIN $tbl_course_user cu ON (cu.user_id = u.id) |
5782
|
|
|
WHERE cu.c_id IN ( |
5783
|
|
|
SELECT DISTINCT(c_id) FROM $tbl_course_user |
5784
|
|
|
WHERE user_id = $userId AND status = ".COURSEMANAGER." |
5785
|
|
|
) |
5786
|
|
|
$userConditions |
5787
|
|
|
)" |
5788
|
|
|
; |
5789
|
|
|
break; |
5790
|
|
|
case STUDENT_BOSS: |
5791
|
|
|
$drhConditions = " AND friend_user_id = $userId AND relation_type = ".USER_RELATION_TYPE_BOSS; |
5792
|
|
|
break; |
5793
|
|
|
case HRM_REQUEST: |
5794
|
|
|
$drhConditions .= " AND |
5795
|
|
|
friend_user_id = '$userId' AND |
5796
|
|
|
relation_type = '".USER_RELATION_TYPE_HRM_REQUEST."' |
5797
|
|
|
"; |
5798
|
|
|
break; |
5799
|
|
|
} |
5800
|
|
|
|
5801
|
|
|
$join = null; |
5802
|
|
|
$sql = " $masterSelect |
5803
|
|
|
( |
5804
|
|
|
( |
5805
|
|
|
$select |
5806
|
|
|
FROM $tbl_user u |
5807
|
|
|
INNER JOIN $tbl_user_rel_user uru ON (uru.user_id = u.id) |
5808
|
|
|
LEFT JOIN $tbl_user_rel_access_url a ON (a.user_id = u.id) |
5809
|
|
|
$join |
5810
|
|
|
WHERE |
5811
|
|
|
access_url_id = ".$urlId." |
5812
|
|
|
$drhConditions |
5813
|
|
|
$userConditions |
5814
|
|
|
) |
5815
|
|
|
$teacherSelect |
5816
|
|
|
) as t1"; |
5817
|
|
|
|
5818
|
|
|
if ($getSql) { |
5819
|
|
|
return $sql; |
5820
|
|
|
} |
5821
|
|
|
|
5822
|
|
|
if ($getCount) { |
5823
|
|
|
$result = Database::query($sql); |
5824
|
|
|
$row = Database::fetch_array($result); |
5825
|
|
|
|
5826
|
|
|
return $row['count']; |
5827
|
|
|
} |
5828
|
|
|
|
5829
|
|
|
$orderBy = null; |
5830
|
|
|
if ($getOnlyUserId == false) { |
|
|
|
|
5831
|
|
|
if (api_is_western_name_order()) { |
5832
|
|
|
$orderBy .= " ORDER BY firstname, lastname "; |
5833
|
|
|
} else { |
5834
|
|
|
$orderBy .= " ORDER BY lastname, firstname "; |
5835
|
|
|
} |
5836
|
|
|
|
5837
|
|
|
if (!empty($column) && !empty($direction)) { |
5838
|
|
|
// Fixing order due the UNIONs |
5839
|
|
|
$column = str_replace('u.', '', $column); |
5840
|
|
|
$column = trim($column); |
5841
|
|
|
$orderBy = " ORDER BY `$column` $direction "; |
5842
|
|
|
} |
5843
|
|
|
} |
5844
|
|
|
|
5845
|
|
|
$sql .= $orderBy; |
5846
|
|
|
$sql .= $limitCondition; |
5847
|
|
|
|
5848
|
|
|
$result = Database::query($sql); |
5849
|
|
|
$users = []; |
5850
|
|
|
if (Database::num_rows($result) > 0) { |
5851
|
|
|
while ($row = Database::fetch_array($result)) { |
5852
|
|
|
$users[$row['user_id']] = $row; |
5853
|
|
|
} |
5854
|
|
|
} |
5855
|
|
|
|
5856
|
|
|
return $users; |
5857
|
|
|
} |
5858
|
|
|
|
5859
|
|
|
/** |
5860
|
|
|
* Subscribes users to human resource manager (Dashboard feature). |
5861
|
|
|
* |
5862
|
|
|
* @param int $hr_dept_id |
5863
|
|
|
* @param array $users_id |
5864
|
|
|
* @param bool $deleteOtherAssignedUsers |
5865
|
|
|
* |
5866
|
|
|
* @return int |
5867
|
|
|
*/ |
5868
|
|
|
public static function subscribeUsersToHRManager( |
5869
|
|
|
$hr_dept_id, |
5870
|
|
|
$users_id, |
5871
|
|
|
$deleteOtherAssignedUsers = true |
5872
|
|
|
) { |
5873
|
|
|
return self::subscribeUsersToUser( |
5874
|
|
|
$hr_dept_id, |
5875
|
|
|
$users_id, |
5876
|
|
|
USER_RELATION_TYPE_RRHH, |
5877
|
|
|
false, |
5878
|
|
|
$deleteOtherAssignedUsers |
5879
|
|
|
); |
5880
|
|
|
} |
5881
|
|
|
|
5882
|
|
|
/** |
5883
|
|
|
* Register request to assign users to HRM. |
5884
|
|
|
* |
5885
|
|
|
* @param int $hrmId The HRM ID |
5886
|
|
|
* @param array $usersId The users IDs |
5887
|
|
|
* |
5888
|
|
|
* @return int |
5889
|
|
|
*/ |
5890
|
|
|
public static function requestUsersToHRManager($hrmId, $usersId) |
5891
|
|
|
{ |
5892
|
|
|
return self::subscribeUsersToUser( |
5893
|
|
|
$hrmId, |
5894
|
|
|
$usersId, |
5895
|
|
|
USER_RELATION_TYPE_HRM_REQUEST, |
5896
|
|
|
false, |
5897
|
|
|
false |
5898
|
|
|
); |
5899
|
|
|
} |
5900
|
|
|
|
5901
|
|
|
/** |
5902
|
|
|
* Remove the requests for assign a user to a HRM. |
5903
|
|
|
* |
5904
|
|
|
* @param array $usersId List of user IDs from whom to remove all relations requests with HRM |
5905
|
|
|
*/ |
5906
|
|
|
public static function clearHrmRequestsForUser(User $hrmId, $usersId) |
5907
|
|
|
{ |
5908
|
|
|
$users = implode(', ', $usersId); |
5909
|
|
|
Database::getManager() |
5910
|
|
|
->createQuery(' |
5911
|
|
|
DELETE FROM ChamiloCoreBundle:UserRelUser uru |
5912
|
|
|
WHERE uru.friendUserId = :hrm_id AND uru.relationType = :relation_type AND uru.userId IN (:users_ids) |
5913
|
|
|
') |
5914
|
|
|
->execute(['hrm_id' => $hrmId, 'relation_type' => USER_RELATION_TYPE_HRM_REQUEST, 'users_ids' => $users]); |
5915
|
|
|
} |
5916
|
|
|
|
5917
|
|
|
/** |
5918
|
|
|
* Add subscribed users to a user by relation type. |
5919
|
|
|
* |
5920
|
|
|
* @param int $userId The user id |
5921
|
|
|
* @param array $subscribedUsersId The id of subscribed users |
5922
|
|
|
* @param string $relationType The relation type |
5923
|
|
|
* @param bool $deleteUsersBeforeInsert |
5924
|
|
|
* @param bool $deleteOtherAssignedUsers |
5925
|
|
|
* |
5926
|
|
|
* @return int |
5927
|
|
|
*/ |
5928
|
|
|
public static function subscribeUsersToUser( |
5929
|
|
|
$userId, |
5930
|
|
|
$subscribedUsersId, |
5931
|
|
|
$relationType, |
5932
|
|
|
$deleteUsersBeforeInsert = false, |
5933
|
|
|
$deleteOtherAssignedUsers = true |
5934
|
|
|
) { |
5935
|
|
|
$userRelUserTable = Database::get_main_table(TABLE_MAIN_USER_REL_USER); |
5936
|
|
|
$userRelAccessUrlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER); |
5937
|
|
|
|
5938
|
|
|
$userId = (int) $userId; |
5939
|
|
|
$relationType = (int) $relationType; |
5940
|
|
|
$affectedRows = 0; |
5941
|
|
|
|
5942
|
|
|
if ($deleteOtherAssignedUsers) { |
5943
|
|
|
if (api_get_multiple_access_url()) { |
5944
|
|
|
// Deleting assigned users to hrm_id |
5945
|
|
|
$sql = "SELECT s.user_id |
5946
|
|
|
FROM $userRelUserTable s |
5947
|
|
|
INNER JOIN $userRelAccessUrlTable a |
5948
|
|
|
ON (a.user_id = s.user_id) |
5949
|
|
|
WHERE |
5950
|
|
|
friend_user_id = $userId AND |
5951
|
|
|
relation_type = $relationType AND |
5952
|
|
|
access_url_id = ".api_get_current_access_url_id(); |
5953
|
|
|
} else { |
5954
|
|
|
$sql = "SELECT user_id |
5955
|
|
|
FROM $userRelUserTable |
5956
|
|
|
WHERE |
5957
|
|
|
friend_user_id = $userId AND |
5958
|
|
|
relation_type = $relationType"; |
5959
|
|
|
} |
5960
|
|
|
$result = Database::query($sql); |
5961
|
|
|
|
5962
|
|
|
if (Database::num_rows($result) > 0) { |
5963
|
|
|
while ($row = Database::fetch_array($result)) { |
5964
|
|
|
$sql = "DELETE FROM $userRelUserTable |
5965
|
|
|
WHERE |
5966
|
|
|
user_id = {$row['user_id']} AND |
5967
|
|
|
friend_user_id = $userId AND |
5968
|
|
|
relation_type = $relationType"; |
5969
|
|
|
Database::query($sql); |
5970
|
|
|
} |
5971
|
|
|
} |
5972
|
|
|
} |
5973
|
|
|
|
5974
|
|
|
if ($deleteUsersBeforeInsert) { |
5975
|
|
|
$sql = "DELETE FROM $userRelUserTable |
5976
|
|
|
WHERE |
5977
|
|
|
user_id = $userId AND |
5978
|
|
|
relation_type = $relationType"; |
5979
|
|
|
Database::query($sql); |
5980
|
|
|
} |
5981
|
|
|
|
5982
|
|
|
// Inserting new user list |
5983
|
|
|
if (is_array($subscribedUsersId)) { |
5984
|
|
|
foreach ($subscribedUsersId as $subscribedUserId) { |
5985
|
|
|
$subscribedUserId = (int) $subscribedUserId; |
5986
|
|
|
$sql = "SELECT id |
5987
|
|
|
FROM $userRelUserTable |
5988
|
|
|
WHERE |
5989
|
|
|
user_id = $subscribedUserId AND |
5990
|
|
|
friend_user_id = $userId AND |
5991
|
|
|
relation_type = $relationType"; |
5992
|
|
|
|
5993
|
|
|
$result = Database::query($sql); |
5994
|
|
|
$num = Database::num_rows($result); |
5995
|
|
|
if ($num === 0) { |
5996
|
|
|
$date = api_get_utc_datetime(); |
5997
|
|
|
$sql = "INSERT INTO $userRelUserTable (user_id, friend_user_id, relation_type, last_edit) |
5998
|
|
|
VALUES ($subscribedUserId, $userId, $relationType, '$date')"; |
5999
|
|
|
$result = Database::query($sql); |
6000
|
|
|
$affectedRows += Database::affected_rows($result); |
6001
|
|
|
} |
6002
|
|
|
} |
6003
|
|
|
} |
6004
|
|
|
|
6005
|
|
|
return $affectedRows; |
6006
|
|
|
} |
6007
|
|
|
|
6008
|
|
|
/** |
6009
|
|
|
* This function check if an user is followed by human resources manager. |
6010
|
|
|
* |
6011
|
|
|
* @param int $user_id |
6012
|
|
|
* @param int $hr_dept_id Human resources manager |
6013
|
|
|
* |
6014
|
|
|
* @return bool |
6015
|
|
|
*/ |
6016
|
|
|
public static function is_user_followed_by_drh($user_id, $hr_dept_id) |
6017
|
|
|
{ |
6018
|
|
|
$tbl_user_rel_user = Database::get_main_table(TABLE_MAIN_USER_REL_USER); |
6019
|
|
|
$user_id = (int) $user_id; |
6020
|
|
|
$hr_dept_id = (int) $hr_dept_id; |
6021
|
|
|
$result = false; |
6022
|
|
|
|
6023
|
|
|
$sql = "SELECT user_id FROM $tbl_user_rel_user |
6024
|
|
|
WHERE |
6025
|
|
|
user_id = $user_id AND |
6026
|
|
|
friend_user_id = $hr_dept_id AND |
6027
|
|
|
relation_type = ".USER_RELATION_TYPE_RRHH; |
6028
|
|
|
$rs = Database::query($sql); |
6029
|
|
|
if (Database::num_rows($rs) > 0) { |
6030
|
|
|
$result = true; |
6031
|
|
|
} |
6032
|
|
|
|
6033
|
|
|
return $result; |
6034
|
|
|
} |
6035
|
|
|
|
6036
|
|
|
/** |
6037
|
|
|
* Return the user id of teacher or session administrator. |
6038
|
|
|
* |
6039
|
|
|
* @return int|bool The user id, or false if the session ID was negative |
6040
|
|
|
*/ |
6041
|
|
|
public static function get_user_id_of_course_admin_or_session_admin(array $courseInfo) |
6042
|
|
|
{ |
6043
|
|
|
$session = api_get_session_id(); |
6044
|
|
|
$table_user = Database::get_main_table(TABLE_MAIN_USER); |
6045
|
|
|
$table_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER); |
6046
|
|
|
$table_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER); |
6047
|
|
|
|
6048
|
|
|
if (empty($courseInfo)) { |
6049
|
|
|
return false; |
6050
|
|
|
} |
6051
|
|
|
|
6052
|
|
|
$courseId = $courseInfo['real_id']; |
6053
|
|
|
|
6054
|
|
|
if (empty($session)) { |
6055
|
|
|
$sql = 'SELECT u.id uid FROM '.$table_user.' u |
6056
|
|
|
INNER JOIN '.$table_course_user.' ru |
6057
|
|
|
ON ru.user_id = u.id |
6058
|
|
|
WHERE |
6059
|
|
|
ru.status = '.COURSEMANAGER.' AND |
6060
|
|
|
ru.c_id = "'.$courseId.'" '; |
6061
|
|
|
} else { |
6062
|
|
|
$sql = 'SELECT u.id uid FROM '.$table_user.' u |
6063
|
|
|
INNER JOIN '.$table_session_course_user.' sru |
6064
|
|
|
ON sru.user_id=u.id |
6065
|
|
|
WHERE |
6066
|
|
|
sru.c_id="'.$courseId.'" AND |
6067
|
|
|
sru.session_id="'.$session.'" AND |
6068
|
|
|
sru.status = '.SessionEntity::COACH; |
6069
|
|
|
} |
6070
|
|
|
|
6071
|
|
|
$rs = Database::query($sql); |
6072
|
|
|
$num_rows = Database::num_rows($rs); |
6073
|
|
|
|
6074
|
|
|
if (0 === $num_rows) { |
6075
|
|
|
return false; |
6076
|
|
|
} |
6077
|
|
|
|
6078
|
|
|
if (1 === $num_rows) { |
6079
|
|
|
$row = Database::fetch_array($rs); |
6080
|
|
|
|
6081
|
|
|
return (int) $row['uid']; |
6082
|
|
|
} |
6083
|
|
|
|
6084
|
|
|
$my_num_rows = $num_rows; |
6085
|
|
|
$my_user_id = Database::result($rs, $my_num_rows - 1, 'uid'); |
6086
|
|
|
|
6087
|
|
|
return (int) $my_user_id; |
6088
|
|
|
} |
6089
|
|
|
|
6090
|
|
|
/** |
6091
|
|
|
* Determines if a user is a gradebook certified. |
6092
|
|
|
* |
6093
|
|
|
* @param int $cat_id The category id of gradebook |
6094
|
|
|
* @param int $user_id The user id |
6095
|
|
|
* |
6096
|
|
|
* @return bool |
6097
|
|
|
*/ |
6098
|
|
|
public static function is_user_certified($cat_id, $user_id) |
6099
|
|
|
{ |
6100
|
|
|
$cat_id = (int) $cat_id; |
6101
|
|
|
$user_id = (int) $user_id; |
6102
|
|
|
|
6103
|
|
|
$table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE); |
6104
|
|
|
$sql = 'SELECT path_certificate |
6105
|
|
|
FROM '.$table.' |
6106
|
|
|
WHERE |
6107
|
|
|
cat_id = "'.$cat_id.'" AND |
6108
|
|
|
user_id = "'.$user_id.'"'; |
6109
|
|
|
$rs = Database::query($sql); |
6110
|
|
|
$row = Database::fetch_array($rs); |
6111
|
|
|
|
6112
|
|
|
if ($row['path_certificate'] == '' || is_null($row['path_certificate'])) { |
6113
|
|
|
return false; |
6114
|
|
|
} |
6115
|
|
|
|
6116
|
|
|
return true; |
6117
|
|
|
} |
6118
|
|
|
|
6119
|
|
|
/** |
6120
|
|
|
* Gets the info about a gradebook certificate for a user by course. |
6121
|
|
|
* |
6122
|
|
|
* @param string $course_code The course code |
6123
|
|
|
* @param int $session_id |
6124
|
|
|
* @param int $user_id The user id |
6125
|
|
|
* @param string $startDate date string |
6126
|
|
|
* @param string $endDate date string |
6127
|
|
|
* |
6128
|
|
|
* @return array if there is not information return false |
6129
|
|
|
*/ |
6130
|
|
|
public static function get_info_gradebook_certificate( |
6131
|
|
|
$course_code, |
6132
|
|
|
$session_id, |
6133
|
|
|
$user_id, |
6134
|
|
|
$startDate = null, |
6135
|
|
|
$endDate = null |
6136
|
|
|
) { |
6137
|
|
|
$tbl_grade_certificate = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE); |
6138
|
|
|
$tbl_grade_category = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY); |
6139
|
|
|
$session_id = (int) $session_id; |
6140
|
|
|
$user_id = (int) $user_id; |
6141
|
|
|
|
6142
|
|
|
if (empty($session_id)) { |
6143
|
|
|
$session_condition = ' AND (session_id = "" OR session_id = 0 OR session_id IS NULL )'; |
6144
|
|
|
} else { |
6145
|
|
|
$session_condition = " AND session_id = $session_id"; |
6146
|
|
|
} |
6147
|
|
|
|
6148
|
|
|
$dateConditions = ""; |
6149
|
|
|
if (!empty($startDate)) { |
6150
|
|
|
$startDate = api_get_utc_datetime($startDate, false, true); |
6151
|
|
|
$dateConditions .= " AND created_at >= '".$startDate->format('Y-m-d 00:00:00')."' "; |
6152
|
|
|
} |
6153
|
|
|
if (!empty($endDate)) { |
6154
|
|
|
$endDate = api_get_utc_datetime($endDate, false, true); |
6155
|
|
|
$dateConditions .= " AND created_at <= '".$endDate->format('Y-m-d 23:59:59')."' "; |
6156
|
|
|
} |
6157
|
|
|
|
6158
|
|
|
$sql = 'SELECT * FROM '.$tbl_grade_certificate.' |
6159
|
|
|
WHERE cat_id = ( |
6160
|
|
|
SELECT id FROM '.$tbl_grade_category.' |
6161
|
|
|
WHERE |
6162
|
|
|
course_code = "'.Database::escape_string($course_code).'" '.$session_condition.' '.$dateConditions.' |
6163
|
|
|
LIMIT 1 |
6164
|
|
|
) AND user_id='.$user_id; |
6165
|
|
|
|
6166
|
|
|
$rs = Database::query($sql); |
6167
|
|
|
if (Database::num_rows($rs) > 0) { |
6168
|
|
|
$row = Database::fetch_array($rs, 'ASSOC'); |
6169
|
|
|
$score = $row['score_certificate']; |
6170
|
|
|
$category_id = $row['cat_id']; |
6171
|
|
|
$cat = Category::load($category_id); |
6172
|
|
|
$displayscore = ScoreDisplay::instance(); |
6173
|
|
|
if (isset($cat) && $displayscore->is_custom()) { |
6174
|
|
|
$grade = $displayscore->display_score( |
6175
|
|
|
[$score, $cat[0]->get_weight()], |
6176
|
|
|
SCORE_DIV_PERCENT_WITH_CUSTOM |
6177
|
|
|
); |
6178
|
|
|
} else { |
6179
|
|
|
$grade = $displayscore->display_score( |
6180
|
|
|
[$score, $cat[0]->get_weight()] |
6181
|
|
|
); |
6182
|
|
|
} |
6183
|
|
|
$row['grade'] = $grade; |
6184
|
|
|
|
6185
|
|
|
return $row; |
6186
|
|
|
} |
6187
|
|
|
|
6188
|
|
|
return false; |
6189
|
|
|
} |
6190
|
|
|
|
6191
|
|
|
/** |
6192
|
|
|
* This function check if the user is a coach inside session course. |
6193
|
|
|
* |
6194
|
|
|
* @param int $user_id User id |
6195
|
|
|
* @param int $courseId |
6196
|
|
|
* @param int $session_id |
6197
|
|
|
* |
6198
|
|
|
* @return bool True if the user is a coach |
6199
|
|
|
*/ |
6200
|
|
|
public static function is_session_course_coach($user_id, $courseId, $session_id) |
6201
|
|
|
{ |
6202
|
|
|
$table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER); |
6203
|
|
|
// Protect data |
6204
|
|
|
$user_id = intval($user_id); |
6205
|
|
|
$courseId = intval($courseId); |
6206
|
|
|
$session_id = intval($session_id); |
6207
|
|
|
$result = false; |
6208
|
|
|
|
6209
|
|
|
$sql = "SELECT session_id FROM $table |
6210
|
|
|
WHERE |
6211
|
|
|
session_id = $session_id AND |
6212
|
|
|
c_id = $courseId AND |
6213
|
|
|
user_id = $user_id AND |
6214
|
|
|
status = 2 "; |
6215
|
|
|
$res = Database::query($sql); |
6216
|
|
|
|
6217
|
|
|
if (Database::num_rows($res) > 0) { |
6218
|
|
|
$result = true; |
6219
|
|
|
} |
6220
|
|
|
|
6221
|
|
|
return $result; |
6222
|
|
|
} |
6223
|
|
|
|
6224
|
|
|
/** |
6225
|
|
|
* This function returns an icon path that represents the favicon of the website of which the url given. |
6226
|
|
|
* Defaults to the current Chamilo favicon. |
6227
|
|
|
* |
6228
|
|
|
* @param string $url1 URL of website where to look for favicon.ico |
6229
|
|
|
* @param string $url2 Optional second URL of website where to look for favicon.ico |
6230
|
|
|
* |
6231
|
|
|
* @return string Path of icon to load |
6232
|
|
|
*/ |
6233
|
|
|
public static function get_favicon_from_url($url1, $url2 = null) |
6234
|
|
|
{ |
6235
|
|
|
$icon_link = ''; |
6236
|
|
|
$url = $url1; |
6237
|
|
|
if (empty($url1)) { |
6238
|
|
|
$url = $url2; |
6239
|
|
|
if (empty($url)) { |
6240
|
|
|
$url = api_get_access_url(api_get_current_access_url_id()); |
6241
|
|
|
$url = $url[0]; |
6242
|
|
|
} |
6243
|
|
|
} |
6244
|
|
|
if (!empty($url)) { |
6245
|
|
|
$pieces = parse_url($url); |
6246
|
|
|
$icon_link = $pieces['scheme'].'://'.$pieces['host'].'/favicon.ico'; |
6247
|
|
|
} |
6248
|
|
|
|
6249
|
|
|
return $icon_link; |
6250
|
|
|
} |
6251
|
|
|
|
6252
|
|
|
public static function addUserAsAdmin(User $user, bool $andFlush = true) |
6253
|
|
|
{ |
6254
|
|
|
if ($user) { |
|
|
|
|
6255
|
|
|
$userId = $user->getId(); |
6256
|
|
|
if (!self::is_admin($userId)) { |
6257
|
|
|
$table = Database::get_main_table(TABLE_MAIN_ADMIN); |
6258
|
|
|
$sql = "INSERT INTO $table SET user_id = $userId"; |
6259
|
|
|
Database::query($sql); |
6260
|
|
|
} |
6261
|
|
|
|
6262
|
|
|
$user->addRole('ROLE_SUPER_ADMIN'); |
6263
|
|
|
self::getManager()->updateUser($user, $andFlush); |
6264
|
|
|
} |
6265
|
|
|
} |
6266
|
|
|
|
6267
|
|
|
public static function removeUserAdmin(User $user, bool $andFlush = true) |
6268
|
|
|
{ |
6269
|
|
|
$userId = (int) $user->getId(); |
6270
|
|
|
if (self::is_admin($userId)) { |
6271
|
|
|
$table = Database::get_main_table(TABLE_MAIN_ADMIN); |
6272
|
|
|
$sql = "DELETE FROM $table WHERE user_id = $userId"; |
6273
|
|
|
Database::query($sql); |
6274
|
|
|
$user->removeRole('ROLE_SUPER_ADMIN'); |
6275
|
|
|
self::getManager()->updateUser($user, $andFlush); |
6276
|
|
|
} |
6277
|
|
|
} |
6278
|
|
|
|
6279
|
|
|
/** |
6280
|
|
|
* @param string $from |
6281
|
|
|
* @param string $to |
6282
|
|
|
*/ |
6283
|
|
|
public static function update_all_user_languages($from, $to) |
6284
|
|
|
{ |
6285
|
|
|
$table_user = Database::get_main_table(TABLE_MAIN_USER); |
6286
|
|
|
$from = Database::escape_string($from); |
6287
|
|
|
$to = Database::escape_string($to); |
6288
|
|
|
|
6289
|
|
|
if (!empty($to) && !empty($from)) { |
6290
|
|
|
$sql = "UPDATE $table_user SET language = '$to' |
6291
|
|
|
WHERE language = '$from'"; |
6292
|
|
|
Database::query($sql); |
6293
|
|
|
} |
6294
|
|
|
} |
6295
|
|
|
|
6296
|
|
|
/** |
6297
|
|
|
* Subscribe boss to students. |
6298
|
|
|
* |
6299
|
|
|
* @param int $bossId The boss id |
6300
|
|
|
* @param array $usersId The users array |
6301
|
|
|
* @param bool $deleteOtherAssignedUsers |
6302
|
|
|
* |
6303
|
|
|
* @return int Affected rows |
6304
|
|
|
*/ |
6305
|
|
|
public static function subscribeBossToUsers($bossId, $usersId, $deleteOtherAssignedUsers = true) |
6306
|
|
|
{ |
6307
|
|
|
return self::subscribeUsersToUser( |
6308
|
|
|
$bossId, |
6309
|
|
|
$usersId, |
6310
|
|
|
USER_RELATION_TYPE_BOSS, |
6311
|
|
|
false, |
6312
|
|
|
$deleteOtherAssignedUsers |
6313
|
|
|
); |
6314
|
|
|
} |
6315
|
|
|
|
6316
|
|
|
/** |
6317
|
|
|
* @param int $userId |
6318
|
|
|
* |
6319
|
|
|
* @return bool |
6320
|
|
|
*/ |
6321
|
|
|
public static function removeAllBossFromStudent($userId) |
6322
|
|
|
{ |
6323
|
|
|
$userId = (int) $userId; |
6324
|
|
|
|
6325
|
|
|
if (empty($userId)) { |
6326
|
|
|
return false; |
6327
|
|
|
} |
6328
|
|
|
|
6329
|
|
|
$userRelUserTable = Database::get_main_table(TABLE_MAIN_USER_REL_USER); |
6330
|
|
|
$sql = "DELETE FROM $userRelUserTable |
6331
|
|
|
WHERE user_id = $userId AND relation_type = ".USER_RELATION_TYPE_BOSS; |
6332
|
|
|
Database::query($sql); |
6333
|
|
|
|
6334
|
|
|
return true; |
6335
|
|
|
} |
6336
|
|
|
|
6337
|
|
|
/** |
6338
|
|
|
* It updates course relation type as EX-LEARNER if project name (extra field from user_edition_extra_field_to_check) is changed. |
6339
|
|
|
* |
6340
|
|
|
* @param $userId |
6341
|
|
|
* @param $extraValue |
6342
|
|
|
* |
6343
|
|
|
* @throws \Doctrine\DBAL\Exception |
6344
|
|
|
*/ |
6345
|
|
|
public static function updateCourseRelationTypeExLearner($userId, $extraValue) |
6346
|
|
|
{ |
6347
|
|
|
if (false !== api_get_configuration_value('user_edition_extra_field_to_check')) { |
6348
|
|
|
$extraToCheck = api_get_configuration_value('user_edition_extra_field_to_check'); |
6349
|
|
|
|
6350
|
|
|
// Get the old user extra value to check |
6351
|
|
|
$userExtra = UserManager::get_extra_user_data_by_field($userId, $extraToCheck); |
6352
|
|
|
if (isset($userExtra[$extraToCheck]) && $userExtra[$extraToCheck] != $extraValue) { |
6353
|
|
|
// it searchs the courses with the user old extravalue |
6354
|
|
|
$extraFieldValues = new ExtraFieldValue('course'); |
6355
|
|
|
$extraItems = $extraFieldValues->get_item_id_from_field_variable_and_field_value($extraToCheck, $userExtra[$extraToCheck], false, false, true); |
6356
|
|
|
$coursesTocheck = []; |
6357
|
|
|
if (!empty($extraItems)) { |
6358
|
|
|
foreach ($extraItems as $items) { |
6359
|
|
|
$coursesTocheck[] = $items['item_id']; |
6360
|
|
|
} |
6361
|
|
|
} |
6362
|
|
|
|
6363
|
|
|
$tblUserGroupRelUser = Database::get_main_table(TABLE_USERGROUP_REL_USER); |
6364
|
|
|
$tblUserGroupRelCourse = Database::get_main_table(TABLE_USERGROUP_REL_COURSE); |
6365
|
|
|
$tblUserGroupRelSession = Database::get_main_table(TABLE_USERGROUP_REL_SESSION); |
6366
|
|
|
$tblSessionUser = Database::get_main_table(TABLE_MAIN_SESSION_USER); |
6367
|
|
|
$tblCourseUser = Database::get_main_table(TABLE_MAIN_COURSE_USER); |
6368
|
|
|
|
6369
|
|
|
// To check in main course |
6370
|
|
|
if (!empty($coursesTocheck)) { |
6371
|
|
|
foreach ($coursesTocheck as $courseId) { |
6372
|
|
|
$sql = "SELECT id FROM $tblCourseUser |
6373
|
|
|
WHERE user_id = $userId AND c_id = $courseId"; |
6374
|
|
|
$rs = Database::query($sql); |
6375
|
|
|
if (Database::num_rows($rs) > 0) { |
6376
|
|
|
$id = Database::result($rs, 0, 0); |
6377
|
|
|
$sql = "UPDATE $tblCourseUser SET relation_type = ".COURSE_EXLEARNER." |
6378
|
|
|
WHERE id = $id"; |
6379
|
|
|
Database::query($sql); |
6380
|
|
|
} |
6381
|
|
|
} |
6382
|
|
|
} |
6383
|
|
|
|
6384
|
|
|
// To check in sessions |
6385
|
|
|
if (!empty($coursesTocheck)) { |
6386
|
|
|
$tblSessionCourseUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER); |
6387
|
|
|
$sessionsToCheck = []; |
6388
|
|
|
foreach ($coursesTocheck as $courseId) { |
6389
|
|
|
$sql = "SELECT id, session_id FROM $tblSessionCourseUser |
6390
|
|
|
WHERE user_id = $userId AND c_id = $courseId"; |
6391
|
|
|
$rs = Database::query($sql); |
6392
|
|
|
if (Database::num_rows($rs) > 0) { |
6393
|
|
|
$row = Database::fetch_array($rs); |
6394
|
|
|
$id = $row['id']; |
6395
|
|
|
$sessionId = $row['session_id']; |
6396
|
|
|
$sql = "UPDATE $tblSessionCourseUser SET status = ".COURSE_EXLEARNER." |
6397
|
|
|
WHERE id = $id"; |
6398
|
|
|
Database::query($sql); |
6399
|
|
|
$sessionsToCheck[] = $sessionId; |
6400
|
|
|
} |
6401
|
|
|
} |
6402
|
|
|
// It checks if user is ex-learner in all courses in the session to update the session relation type |
6403
|
|
|
if (!empty($sessionsToCheck)) { |
6404
|
|
|
$sessionsToCheck = array_unique($sessionsToCheck); |
6405
|
|
|
foreach ($sessionsToCheck as $sessionId) { |
6406
|
|
|
$checkAll = Database::query("SELECT count(id) FROM $tblSessionCourseUser WHERE user_id = $userId AND session_id = $sessionId"); |
6407
|
|
|
$countAll = Database::result($checkAll, 0, 0); |
6408
|
|
|
$checkExLearner = Database::query("SELECT count(id) FROM $tblSessionCourseUser WHERE status = ".COURSE_EXLEARNER." AND user_id = $userId AND session_id = $sessionId"); |
6409
|
|
|
$countExLearner = Database::result($checkExLearner, 0, 0); |
6410
|
|
|
if ($countAll > 0 && $countAll == $countExLearner) { |
6411
|
|
|
$sql = "UPDATE $tblSessionUser SET relation_type = ".COURSE_EXLEARNER." |
6412
|
|
|
WHERE user_id = $userId AND session_id = $sessionId"; |
6413
|
|
|
Database::query($sql); |
6414
|
|
|
} |
6415
|
|
|
} |
6416
|
|
|
} |
6417
|
|
|
} |
6418
|
|
|
// To check users inside a class |
6419
|
|
|
$rsUser = Database::query("SELECT usergroup_id FROM $tblUserGroupRelUser WHERE user_id = $userId"); |
6420
|
|
|
if (Database::num_rows($rsUser) > 0) { |
6421
|
|
|
while ($rowUser = Database::fetch_array($rsUser)) { |
6422
|
|
|
$usergroupId = $rowUser['usergroup_id']; |
6423
|
|
|
|
6424
|
|
|
// Count courses with exlearners |
6425
|
|
|
$sqlC1 = "SELECT count(id) FROM $tblUserGroupRelCourse WHERE usergroup_id = $usergroupId"; |
6426
|
|
|
$rsCourses = Database::query($sqlC1); |
6427
|
|
|
$countGroupCourses = Database::result($rsCourses, 0, 0); |
6428
|
|
|
|
6429
|
|
|
$sqlC2 = "SELECT count(cu.id) |
6430
|
|
|
FROM $tblCourseUser cu |
6431
|
|
|
INNER JOIN $tblUserGroupRelCourse gc |
6432
|
|
|
ON gc.course_id = cu.c_id |
6433
|
|
|
WHERE |
6434
|
|
|
cu.user_id = $userId AND |
6435
|
|
|
usergroup_id = $usergroupId AND |
6436
|
|
|
relation_type = ".COURSE_EXLEARNER; |
6437
|
|
|
$rsExCourses = Database::query($sqlC2); |
6438
|
|
|
$countExCourses = Database::result($rsExCourses, 0, 0); |
6439
|
|
|
$checkedExCourses = $countGroupCourses > 0 && ($countExCourses == $countGroupCourses); |
6440
|
|
|
|
6441
|
|
|
// Count sessions with exlearners |
6442
|
|
|
$sqlS1 = "SELECT count(id) FROM $tblUserGroupRelSession WHERE usergroup_id = $usergroupId"; |
6443
|
|
|
$rsSessions = Database::query($sqlS1); |
6444
|
|
|
$countGroupSessions = Database::result($rsSessions, 0, 0); |
6445
|
|
|
|
6446
|
|
|
$sqlS2 = "SELECT count(su.id) |
6447
|
|
|
FROM $tblSessionUser su |
6448
|
|
|
INNER JOIN $tblUserGroupRelSession gs |
6449
|
|
|
ON gs.session_id = su.session_id |
6450
|
|
|
WHERE |
6451
|
|
|
su.user_id = $userId AND |
6452
|
|
|
usergroup_id = $usergroupId AND |
6453
|
|
|
relation_type = ".COURSE_EXLEARNER; |
6454
|
|
|
$rsExSessions = Database::query($sqlS2); |
6455
|
|
|
$countExSessions = Database::result($rsExSessions, 0, 0); |
6456
|
|
|
$checkedExSessions = $countGroupSessions > 0 && ($countExSessions == $countGroupSessions); |
6457
|
|
|
|
6458
|
|
|
// it checks if usergroup user should be set to EXLEARNER |
6459
|
|
|
$checkedExClassLearner = false; |
6460
|
|
|
if ($countGroupCourses > 0 && $countGroupSessions == 0) { |
6461
|
|
|
$checkedExClassLearner = $checkedExCourses; |
6462
|
|
|
} elseif ($countGroupCourses == 0 && $countGroupSessions > 0) { |
6463
|
|
|
$checkedExClassLearner = $checkedExSessions; |
6464
|
|
|
} elseif ($countGroupCourses > 0 && $countGroupSessions > 0) { |
6465
|
|
|
$checkedExClassLearner = ($checkedExCourses && $checkedExSessions); |
6466
|
|
|
} |
6467
|
|
|
|
6468
|
|
|
if ($checkedExClassLearner) { |
6469
|
|
|
Database::query("UPDATE $tblUserGroupRelUser SET relation_type = ".COURSE_EXLEARNER." WHERE user_id = $userId AND usergroup_id = $usergroupId"); |
6470
|
|
|
} |
6471
|
|
|
} |
6472
|
|
|
} |
6473
|
|
|
} |
6474
|
|
|
} |
6475
|
|
|
} |
6476
|
|
|
|
6477
|
|
|
/** |
6478
|
|
|
* Subscribe boss to students, if $bossList is empty then the boss list will be empty too. |
6479
|
|
|
* |
6480
|
|
|
* @param int $studentId |
6481
|
|
|
* @param array $bossList |
6482
|
|
|
* @param bool $sendNotification |
6483
|
|
|
* |
6484
|
|
|
* @return mixed Affected rows or false on failure |
6485
|
|
|
*/ |
6486
|
|
|
public static function subscribeUserToBossList( |
6487
|
|
|
$studentId, |
6488
|
|
|
$bossList, |
6489
|
|
|
$sendNotification = false |
6490
|
|
|
) { |
6491
|
|
|
$inserted = 0; |
6492
|
|
|
if (!empty($bossList)) { |
6493
|
|
|
sort($bossList); |
6494
|
|
|
$studentId = (int) $studentId; |
6495
|
|
|
$studentInfo = api_get_user_info($studentId); |
6496
|
|
|
|
6497
|
|
|
if (empty($studentInfo)) { |
6498
|
|
|
return false; |
6499
|
|
|
} |
6500
|
|
|
|
6501
|
|
|
$previousBossList = self::getStudentBossList($studentId); |
6502
|
|
|
$previousBossList = !empty($previousBossList) ? array_column($previousBossList, 'boss_id') : []; |
6503
|
|
|
sort($previousBossList); |
6504
|
|
|
|
6505
|
|
|
// Boss list is the same, nothing changed. |
6506
|
|
|
if ($bossList == $previousBossList) { |
6507
|
|
|
return false; |
6508
|
|
|
} |
6509
|
|
|
|
6510
|
|
|
$userRelUserTable = Database::get_main_table(TABLE_MAIN_USER_REL_USER); |
6511
|
|
|
self::removeAllBossFromStudent($studentId); |
6512
|
|
|
|
6513
|
|
|
foreach ($bossList as $bossId) { |
6514
|
|
|
$bossId = (int) $bossId; |
6515
|
|
|
$bossInfo = api_get_user_info($bossId); |
6516
|
|
|
|
6517
|
|
|
if (empty($bossInfo)) { |
6518
|
|
|
continue; |
6519
|
|
|
} |
6520
|
|
|
|
6521
|
|
|
$bossLanguage = $bossInfo['language']; |
6522
|
|
|
|
6523
|
|
|
$sql = "INSERT IGNORE INTO $userRelUserTable (user_id, friend_user_id, relation_type) |
6524
|
|
|
VALUES ($studentId, $bossId, ".USER_RELATION_TYPE_BOSS.")"; |
6525
|
|
|
$insertId = Database::query($sql); |
6526
|
|
|
|
6527
|
|
|
if ($insertId) { |
6528
|
|
|
if ($sendNotification) { |
6529
|
|
|
$name = $studentInfo['complete_name']; |
6530
|
|
|
$url = api_get_path(WEB_CODE_PATH).'mySpace/myStudents.php?student='.$studentId; |
6531
|
|
|
$url = Display::url($url, $url); |
6532
|
|
|
$subject = sprintf( |
6533
|
|
|
get_lang('UserXHasBeenAssignedToBoss', false, $bossLanguage), |
6534
|
|
|
$name |
6535
|
|
|
); |
6536
|
|
|
$message = sprintf( |
6537
|
|
|
get_lang('UserXHasBeenAssignedToBossWithUrlX', false, $bossLanguage), |
6538
|
|
|
$name, |
6539
|
|
|
$url |
6540
|
|
|
); |
6541
|
|
|
MessageManager::send_message_simple( |
6542
|
|
|
$bossId, |
6543
|
|
|
$subject, |
6544
|
|
|
$message |
6545
|
|
|
); |
6546
|
|
|
} |
6547
|
|
|
$inserted++; |
6548
|
|
|
} |
6549
|
|
|
} |
6550
|
|
|
} else { |
6551
|
|
|
self::removeAllBossFromStudent($studentId); |
6552
|
|
|
} |
6553
|
|
|
|
6554
|
|
|
return $inserted; |
6555
|
|
|
} |
6556
|
|
|
|
6557
|
|
|
/** |
6558
|
|
|
* Get users followed by student boss. |
6559
|
|
|
* |
6560
|
|
|
* @param int $userId |
6561
|
|
|
* @param int $userStatus (STUDENT, COURSEMANAGER, etc) |
6562
|
|
|
* @param bool $getOnlyUserId |
6563
|
|
|
* @param bool $getSql |
6564
|
|
|
* @param bool $getCount |
6565
|
|
|
* @param int $from |
6566
|
|
|
* @param int $numberItems |
6567
|
|
|
* @param int $column |
6568
|
|
|
* @param string $direction |
6569
|
|
|
* @param int $active |
6570
|
|
|
* @param string $lastConnectionDate |
6571
|
|
|
* |
6572
|
|
|
* @return array users |
6573
|
|
|
*/ |
6574
|
|
|
public static function getUsersFollowedByStudentBoss( |
6575
|
|
|
$userId, |
6576
|
|
|
$userStatus = 0, |
6577
|
|
|
$getOnlyUserId = false, |
6578
|
|
|
$getSql = false, |
6579
|
|
|
$getCount = false, |
6580
|
|
|
$from = null, |
6581
|
|
|
$numberItems = null, |
6582
|
|
|
$column = null, |
6583
|
|
|
$direction = null, |
6584
|
|
|
$active = null, |
6585
|
|
|
$lastConnectionDate = null |
6586
|
|
|
) { |
6587
|
|
|
return self::getUsersFollowedByUser( |
|
|
|
|
6588
|
|
|
$userId, |
6589
|
|
|
$userStatus, |
6590
|
|
|
$getOnlyUserId, |
6591
|
|
|
$getSql, |
6592
|
|
|
$getCount, |
6593
|
|
|
$from, |
6594
|
|
|
$numberItems, |
6595
|
|
|
$column, |
6596
|
|
|
$direction, |
6597
|
|
|
$active, |
6598
|
|
|
$lastConnectionDate, |
6599
|
|
|
STUDENT_BOSS |
6600
|
|
|
); |
6601
|
|
|
} |
6602
|
|
|
|
6603
|
|
|
/** |
6604
|
|
|
* @return array |
6605
|
|
|
*/ |
6606
|
|
|
public static function getOfficialCodeGrouped() |
6607
|
|
|
{ |
6608
|
|
|
$user = Database::get_main_table(TABLE_MAIN_USER); |
6609
|
|
|
$sql = "SELECT DISTINCT official_code |
6610
|
|
|
FROM $user |
6611
|
|
|
GROUP BY official_code"; |
6612
|
|
|
$result = Database::query($sql); |
6613
|
|
|
$values = Database::store_result($result, 'ASSOC'); |
6614
|
|
|
$result = []; |
6615
|
|
|
foreach ($values as $value) { |
6616
|
|
|
$result[$value['official_code']] = $value['official_code']; |
6617
|
|
|
} |
6618
|
|
|
|
6619
|
|
|
return $result; |
6620
|
|
|
} |
6621
|
|
|
|
6622
|
|
|
/** |
6623
|
|
|
* @param string $officialCode |
6624
|
|
|
* |
6625
|
|
|
* @return array |
6626
|
|
|
*/ |
6627
|
|
|
public static function getUsersByOfficialCode($officialCode) |
6628
|
|
|
{ |
6629
|
|
|
$user = Database::get_main_table(TABLE_MAIN_USER); |
6630
|
|
|
$officialCode = Database::escape_string($officialCode); |
6631
|
|
|
|
6632
|
|
|
$sql = "SELECT DISTINCT id |
6633
|
|
|
FROM $user |
6634
|
|
|
WHERE official_code = '$officialCode' |
6635
|
|
|
"; |
6636
|
|
|
$result = Database::query($sql); |
6637
|
|
|
|
6638
|
|
|
$users = []; |
6639
|
|
|
while ($row = Database::fetch_array($result)) { |
6640
|
|
|
$users[] = $row['id']; |
6641
|
|
|
} |
6642
|
|
|
|
6643
|
|
|
return $users; |
6644
|
|
|
} |
6645
|
|
|
|
6646
|
|
|
/** |
6647
|
|
|
* Calc the expended time (in seconds) by a user in a course. |
6648
|
|
|
* |
6649
|
|
|
* @param int $userId The user id |
6650
|
|
|
* @param int $courseId The course id |
6651
|
|
|
* @param int $sessionId Optional. The session id |
6652
|
|
|
* @param string $from Optional. From date |
6653
|
|
|
* @param string $until Optional. Until date |
6654
|
|
|
* |
6655
|
|
|
* @return int The time |
6656
|
|
|
*/ |
6657
|
|
|
public static function getTimeSpentInCourses( |
6658
|
|
|
$userId, |
6659
|
|
|
$courseId, |
6660
|
|
|
$sessionId = 0, |
6661
|
|
|
$from = '', |
6662
|
|
|
$until = '' |
6663
|
|
|
) { |
6664
|
|
|
$userId = (int) $userId; |
6665
|
|
|
$sessionId = (int) $sessionId; |
6666
|
|
|
|
6667
|
|
|
$trackCourseAccessTable = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS); |
6668
|
|
|
$whereConditions = [ |
6669
|
|
|
'user_id = ? ' => $userId, |
6670
|
|
|
'AND c_id = ? ' => $courseId, |
6671
|
|
|
'AND session_id = ? ' => $sessionId, |
6672
|
|
|
]; |
6673
|
|
|
|
6674
|
|
|
if (!empty($from) && !empty($until)) { |
6675
|
|
|
$whereConditions["AND (login_course_date >= '?' "] = $from; |
6676
|
|
|
$whereConditions["AND logout_course_date <= DATE_ADD('?', INTERVAL 1 DAY)) "] = $until; |
6677
|
|
|
} |
6678
|
|
|
|
6679
|
|
|
$trackResult = Database::select( |
6680
|
|
|
'SUM(UNIX_TIMESTAMP(logout_course_date) - UNIX_TIMESTAMP(login_course_date)) as total_time', |
6681
|
|
|
$trackCourseAccessTable, |
6682
|
|
|
[ |
6683
|
|
|
'where' => $whereConditions, |
6684
|
|
|
], |
6685
|
|
|
'first' |
6686
|
|
|
); |
6687
|
|
|
|
6688
|
|
|
if ($trackResult != false) { |
6689
|
|
|
return $trackResult['total_time'] ? $trackResult['total_time'] : 0; |
6690
|
|
|
} |
6691
|
|
|
|
6692
|
|
|
return 0; |
6693
|
|
|
} |
6694
|
|
|
|
6695
|
|
|
/** |
6696
|
|
|
* Get the boss user ID from a followed user id. |
6697
|
|
|
* |
6698
|
|
|
* @param $userId |
6699
|
|
|
* |
6700
|
|
|
* @return bool |
6701
|
|
|
*/ |
6702
|
|
|
public static function getFirstStudentBoss($userId) |
6703
|
|
|
{ |
6704
|
|
|
$userId = (int) $userId; |
6705
|
|
|
if ($userId > 0) { |
6706
|
|
|
$userRelTable = Database::get_main_table(TABLE_MAIN_USER_REL_USER); |
6707
|
|
|
$row = Database::select( |
6708
|
|
|
'DISTINCT friend_user_id AS boss_id', |
6709
|
|
|
$userRelTable, |
6710
|
|
|
[ |
6711
|
|
|
'where' => [ |
6712
|
|
|
'user_id = ? AND relation_type = ? LIMIT 1' => [ |
6713
|
|
|
$userId, |
6714
|
|
|
USER_RELATION_TYPE_BOSS, |
6715
|
|
|
], |
6716
|
|
|
], |
6717
|
|
|
] |
6718
|
|
|
); |
6719
|
|
|
if (!empty($row)) { |
6720
|
|
|
return $row[0]['boss_id']; |
6721
|
|
|
} |
6722
|
|
|
} |
6723
|
|
|
|
6724
|
|
|
return false; |
6725
|
|
|
} |
6726
|
|
|
|
6727
|
|
|
/** |
6728
|
|
|
* Get the boss user ID from a followed user id. |
6729
|
|
|
* |
6730
|
|
|
* @param int $userId student id |
6731
|
|
|
* |
6732
|
|
|
* @return array |
6733
|
|
|
*/ |
6734
|
|
|
public static function getStudentBossList($userId) |
6735
|
|
|
{ |
6736
|
|
|
$userId = (int) $userId; |
6737
|
|
|
|
6738
|
|
|
if ($userId > 0) { |
6739
|
|
|
$userRelTable = Database::get_main_table(TABLE_MAIN_USER_REL_USER); |
6740
|
|
|
|
6741
|
|
|
return Database::select( |
6742
|
|
|
'DISTINCT friend_user_id AS boss_id', |
6743
|
|
|
$userRelTable, |
6744
|
|
|
[ |
6745
|
|
|
'where' => [ |
6746
|
|
|
'user_id = ? AND relation_type = ? ' => [ |
6747
|
|
|
$userId, |
6748
|
|
|
USER_RELATION_TYPE_BOSS, |
6749
|
|
|
], |
6750
|
|
|
], |
6751
|
|
|
] |
6752
|
|
|
); |
6753
|
|
|
} |
6754
|
|
|
|
6755
|
|
|
return []; |
6756
|
|
|
} |
6757
|
|
|
|
6758
|
|
|
/** |
6759
|
|
|
* @param int $bossId |
6760
|
|
|
* @param int $studentId |
6761
|
|
|
* |
6762
|
|
|
* @return bool |
6763
|
|
|
*/ |
6764
|
|
|
public static function userIsBossOfStudent($bossId, $studentId) |
6765
|
|
|
{ |
6766
|
|
|
$result = false; |
6767
|
|
|
$bossList = self::getStudentBossList($studentId); |
6768
|
|
|
if (!empty($bossList)) { |
6769
|
|
|
$bossList = array_column($bossList, 'boss_id'); |
6770
|
|
|
if (in_array($bossId, $bossList)) { |
6771
|
|
|
$result = true; |
6772
|
|
|
} |
6773
|
|
|
} |
6774
|
|
|
|
6775
|
|
|
return $result; |
6776
|
|
|
} |
6777
|
|
|
|
6778
|
|
|
/** |
6779
|
|
|
* Displays the name of the user and makes the link to the user profile. |
6780
|
|
|
* |
6781
|
|
|
* @param array $userInfo |
6782
|
|
|
* |
6783
|
|
|
* @return string |
6784
|
|
|
*/ |
6785
|
|
|
public static function getUserProfileLink($userInfo) |
6786
|
|
|
{ |
6787
|
|
|
if (isset($userInfo) && isset($userInfo['user_id'])) { |
6788
|
|
|
return Display::url( |
6789
|
|
|
$userInfo['complete_name_with_username'], |
6790
|
|
|
$userInfo['profile_url'] |
6791
|
|
|
); |
6792
|
|
|
} |
6793
|
|
|
|
6794
|
|
|
return get_lang('Anonymous'); |
6795
|
|
|
} |
6796
|
|
|
|
6797
|
|
|
/** |
6798
|
|
|
* Get users whose name matches $firstname and $lastname. |
6799
|
|
|
* |
6800
|
|
|
* @param string $firstname Firstname to search |
6801
|
|
|
* @param string $lastname Lastname to search |
6802
|
|
|
* |
6803
|
|
|
* @return array The user list |
6804
|
|
|
*/ |
6805
|
|
|
public static function getUsersByName($firstname, $lastname) |
6806
|
|
|
{ |
6807
|
|
|
$firstname = Database::escape_string($firstname); |
6808
|
|
|
$lastname = Database::escape_string($lastname); |
6809
|
|
|
$userTable = Database::get_main_table(TABLE_MAIN_USER); |
6810
|
|
|
|
6811
|
|
|
$sql = <<<SQL |
6812
|
|
|
SELECT id, username, lastname, firstname |
6813
|
|
|
FROM $userTable |
6814
|
|
|
WHERE |
6815
|
|
|
firstname LIKE '$firstname%' AND |
6816
|
|
|
lastname LIKE '$lastname%' |
6817
|
|
|
SQL; |
6818
|
|
|
$result = Database::query($sql); |
6819
|
|
|
$users = []; |
6820
|
|
|
while ($resultData = Database::fetch_object($result)) { |
6821
|
|
|
$users[] = $resultData; |
6822
|
|
|
} |
6823
|
|
|
|
6824
|
|
|
return $users; |
6825
|
|
|
} |
6826
|
|
|
|
6827
|
|
|
/** |
6828
|
|
|
* @param int $optionSelected |
6829
|
|
|
* |
6830
|
|
|
* @return string |
6831
|
|
|
*/ |
6832
|
|
|
public static function getUserSubscriptionTab($optionSelected = 1) |
6833
|
|
|
{ |
6834
|
|
|
$allowAdmin = api_get_setting('allow_user_course_subscription_by_course_admin'); |
6835
|
|
|
if (($allowAdmin === 'true' && api_is_allowed_to_edit()) || |
6836
|
|
|
api_is_platform_admin() |
6837
|
|
|
) { |
6838
|
|
|
$userPath = api_get_path(WEB_CODE_PATH).'user/'; |
6839
|
|
|
|
6840
|
|
|
$headers = [ |
6841
|
|
|
[ |
6842
|
|
|
'url' => $userPath.'user.php?'.api_get_cidreq().'&type='.STUDENT, |
6843
|
|
|
'content' => get_lang('Students'), |
6844
|
|
|
], |
6845
|
|
|
[ |
6846
|
|
|
'url' => $userPath.'user.php?'.api_get_cidreq().'&type='.COURSEMANAGER, |
6847
|
|
|
'content' => get_lang('Teachers'), |
6848
|
|
|
], |
6849
|
|
|
/*[ |
6850
|
|
|
'url' => $userPath.'subscribe_user.php?'.api_get_cidreq(), |
6851
|
|
|
'content' => get_lang('Students'), |
6852
|
|
|
], |
6853
|
|
|
[ |
6854
|
|
|
'url' => $userPath.'subscribe_user.php?type=teacher&'.api_get_cidreq(), |
6855
|
|
|
'content' => get_lang('Teachers'), |
6856
|
|
|
],*/ |
6857
|
|
|
[ |
6858
|
|
|
'url' => api_get_path(WEB_CODE_PATH).'group/group.php?'.api_get_cidreq(), |
6859
|
|
|
'content' => get_lang('Groups'), |
6860
|
|
|
], |
6861
|
|
|
'classes' => [ |
6862
|
|
|
'url' => $userPath.'class.php?'.api_get_cidreq(), |
6863
|
|
|
'content' => get_lang('Classes'), |
6864
|
|
|
], |
6865
|
|
|
]; |
6866
|
|
|
|
6867
|
|
|
if (api_get_configuration_value('session_classes_tab_disable') |
6868
|
|
|
&& !api_is_platform_admin() |
6869
|
|
|
&& api_get_session_id() |
6870
|
|
|
) { |
6871
|
|
|
unset($headers['classes']); |
6872
|
|
|
} |
6873
|
|
|
|
6874
|
|
|
return Display::tabsOnlyLink($headers, $optionSelected); |
6875
|
|
|
} |
6876
|
|
|
|
6877
|
|
|
return ''; |
6878
|
|
|
} |
6879
|
|
|
|
6880
|
|
|
/** |
6881
|
|
|
* Make sure this function is protected because it does NOT check password! |
6882
|
|
|
* |
6883
|
|
|
* This function defines globals. |
6884
|
|
|
* |
6885
|
|
|
* @param int $userId |
6886
|
|
|
* @param bool $checkIfUserCanLoginAs |
6887
|
|
|
* |
6888
|
|
|
* @return bool |
6889
|
|
|
* |
6890
|
|
|
* @author Evie Embrechts |
6891
|
|
|
* @author Yannick Warnier <[email protected]> |
6892
|
|
|
*/ |
6893
|
|
|
public static function loginAsUser($userId, $checkIfUserCanLoginAs = true) |
6894
|
|
|
{ |
6895
|
|
|
$userId = (int) $userId; |
6896
|
|
|
$userInfo = api_get_user_info($userId); |
6897
|
|
|
|
6898
|
|
|
// Check if the user is allowed to 'login_as' |
6899
|
|
|
$canLoginAs = true; |
6900
|
|
|
if ($checkIfUserCanLoginAs) { |
6901
|
|
|
$canLoginAs = api_can_login_as($userId); |
6902
|
|
|
} |
6903
|
|
|
|
6904
|
|
|
if (!$canLoginAs || empty($userInfo)) { |
6905
|
|
|
return false; |
6906
|
|
|
} |
6907
|
|
|
|
6908
|
|
|
if ($userId) { |
6909
|
|
|
$logInfo = [ |
6910
|
|
|
'tool' => 'logout', |
6911
|
|
|
'tool_id' => 0, |
6912
|
|
|
'tool_id_detail' => 0, |
6913
|
|
|
'action' => '', |
6914
|
|
|
'info' => 'Change user (login as)', |
6915
|
|
|
]; |
6916
|
|
|
Event::registerLog($logInfo); |
|
|
|
|
6917
|
|
|
|
6918
|
|
|
// Logout the current user |
6919
|
|
|
self::loginDelete(api_get_user_id()); |
6920
|
|
|
|
6921
|
|
|
Session::erase('_user'); |
6922
|
|
|
Session::erase('is_platformAdmin'); |
6923
|
|
|
Session::erase('is_allowedCreateCourse'); |
6924
|
|
|
Session::erase('_uid'); |
6925
|
|
|
|
6926
|
|
|
// Cleaning session variables |
6927
|
|
|
$_user['firstName'] = $userInfo['firstname']; |
|
|
|
|
6928
|
|
|
$_user['lastName'] = $userInfo['lastname']; |
6929
|
|
|
$_user['mail'] = $userInfo['email']; |
6930
|
|
|
$_user['official_code'] = $userInfo['official_code']; |
6931
|
|
|
$_user['picture_uri'] = $userInfo['picture_uri']; |
6932
|
|
|
$_user['user_id'] = $userId; |
6933
|
|
|
$_user['id'] = $userId; |
6934
|
|
|
$_user['status'] = $userInfo['status']; |
6935
|
|
|
|
6936
|
|
|
// Filling session variables with new data |
6937
|
|
|
Session::write('_uid', $userId); |
6938
|
|
|
Session::write('_user', $userInfo); |
6939
|
|
|
Session::write('is_platformAdmin', (bool) self::is_admin($userId)); |
6940
|
|
|
Session::write('is_allowedCreateCourse', $userInfo['status'] == 1); |
6941
|
|
|
// will be useful later to know if the user is actually an admin or not (example reporting) |
6942
|
|
|
Session::write('login_as', true); |
6943
|
|
|
$logInfo = [ |
6944
|
|
|
'tool' => 'login', |
6945
|
|
|
'tool_id' => 0, |
6946
|
|
|
'tool_id_detail' => 0, |
6947
|
|
|
'info' => $userId, |
6948
|
|
|
]; |
6949
|
|
|
Event::registerLog($logInfo); |
6950
|
|
|
|
6951
|
|
|
return true; |
6952
|
|
|
} |
6953
|
|
|
|
6954
|
|
|
return false; |
6955
|
|
|
} |
6956
|
|
|
|
6957
|
|
|
/** |
6958
|
|
|
* Remove all login records from the track_e_online stats table, |
6959
|
|
|
* for the given user ID. |
6960
|
|
|
* |
6961
|
|
|
* @param int $userId User ID |
6962
|
|
|
*/ |
6963
|
|
|
public static function loginDelete($userId) |
6964
|
|
|
{ |
6965
|
|
|
$online_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE); |
6966
|
|
|
$userId = (int) $userId; |
6967
|
|
|
$query = "DELETE FROM $online_table WHERE login_user_id = $userId"; |
6968
|
|
|
Database::query($query); |
6969
|
|
|
} |
6970
|
|
|
|
6971
|
|
|
/** |
6972
|
|
|
* Login as first admin user registered in the platform. |
6973
|
|
|
* |
6974
|
|
|
* @return array |
6975
|
|
|
*/ |
6976
|
|
|
public static function logInAsFirstAdmin() |
6977
|
|
|
{ |
6978
|
|
|
$adminList = self::get_all_administrators(); |
6979
|
|
|
|
6980
|
|
|
if (!empty($adminList)) { |
6981
|
|
|
$userInfo = current($adminList); |
6982
|
|
|
if (!empty($userInfo)) { |
6983
|
|
|
$result = self::loginAsUser($userInfo['user_id'], false); |
6984
|
|
|
if ($result && api_is_platform_admin()) { |
6985
|
|
|
return api_get_user_info(); |
|
|
|
|
6986
|
|
|
} |
6987
|
|
|
} |
6988
|
|
|
} |
6989
|
|
|
|
6990
|
|
|
return []; |
6991
|
|
|
} |
6992
|
|
|
|
6993
|
|
|
public static function blockIfMaxLoginAttempts(array $userInfo) |
6994
|
|
|
{ |
6995
|
|
|
if (false === (bool) $userInfo['active'] || null === $userInfo['last_login']) { |
6996
|
|
|
return; |
6997
|
|
|
} |
6998
|
|
|
|
6999
|
|
|
$maxAllowed = (int) api_get_configuration_value('login_max_attempt_before_blocking_account'); |
7000
|
|
|
|
7001
|
|
|
if ($maxAllowed <= 0) { |
7002
|
|
|
return; |
7003
|
|
|
} |
7004
|
|
|
|
7005
|
|
|
$em = Database::getManager(); |
7006
|
|
|
|
7007
|
|
|
$countFailedAttempts = $em |
7008
|
|
|
->getRepository(TrackELoginAttempt::class) |
7009
|
|
|
->createQueryBuilder('la') |
7010
|
|
|
->select('COUNT(la)') |
7011
|
|
|
->where('la.username = :username') |
7012
|
|
|
->andWhere('la.loginDate >= :last_login') |
7013
|
|
|
->andWhere('la.success <> TRUE') |
7014
|
|
|
->setParameters( |
7015
|
|
|
[ |
7016
|
|
|
'username' => $userInfo['username'], |
7017
|
|
|
'last_login' => $userInfo['last_login'], |
7018
|
|
|
] |
7019
|
|
|
) |
7020
|
|
|
->getQuery() |
7021
|
|
|
->getSingleScalarResult() |
7022
|
|
|
; |
7023
|
|
|
|
7024
|
|
|
if ($countFailedAttempts >= $maxAllowed) { |
7025
|
|
|
Database::update( |
7026
|
|
|
Database::get_main_table(TABLE_MAIN_USER), |
7027
|
|
|
['active' => false], |
7028
|
|
|
['username = ?' => $userInfo['username']] |
7029
|
|
|
); |
7030
|
|
|
|
7031
|
|
|
Display::addFlash( |
7032
|
|
|
Display::return_message( |
7033
|
|
|
sprintf( |
7034
|
|
|
get_lang('XAccountDisabledByYAttempts'), |
7035
|
|
|
$userInfo['username'], |
7036
|
|
|
$countFailedAttempts |
7037
|
|
|
), |
7038
|
|
|
'error', |
7039
|
|
|
false |
7040
|
|
|
) |
7041
|
|
|
); |
7042
|
|
|
} |
7043
|
|
|
} |
7044
|
|
|
|
7045
|
|
|
/** |
7046
|
|
|
* Check if user is teacher of a student based in their courses. |
7047
|
|
|
* |
7048
|
|
|
* @param $teacherId |
7049
|
|
|
* @param $studentId |
7050
|
|
|
* |
7051
|
|
|
* @return array |
7052
|
|
|
*/ |
7053
|
|
|
public static function getCommonCoursesBetweenTeacherAndStudent($teacherId, $studentId) |
7054
|
|
|
{ |
7055
|
|
|
$courses = CourseManager::getCoursesFollowedByUser( |
7056
|
|
|
$teacherId, |
7057
|
|
|
COURSEMANAGER |
7058
|
|
|
); |
7059
|
|
|
if (empty($courses)) { |
7060
|
|
|
return false; |
7061
|
|
|
} |
7062
|
|
|
|
7063
|
|
|
$coursesFromUser = CourseManager::get_courses_list_by_user_id($studentId); |
7064
|
|
|
if (empty($coursesFromUser)) { |
7065
|
|
|
return false; |
7066
|
|
|
} |
7067
|
|
|
|
7068
|
|
|
$coursesCodeList = array_column($courses, 'code'); |
7069
|
|
|
$coursesCodeFromUserList = array_column($coursesFromUser, 'code'); |
7070
|
|
|
$commonCourses = array_intersect($coursesCodeList, $coursesCodeFromUserList); |
7071
|
|
|
$commonCourses = array_filter($commonCourses); |
7072
|
|
|
|
7073
|
|
|
if (!empty($commonCourses)) { |
7074
|
|
|
return $commonCourses; |
7075
|
|
|
} |
7076
|
|
|
|
7077
|
|
|
return []; |
7078
|
|
|
} |
7079
|
|
|
|
7080
|
|
|
/** |
7081
|
|
|
* @param int $teacherId |
7082
|
|
|
* @param int $studentId |
7083
|
|
|
* |
7084
|
|
|
* @return bool |
7085
|
|
|
*/ |
7086
|
|
|
public static function isTeacherOfStudent($teacherId, $studentId) |
7087
|
|
|
{ |
7088
|
|
|
$courses = self::getCommonCoursesBetweenTeacherAndStudent( |
7089
|
|
|
$teacherId, |
7090
|
|
|
$studentId |
7091
|
|
|
); |
7092
|
|
|
|
7093
|
|
|
if (!empty($courses)) { |
7094
|
|
|
return true; |
7095
|
|
|
} |
7096
|
|
|
|
7097
|
|
|
return false; |
7098
|
|
|
} |
7099
|
|
|
|
7100
|
|
|
/** |
7101
|
|
|
* Send user confirmation mail. |
7102
|
|
|
* |
7103
|
|
|
* @throws Exception |
7104
|
|
|
*/ |
7105
|
|
|
public static function sendUserConfirmationMail(User $user) |
7106
|
|
|
{ |
7107
|
|
|
$uniqueId = api_get_unique_id(); |
7108
|
|
|
$user->setConfirmationToken($uniqueId); |
7109
|
|
|
|
7110
|
|
|
Database::getManager()->persist($user); |
7111
|
|
|
Database::getManager()->flush(); |
7112
|
|
|
|
7113
|
|
|
$url = api_get_path(WEB_CODE_PATH).'auth/user_mail_confirmation.php?token='.$uniqueId; |
7114
|
|
|
|
7115
|
|
|
// Check if the user was originally set for an automated subscription to a course or session |
7116
|
|
|
$courseCodeToRedirect = Session::read('course_redirect'); |
7117
|
|
|
$sessionToRedirect = Session::read('session_redirect'); |
7118
|
|
|
if (!empty($courseCodeToRedirect)) { |
7119
|
|
|
$url .= '&c='.$courseCodeToRedirect; |
7120
|
|
|
} |
7121
|
|
|
if (!empty($sessionToRedirect)) { |
7122
|
|
|
$url .= '&s='.$sessionToRedirect; |
7123
|
|
|
} |
7124
|
|
|
$mailSubject = get_lang('RegistrationConfirmation'); |
7125
|
|
|
$mailBody = get_lang('RegistrationConfirmationEmailMessage') |
7126
|
|
|
.PHP_EOL |
7127
|
|
|
.Display::url($url, $url); |
7128
|
|
|
|
7129
|
|
|
api_mail_html( |
7130
|
|
|
self::formatUserFullName($user), |
7131
|
|
|
$user->getEmail(), |
7132
|
|
|
$mailSubject, |
7133
|
|
|
$mailBody |
7134
|
|
|
); |
7135
|
|
|
Display::addFlash(Display::return_message(get_lang('CheckYourEmailAndFollowInstructions'))); |
7136
|
|
|
} |
7137
|
|
|
|
7138
|
|
|
/** |
7139
|
|
|
* Anonymize a user. Replace personal info by anonymous info. |
7140
|
|
|
* |
7141
|
|
|
* @param int $userId User id |
7142
|
|
|
* @param bool $deleteIP Whether to replace the IP address in logs tables by 127.0.0.1 or to leave as is |
7143
|
|
|
* |
7144
|
|
|
* @throws \Exception |
7145
|
|
|
* |
7146
|
|
|
* @return bool |
7147
|
|
|
* @assert (0) === false |
7148
|
|
|
*/ |
7149
|
|
|
public static function anonymize($userId, $deleteIP = true) |
7150
|
|
|
{ |
7151
|
|
|
global $debug; |
7152
|
|
|
|
7153
|
|
|
$userId = (int) $userId; |
7154
|
|
|
|
7155
|
|
|
if (empty($userId)) { |
7156
|
|
|
return false; |
7157
|
|
|
} |
7158
|
|
|
|
7159
|
|
|
$em = Database::getManager(); |
7160
|
|
|
$user = api_get_user_entity($userId); |
7161
|
|
|
$uniqueId = uniqid('anon', true); |
7162
|
|
|
$user |
7163
|
|
|
->setFirstname($uniqueId) |
7164
|
|
|
->setLastname($uniqueId) |
7165
|
|
|
->setBiography('') |
7166
|
|
|
->setAddress('') |
7167
|
|
|
->setCurriculumItems(null) |
7168
|
|
|
->setDateOfBirth(null) |
7169
|
|
|
->setCompetences('') |
7170
|
|
|
->setDiplomas('') |
7171
|
|
|
->setOpenarea('') |
7172
|
|
|
->setTeach('') |
7173
|
|
|
->setProductions(null) |
7174
|
|
|
->setOpenid('') |
7175
|
|
|
->setEmailCanonical($uniqueId.'@example.com') |
7176
|
|
|
->setEmail($uniqueId.'@example.com') |
7177
|
|
|
->setUsername($uniqueId) |
7178
|
|
|
->setUsernameCanonical($uniqueId) |
7179
|
|
|
->setPhone('') |
7180
|
|
|
->setOfficialCode('') |
7181
|
|
|
; |
7182
|
|
|
|
7183
|
|
|
self::deleteUserPicture($userId); |
7184
|
|
|
self::cleanUserRequestsOfRemoval($userId); |
7185
|
|
|
|
7186
|
|
|
// The IP address is a border-case personal data, as it does |
7187
|
|
|
// not directly allow for personal identification (it is not |
7188
|
|
|
// a completely safe value in most countries - the IP could |
7189
|
|
|
// be used by neighbours and crackers) |
7190
|
|
|
if ($deleteIP) { |
7191
|
|
|
$substitute = '127.0.0.1'; |
7192
|
|
|
$table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS); |
7193
|
|
|
$sql = "UPDATE $table set user_ip = '$substitute' WHERE access_user_id = $userId"; |
7194
|
|
|
$res = Database::query($sql); |
7195
|
|
|
if ($res === false && $debug > 0) { |
7196
|
|
|
error_log("Could not anonymize IP address for user $userId ($sql)"); |
7197
|
|
|
} |
7198
|
|
|
|
7199
|
|
|
$table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS); |
7200
|
|
|
$sql = "UPDATE $table set user_ip = '$substitute' WHERE user_id = $userId"; |
7201
|
|
|
$res = Database::query($sql); |
7202
|
|
|
if ($res === false && $debug > 0) { |
7203
|
|
|
error_log("Could not anonymize IP address for user $userId ($sql)"); |
7204
|
|
|
} |
7205
|
|
|
|
7206
|
|
|
$table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES); |
7207
|
|
|
$sql = "UPDATE $table set user_ip = '$substitute' WHERE exe_user_id = $userId"; |
7208
|
|
|
$res = Database::query($sql); |
7209
|
|
|
if ($res === false && $debug > 0) { |
7210
|
|
|
error_log("Could not anonymize IP address for user $userId ($sql)"); |
7211
|
|
|
} |
7212
|
|
|
|
7213
|
|
|
$table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN); |
7214
|
|
|
$sql = "UPDATE $table set user_ip = '$substitute' WHERE login_user_id = $userId"; |
7215
|
|
|
$res = Database::query($sql); |
7216
|
|
|
if ($res === false && $debug > 0) { |
7217
|
|
|
error_log("Could not anonymize IP address for user $userId ($sql)"); |
7218
|
|
|
} |
7219
|
|
|
|
7220
|
|
|
$table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE); |
7221
|
|
|
$sql = "UPDATE $table set user_ip = '$substitute' WHERE login_user_id = $userId"; |
7222
|
|
|
$res = Database::query($sql); |
7223
|
|
|
if ($res === false && $debug > 0) { |
7224
|
|
|
error_log("Could not anonymize IP address for user $userId ($sql)"); |
7225
|
|
|
} |
7226
|
|
|
|
7227
|
|
|
$table = Database::get_course_table(TABLE_WIKI); |
7228
|
|
|
$sql = "UPDATE $table set user_ip = '$substitute' WHERE user_id = $userId"; |
7229
|
|
|
$res = Database::query($sql); |
7230
|
|
|
if ($res === false && $debug > 0) { |
7231
|
|
|
error_log("Could not anonymize IP address for user $userId ($sql)"); |
7232
|
|
|
} |
7233
|
|
|
|
7234
|
|
|
$table = Database::get_main_table(TABLE_TICKET_MESSAGE); |
7235
|
|
|
$sql = "UPDATE $table set ip_address = '$substitute' WHERE sys_insert_user_id = $userId"; |
7236
|
|
|
$res = Database::query($sql); |
7237
|
|
|
if ($res === false && $debug > 0) { |
7238
|
|
|
error_log("Could not anonymize IP address for user $userId ($sql)"); |
7239
|
|
|
} |
7240
|
|
|
|
7241
|
|
|
$table = Database::get_course_table(TABLE_WIKI); |
7242
|
|
|
$sql = "UPDATE $table set user_ip = '$substitute' WHERE user_id = $userId"; |
7243
|
|
|
$res = Database::query($sql); |
7244
|
|
|
if ($res === false && $debug > 0) { |
7245
|
|
|
error_log("Could not anonymize IP address for user $userId ($sql)"); |
7246
|
|
|
} |
7247
|
|
|
} |
7248
|
|
|
$em->persist($user); |
7249
|
|
|
$em->flush($user); |
7250
|
|
|
Event::addEvent(LOG_USER_ANONYMIZE, LOG_USER_ID, $userId); |
7251
|
|
|
|
7252
|
|
|
return true; |
7253
|
|
|
} |
7254
|
|
|
|
7255
|
|
|
/** |
7256
|
|
|
* @param int $userId |
7257
|
|
|
* |
7258
|
|
|
* @throws Exception |
7259
|
|
|
* |
7260
|
|
|
* @return string |
7261
|
|
|
*/ |
7262
|
|
|
public static function anonymizeUserWithVerification($userId) |
7263
|
|
|
{ |
7264
|
|
|
$allowDelete = api_get_configuration_value('allow_delete_user_for_session_admin'); |
7265
|
|
|
|
7266
|
|
|
$message = ''; |
7267
|
|
|
if (api_is_platform_admin() || |
7268
|
|
|
($allowDelete && api_is_session_admin()) |
7269
|
|
|
) { |
7270
|
|
|
$userToUpdateInfo = api_get_user_info($userId); |
7271
|
|
|
$currentUserId = api_get_user_id(); |
7272
|
|
|
|
7273
|
|
|
if ($userToUpdateInfo && |
7274
|
|
|
api_global_admin_can_edit_admin($userId, null, $allowDelete) |
7275
|
|
|
) { |
7276
|
|
|
if ($userId != $currentUserId && |
7277
|
|
|
self::anonymize($userId) |
7278
|
|
|
) { |
7279
|
|
|
$message = Display::return_message( |
7280
|
|
|
sprintf(get_lang('UserXAnonymized'), $userToUpdateInfo['complete_name_with_username']), |
7281
|
|
|
'confirmation' |
7282
|
|
|
); |
7283
|
|
|
} else { |
7284
|
|
|
$message = Display::return_message( |
7285
|
|
|
sprintf(get_lang('CannotAnonymizeUserX'), $userToUpdateInfo['complete_name_with_username']), |
7286
|
|
|
'error' |
7287
|
|
|
); |
7288
|
|
|
} |
7289
|
|
|
} else { |
7290
|
|
|
$message = Display::return_message( |
7291
|
|
|
sprintf(get_lang('NoPermissionToAnonymizeUserX'), $userToUpdateInfo['complete_name_with_username']), |
7292
|
|
|
'error' |
7293
|
|
|
); |
7294
|
|
|
} |
7295
|
|
|
} |
7296
|
|
|
|
7297
|
|
|
return $message; |
7298
|
|
|
} |
7299
|
|
|
|
7300
|
|
|
/** |
7301
|
|
|
* @param int $userId |
7302
|
|
|
* |
7303
|
|
|
* @throws Exception |
7304
|
|
|
* |
7305
|
|
|
* @return string |
7306
|
|
|
*/ |
7307
|
|
|
public static function deleteUserWithVerification($userId) |
7308
|
|
|
{ |
7309
|
|
|
$allowDelete = api_get_configuration_value('allow_delete_user_for_session_admin'); |
7310
|
|
|
$message = Display::return_message(get_lang('CannotDeleteUser'), 'error'); |
7311
|
|
|
$userToUpdateInfo = api_get_user_info($userId); |
7312
|
|
|
|
7313
|
|
|
// User must exist. |
7314
|
|
|
if (empty($userToUpdateInfo)) { |
7315
|
|
|
return $message; |
7316
|
|
|
} |
7317
|
|
|
|
7318
|
|
|
$currentUserId = api_get_user_id(); |
7319
|
|
|
|
7320
|
|
|
// Cannot delete myself. |
7321
|
|
|
if ($userId == $currentUserId) { |
7322
|
|
|
return $message; |
7323
|
|
|
} |
7324
|
|
|
|
7325
|
|
|
if (api_is_platform_admin() || |
7326
|
|
|
($allowDelete && api_is_session_admin()) |
7327
|
|
|
) { |
7328
|
|
|
if (api_global_admin_can_edit_admin($userId, null, $allowDelete)) { |
7329
|
|
|
if (self::delete_user($userId)) { |
7330
|
|
|
$message = Display::return_message( |
7331
|
|
|
get_lang('UserDeleted').': '.$userToUpdateInfo['complete_name_with_username'], |
7332
|
|
|
'confirmation' |
7333
|
|
|
); |
7334
|
|
|
} else { |
7335
|
|
|
$message = Display::return_message(get_lang('CannotDeleteUserBecauseOwnsCourse'), 'error'); |
7336
|
|
|
} |
7337
|
|
|
} |
7338
|
|
|
} |
7339
|
|
|
|
7340
|
|
|
return $message; |
7341
|
|
|
} |
7342
|
|
|
|
7343
|
|
|
/** |
7344
|
|
|
* @return array |
7345
|
|
|
*/ |
7346
|
|
|
public static function createDataPrivacyExtraFields() |
7347
|
|
|
{ |
7348
|
|
|
self::create_extra_field( |
7349
|
|
|
'request_for_legal_agreement_consent_removal_justification', |
7350
|
|
|
1, //text |
7351
|
|
|
'Request for legal agreement consent removal justification ', |
7352
|
|
|
'' |
7353
|
|
|
); |
7354
|
|
|
|
7355
|
|
|
self::create_extra_field( |
7356
|
|
|
'request_for_delete_account_justification', |
7357
|
|
|
1, //text |
7358
|
|
|
'Request for delete account justification', |
7359
|
|
|
'' |
7360
|
|
|
); |
7361
|
|
|
|
7362
|
|
|
$extraFieldId = self::create_extra_field( |
7363
|
|
|
'request_for_legal_agreement_consent_removal', |
7364
|
|
|
1, //text |
7365
|
|
|
'Request for legal agreement consent removal', |
7366
|
|
|
'' |
7367
|
|
|
); |
7368
|
|
|
|
7369
|
|
|
$extraFieldIdDeleteAccount = self::create_extra_field( |
7370
|
|
|
'request_for_delete_account', |
7371
|
|
|
1, //text |
7372
|
|
|
'Request for delete user account', |
7373
|
|
|
'' |
7374
|
|
|
); |
7375
|
|
|
|
7376
|
|
|
return [ |
7377
|
|
|
'delete_account_extra_field' => $extraFieldIdDeleteAccount, |
7378
|
|
|
'delete_legal' => $extraFieldId, |
7379
|
|
|
]; |
7380
|
|
|
} |
7381
|
|
|
|
7382
|
|
|
/** |
7383
|
|
|
* @param int $userId |
7384
|
|
|
*/ |
7385
|
|
|
public static function cleanUserRequestsOfRemoval($userId) |
7386
|
|
|
{ |
7387
|
|
|
$userId = (int) $userId; |
7388
|
|
|
|
7389
|
|
|
$extraFieldValue = new ExtraFieldValue('user'); |
7390
|
|
|
$extraFieldsToDelete = [ |
7391
|
|
|
'legal_accept', |
7392
|
|
|
'request_for_legal_agreement_consent_removal', |
7393
|
|
|
'request_for_legal_agreement_consent_removal_justification', |
7394
|
|
|
'request_for_delete_account_justification', // just in case delete also this |
7395
|
|
|
'request_for_delete_account', |
7396
|
|
|
]; |
7397
|
|
|
|
7398
|
|
|
foreach ($extraFieldsToDelete as $variable) { |
7399
|
|
|
$value = $extraFieldValue->get_values_by_handler_and_field_variable( |
7400
|
|
|
$userId, |
7401
|
|
|
$variable |
7402
|
|
|
); |
7403
|
|
|
if ($value && isset($value['id'])) { |
7404
|
|
|
$extraFieldValue->delete($value['id']); |
7405
|
|
|
} |
7406
|
|
|
} |
7407
|
|
|
} |
7408
|
|
|
|
7409
|
|
|
/** |
7410
|
|
|
* @param int $searchYear |
7411
|
|
|
* |
7412
|
|
|
* @throws Exception |
7413
|
|
|
* |
7414
|
|
|
* @return array |
7415
|
|
|
*/ |
7416
|
|
|
public static function getSubscribedSessionsByYear(array $userInfo, $searchYear) |
7417
|
|
|
{ |
7418
|
|
|
$timezone = new DateTimeZone(api_get_timezone()); |
7419
|
|
|
|
7420
|
|
|
$sessions = []; |
7421
|
|
|
if (DRH == $userInfo['status']) { |
7422
|
|
|
$sessions = SessionManager::get_sessions_followed_by_drh($userInfo['id']); |
7423
|
|
|
} elseif (api_is_platform_admin(true)) { |
7424
|
|
|
$sessions = SessionManager::getSessionsForAdmin($userInfo['id']); |
7425
|
|
|
} else { |
7426
|
|
|
$sessionsByCategory = self::get_sessions_by_category($userInfo['id'], false, true, true); |
7427
|
|
|
$sessionsByCategory = array_column($sessionsByCategory, 'sessions'); |
7428
|
|
|
|
7429
|
|
|
foreach ($sessionsByCategory as $sessionsInCategory) { |
7430
|
|
|
$sessions = array_merge($sessions, $sessionsInCategory); |
7431
|
|
|
} |
7432
|
|
|
} |
7433
|
|
|
|
7434
|
|
|
$sessions = array_map( |
7435
|
|
|
function ($sessionInfo) { |
7436
|
|
|
if (!isset($sessionInfo['session_id'])) { |
7437
|
|
|
$sessionInfo['session_id'] = $sessionInfo['id']; |
7438
|
|
|
} |
7439
|
|
|
if (!isset($sessionInfo['session_name'])) { |
7440
|
|
|
$sessionInfo['session_name'] = $sessionInfo['name']; |
7441
|
|
|
} |
7442
|
|
|
|
7443
|
|
|
return $sessionInfo; |
7444
|
|
|
}, |
7445
|
|
|
$sessions |
7446
|
|
|
); |
7447
|
|
|
|
7448
|
|
|
$calendarSessions = []; |
7449
|
|
|
|
7450
|
|
|
foreach ($sessions as $sessionInfo) { |
7451
|
|
|
if (!empty($sessionInfo['duration'])) { |
7452
|
|
|
$courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser( |
7453
|
|
|
$sessionInfo['session_id'], |
7454
|
|
|
$userInfo['id'] |
7455
|
|
|
); |
7456
|
|
|
|
7457
|
|
|
if (empty($courseAccess)) { |
7458
|
|
|
continue; |
7459
|
|
|
} |
7460
|
|
|
|
7461
|
|
|
$firstAcessDate = new DateTime(api_get_local_time($courseAccess['login_course_date']), $timezone); |
7462
|
|
|
$lastAccessDate = clone $firstAcessDate; |
7463
|
|
|
$lastAccessDate->modify("+{$sessionInfo['duration']} days"); |
7464
|
|
|
|
7465
|
|
|
$firstAccessYear = (int) $firstAcessDate->format('Y'); |
7466
|
|
|
$lastAccessYear = (int) $lastAccessDate->format('Y'); |
7467
|
|
|
|
7468
|
|
|
if ($firstAccessYear <= $searchYear && $lastAccessYear >= $searchYear) { |
7469
|
|
|
$calendarSessions[$sessionInfo['session_id']] = [ |
7470
|
|
|
'name' => $sessionInfo['session_name'], |
7471
|
|
|
'access_start_date' => $firstAcessDate->format('Y-m-d h:i:s'), |
7472
|
|
|
'access_end_date' => $lastAccessDate->format('Y-m-d h:i:s'), |
7473
|
|
|
]; |
7474
|
|
|
} |
7475
|
|
|
|
7476
|
|
|
continue; |
7477
|
|
|
} |
7478
|
|
|
|
7479
|
|
|
$accessStartDate = !empty($sessionInfo['access_start_date']) |
7480
|
|
|
? new DateTime(api_get_local_time($sessionInfo['access_start_date']), $timezone) |
7481
|
|
|
: null; |
7482
|
|
|
$accessEndDate = !empty($sessionInfo['access_end_date']) |
7483
|
|
|
? new DateTime(api_get_local_time($sessionInfo['access_end_date']), $timezone) |
7484
|
|
|
: null; |
7485
|
|
|
$accessStartYear = $accessStartDate ? (int) $accessStartDate->format('Y') : 0; |
7486
|
|
|
$accessEndYear = $accessEndDate ? (int) $accessEndDate->format('Y') : 0; |
7487
|
|
|
|
7488
|
|
|
$isValid = false; |
7489
|
|
|
|
7490
|
|
|
if ($accessStartYear && $accessEndYear) { |
7491
|
|
|
if ($accessStartYear <= $searchYear && $accessEndYear >= $searchYear) { |
7492
|
|
|
$isValid = true; |
7493
|
|
|
} |
7494
|
|
|
} |
7495
|
|
|
|
7496
|
|
|
if ($accessStartYear && !$accessEndYear) { |
7497
|
|
|
if ($accessStartYear == $searchYear) { |
7498
|
|
|
$isValid = true; |
7499
|
|
|
} |
7500
|
|
|
} |
7501
|
|
|
|
7502
|
|
|
if (!$accessStartYear && $accessEndYear) { |
7503
|
|
|
if ($accessEndYear == $searchYear) { |
7504
|
|
|
$isValid = true; |
7505
|
|
|
} |
7506
|
|
|
} |
7507
|
|
|
|
7508
|
|
|
if ($isValid) { |
7509
|
|
|
$calendarSessions[$sessionInfo['session_id']] = [ |
7510
|
|
|
'name' => $sessionInfo['session_name'], |
7511
|
|
|
'access_start_date' => $accessStartDate ? $accessStartDate->format('Y-m-d h:i:s') : null, |
7512
|
|
|
'access_end_date' => $accessEndDate ? $accessEndDate->format('Y-m-d h:i:s') : null, |
7513
|
|
|
]; |
7514
|
|
|
} |
7515
|
|
|
} |
7516
|
|
|
|
7517
|
|
|
return $calendarSessions; |
7518
|
|
|
} |
7519
|
|
|
|
7520
|
|
|
/** |
7521
|
|
|
* Get sessions info for planification calendar. |
7522
|
|
|
* |
7523
|
|
|
* @param array $sessionsList Session list from UserManager::getSubscribedSessionsByYear |
7524
|
|
|
* @param int $searchYear |
7525
|
|
|
* |
7526
|
|
|
* @throws Exception |
7527
|
|
|
* |
7528
|
|
|
* @return array |
7529
|
|
|
*/ |
7530
|
|
|
public static function getSessionsCalendarByYear(array $sessionsList, $searchYear) |
7531
|
|
|
{ |
7532
|
|
|
$timezone = new DateTimeZone(api_get_timezone()); |
7533
|
|
|
$calendar = []; |
7534
|
|
|
|
7535
|
|
|
foreach ($sessionsList as $sessionId => $sessionInfo) { |
7536
|
|
|
$startDate = $sessionInfo['access_start_date'] |
7537
|
|
|
? new DateTime(api_get_local_time($sessionInfo['access_start_date']), $timezone) |
7538
|
|
|
: null; |
7539
|
|
|
$endDate = $sessionInfo['access_end_date'] |
7540
|
|
|
? new DateTime(api_get_local_time($sessionInfo['access_end_date']), $timezone) |
7541
|
|
|
: null; |
7542
|
|
|
|
7543
|
|
|
$startYear = $startDate ? (int) $startDate->format('Y') : 0; |
7544
|
|
|
$startWeekYear = $startDate ? (int) $startDate->format('o') : 0; |
7545
|
|
|
$startWeek = $startDate ? (int) $startDate->format('W') : 0; |
7546
|
|
|
$endYear = $endDate ? (int) $endDate->format('Y') : 0; |
7547
|
|
|
$endWeekYear = $endDate ? (int) $endDate->format('o') : 0; |
7548
|
|
|
$endWeek = $endDate ? (int) $endDate->format('W') : 0; |
7549
|
|
|
|
7550
|
|
|
$start = $startWeekYear < $searchYear ? 0 : $startWeek - 1; |
7551
|
|
|
$duration = $endWeekYear > $searchYear ? 52 - $start : $endWeek - $start; |
7552
|
|
|
|
7553
|
|
|
$calendar[] = [ |
7554
|
|
|
'id' => $sessionId, |
7555
|
|
|
'name' => $sessionInfo['name'], |
7556
|
|
|
'human_date' => SessionManager::convertSessionDateToString($startDate, $endDate, false, true), |
7557
|
|
|
'start_in_last_year' => $startYear < $searchYear, |
7558
|
|
|
'end_in_next_year' => $endYear > $searchYear, |
7559
|
|
|
'no_start' => !$startWeek, |
7560
|
|
|
'no_end' => !$endWeek, |
7561
|
|
|
'start' => $start, |
7562
|
|
|
'duration' => $duration > 0 ? $duration : 1, |
7563
|
|
|
]; |
7564
|
|
|
} |
7565
|
|
|
|
7566
|
|
|
usort( |
7567
|
|
|
$calendar, |
7568
|
|
|
function ($sA, $sB) { |
7569
|
|
|
if ($sA['start'] == $sB['start']) { |
7570
|
|
|
return 0; |
7571
|
|
|
} |
7572
|
|
|
|
7573
|
|
|
if ($sA['start'] < $sB['start']) { |
7574
|
|
|
return -1; |
7575
|
|
|
} |
7576
|
|
|
|
7577
|
|
|
return 1; |
7578
|
|
|
} |
7579
|
|
|
); |
7580
|
|
|
|
7581
|
|
|
return $calendar; |
7582
|
|
|
} |
7583
|
|
|
|
7584
|
|
|
/** |
7585
|
|
|
* Return the user's full name. Optionally with the username. |
7586
|
|
|
* |
7587
|
|
|
* @param bool $includeUsername Optional. By default username is not included. |
7588
|
|
|
* |
7589
|
|
|
* @return string |
7590
|
|
|
*/ |
7591
|
|
|
public static function formatUserFullName(User $user, $includeUsername = false) |
7592
|
|
|
{ |
7593
|
|
|
$fullName = api_get_person_name($user->getFirstname(), $user->getLastname()); |
7594
|
|
|
|
7595
|
|
|
if ($includeUsername && api_get_configuration_value('hide_username_with_complete_name') !== true) { |
7596
|
|
|
$username = $user->getUsername(); |
7597
|
|
|
|
7598
|
|
|
return "$fullName ($username)"; |
7599
|
|
|
} |
7600
|
|
|
|
7601
|
|
|
return $fullName; |
7602
|
|
|
} |
7603
|
|
|
|
7604
|
|
|
/** |
7605
|
|
|
* @param int $userId |
7606
|
|
|
* |
7607
|
|
|
* @return array |
7608
|
|
|
*/ |
7609
|
|
|
public static function getUserCareers($userId) |
7610
|
|
|
{ |
7611
|
|
|
$table = Database::get_main_table(TABLE_MAIN_USER_CAREER); |
7612
|
|
|
$tableCareer = Database::get_main_table(TABLE_CAREER); |
7613
|
|
|
$userId = (int) $userId; |
7614
|
|
|
|
7615
|
|
|
$sql = "SELECT c.id, c.name |
7616
|
|
|
FROM $table uc |
7617
|
|
|
INNER JOIN $tableCareer c |
7618
|
|
|
ON uc.career_id = c.id |
7619
|
|
|
WHERE user_id = $userId |
7620
|
|
|
ORDER BY uc.created_at |
7621
|
|
|
"; |
7622
|
|
|
$result = Database::query($sql); |
7623
|
|
|
|
7624
|
|
|
return Database::store_result($result, 'ASSOC'); |
7625
|
|
|
} |
7626
|
|
|
|
7627
|
|
|
/** |
7628
|
|
|
* @param int $userId |
7629
|
|
|
* @param int $careerId |
7630
|
|
|
*/ |
7631
|
|
|
public static function addUserCareer($userId, $careerId) |
7632
|
|
|
{ |
7633
|
|
|
if (!api_get_configuration_value('allow_career_users')) { |
7634
|
|
|
return false; |
7635
|
|
|
} |
7636
|
|
|
|
7637
|
|
|
if (self::userHasCareer($userId, $careerId) === false) { |
7638
|
|
|
$params = [ |
7639
|
|
|
'user_id' => $userId, |
7640
|
|
|
'career_id' => $careerId, |
7641
|
|
|
'created_at' => api_get_utc_datetime(), |
7642
|
|
|
'updated_at' => api_get_utc_datetime(), |
7643
|
|
|
]; |
7644
|
|
|
$table = Database::get_main_table(TABLE_MAIN_USER_CAREER); |
7645
|
|
|
Database::insert($table, $params); |
7646
|
|
|
} |
7647
|
|
|
|
7648
|
|
|
return true; |
7649
|
|
|
} |
7650
|
|
|
|
7651
|
|
|
/** |
7652
|
|
|
* @param int $userCareerId |
7653
|
|
|
* @param array $data |
7654
|
|
|
* |
7655
|
|
|
* @return bool |
7656
|
|
|
*/ |
7657
|
|
|
public static function updateUserCareer($userCareerId, $data) |
7658
|
|
|
{ |
7659
|
|
|
if (!api_get_configuration_value('allow_career_users')) { |
7660
|
|
|
return false; |
7661
|
|
|
} |
7662
|
|
|
|
7663
|
|
|
$params = ['extra_data' => $data, 'updated_at' => api_get_utc_datetime()]; |
7664
|
|
|
$table = Database::get_main_table(TABLE_MAIN_USER_CAREER); |
7665
|
|
|
Database::update( |
7666
|
|
|
$table, |
7667
|
|
|
$params, |
7668
|
|
|
['id = ?' => (int) $userCareerId] |
7669
|
|
|
); |
7670
|
|
|
|
7671
|
|
|
return true; |
7672
|
|
|
} |
7673
|
|
|
|
7674
|
|
|
/** |
7675
|
|
|
* @param int $userId |
7676
|
|
|
* @param int $careerId |
7677
|
|
|
* |
7678
|
|
|
* @return array |
7679
|
|
|
*/ |
7680
|
|
|
public static function getUserCareer($userId, $careerId) |
7681
|
|
|
{ |
7682
|
|
|
$userId = (int) $userId; |
7683
|
|
|
$careerId = (int) $careerId; |
7684
|
|
|
$table = Database::get_main_table(TABLE_MAIN_USER_CAREER); |
7685
|
|
|
|
7686
|
|
|
$sql = "SELECT * FROM $table WHERE user_id = $userId AND career_id = $careerId"; |
7687
|
|
|
$result = Database::query($sql); |
7688
|
|
|
|
7689
|
|
|
return Database::fetch_array($result, 'ASSOC'); |
7690
|
|
|
} |
7691
|
|
|
|
7692
|
|
|
/** |
7693
|
|
|
* @param int $userId |
7694
|
|
|
* @param int $careerId |
7695
|
|
|
* |
7696
|
|
|
* @return bool |
7697
|
|
|
*/ |
7698
|
|
|
public static function userHasCareer($userId, $careerId) |
7699
|
|
|
{ |
7700
|
|
|
$userId = (int) $userId; |
7701
|
|
|
$careerId = (int) $careerId; |
7702
|
|
|
$table = Database::get_main_table(TABLE_MAIN_USER_CAREER); |
7703
|
|
|
|
7704
|
|
|
$sql = "SELECT id FROM $table WHERE user_id = $userId AND career_id = $careerId"; |
7705
|
|
|
$result = Database::query($sql); |
7706
|
|
|
|
7707
|
|
|
return Database::num_rows($result) > 0; |
7708
|
|
|
} |
7709
|
|
|
|
7710
|
|
|
/** |
7711
|
|
|
* @param int $userId |
7712
|
|
|
* |
7713
|
|
|
* @throws Exception |
7714
|
|
|
*/ |
7715
|
|
|
public static function deleteUserFiles($userId) |
7716
|
|
|
{ |
7717
|
|
|
$path = self::getUserPathById($userId, 'system'); |
7718
|
|
|
|
7719
|
|
|
$fs = new Filesystem(); |
7720
|
|
|
$fs->remove($path); |
7721
|
|
|
} |
7722
|
|
|
|
7723
|
|
|
public static function redirectToResetPassword($userId) |
7724
|
|
|
{ |
7725
|
|
|
$forceRenew = api_get_configuration_value('force_renew_password_at_first_login'); |
7726
|
|
|
|
7727
|
|
|
if ($forceRenew) { |
7728
|
|
|
$askPassword = self::get_extra_user_data_by_field( |
7729
|
|
|
$userId, |
7730
|
|
|
'ask_new_password' |
7731
|
|
|
); |
7732
|
|
|
|
7733
|
|
|
if (!empty($askPassword) && isset($askPassword['ask_new_password']) && |
7734
|
|
|
1 === (int) $askPassword['ask_new_password'] |
7735
|
|
|
) { |
7736
|
|
|
$uniqueId = api_get_unique_id(); |
7737
|
|
|
$userObj = api_get_user_entity($userId); |
7738
|
|
|
|
7739
|
|
|
$userObj->setConfirmationToken($uniqueId); |
7740
|
|
|
$userObj->setPasswordRequestedAt(new \DateTime()); |
7741
|
|
|
|
7742
|
|
|
Database::getManager()->persist($userObj); |
7743
|
|
|
Database::getManager()->flush(); |
7744
|
|
|
|
7745
|
|
|
$url = api_get_path(WEB_CODE_PATH).'auth/reset.php?token='.$uniqueId; |
7746
|
|
|
api_location($url); |
7747
|
|
|
} |
7748
|
|
|
} |
7749
|
|
|
|
7750
|
|
|
$forceRotateDays = api_get_configuration_value('security_password_rotate_days'); |
7751
|
|
|
$forceRotate = false; |
7752
|
|
|
|
7753
|
|
|
if ($forceRotateDays > 0) { |
7754
|
|
|
// get the date of the last password update recorded |
7755
|
|
|
$lastUpdate = self::get_extra_user_data_by_field( |
7756
|
|
|
$userId, |
7757
|
|
|
'password_updated_at' |
7758
|
|
|
); |
7759
|
|
|
|
7760
|
|
|
if (empty($lastUpdate) or empty($lastUpdate['password_updated_at'])) { |
7761
|
|
|
$userObj = api_get_user_entity($userId); |
7762
|
|
|
$registrationDate = $userObj->getRegistrationDate(); |
7763
|
|
|
$now = new \DateTime(null, new DateTimeZone('UTC')); |
7764
|
|
|
$interval = $now->diff($registrationDate); |
7765
|
|
|
$daysSince = $interval->format('%a'); |
7766
|
|
|
if ($daysSince > $forceRotateDays) { |
7767
|
|
|
$forceRotate = true; |
7768
|
|
|
} |
7769
|
|
|
} else { |
7770
|
|
|
$now = new \DateTime(null, new DateTimeZone('UTC')); |
7771
|
|
|
// In some cases, old records might contain an incomplete Y-m-d H:i:s format |
7772
|
|
|
if (strlen($lastUpdate['password_updated_at']) == 10) { |
7773
|
|
|
$lastUpdate['password_updated_at'] .= ' 00:00:00'; |
7774
|
|
|
} |
7775
|
|
|
if (strlen($lastUpdate['password_updated_at']) == 16) { |
7776
|
|
|
$lastUpdate['password_updated_at'] .= ':00'; |
7777
|
|
|
} |
7778
|
|
|
$date = \DateTime::createFromFormat('Y-m-d H:i:s', $lastUpdate['password_updated_at'], new DateTimeZone('UTC')); |
7779
|
|
|
$interval = $now->diff($date); |
7780
|
|
|
$daysSince = $interval->format('%a'); |
7781
|
|
|
if ($daysSince > $forceRotateDays) { |
7782
|
|
|
$forceRotate = true; |
7783
|
|
|
} |
7784
|
|
|
} |
7785
|
|
|
if ($forceRotate) { |
7786
|
|
|
$uniqueId = api_get_unique_id(); |
7787
|
|
|
$userObj = api_get_user_entity($userId); |
7788
|
|
|
|
7789
|
|
|
$userObj->setConfirmationToken($uniqueId); |
7790
|
|
|
$userObj->setPasswordRequestedAt(new \DateTime()); |
7791
|
|
|
|
7792
|
|
|
Database::getManager()->persist($userObj); |
7793
|
|
|
Database::getManager()->flush(); |
7794
|
|
|
|
7795
|
|
|
$url = api_get_path(WEB_CODE_PATH).'auth/reset.php?token='.$uniqueId.'&rotate=1'; |
7796
|
|
|
api_location($url); |
7797
|
|
|
} |
7798
|
|
|
} |
7799
|
|
|
} |
7800
|
|
|
|
7801
|
|
|
/** |
7802
|
|
|
* It returns the list of user status available. |
7803
|
|
|
* |
7804
|
|
|
* @return array |
7805
|
|
|
*/ |
7806
|
|
|
public static function getUserStatusList() |
7807
|
|
|
{ |
7808
|
|
|
$userStatusConfig = []; |
7809
|
|
|
// it gets the roles to show in creation/edition user |
7810
|
|
|
if (true === api_get_configuration_value('user_status_show_options_enabled')) { |
7811
|
|
|
$userStatusConfig = api_get_configuration_value('user_status_show_option'); |
7812
|
|
|
} |
7813
|
|
|
// it gets the roles to show in creation/edition user (only for admins) |
7814
|
|
|
if (true === api_get_configuration_value('user_status_option_only_for_admin_enabled') && api_is_platform_admin()) { |
7815
|
|
|
$userStatusConfig = api_get_configuration_value('user_status_option_show_only_for_admin'); |
7816
|
|
|
} |
7817
|
|
|
|
7818
|
|
|
$status = []; |
7819
|
|
|
if (!empty($userStatusConfig)) { |
7820
|
|
|
$statusLang = api_get_status_langvars(); |
7821
|
|
|
foreach ($userStatusConfig as $role => $enabled) { |
7822
|
|
|
if ($enabled) { |
7823
|
|
|
$constStatus = constant($role); |
7824
|
|
|
$status[$constStatus] = $statusLang[$constStatus]; |
7825
|
|
|
} |
7826
|
|
|
} |
7827
|
|
|
} else { |
7828
|
|
|
$status[COURSEMANAGER] = get_lang('Teacher'); |
7829
|
|
|
$status[STUDENT] = get_lang('Learner'); |
7830
|
|
|
$status[DRH] = get_lang('Drh'); |
7831
|
|
|
$status[SESSIONADMIN] = get_lang('SessionsAdmin'); |
7832
|
|
|
$status[STUDENT_BOSS] = get_lang('RoleStudentBoss'); |
7833
|
|
|
$status[INVITEE] = get_lang('Invitee'); |
7834
|
|
|
} |
7835
|
|
|
|
7836
|
|
|
return $status; |
7837
|
|
|
} |
7838
|
|
|
|
7839
|
|
|
/** |
7840
|
|
|
* Get the expiration date by user status from configuration value. |
7841
|
|
|
* |
7842
|
|
|
* @param $status |
7843
|
|
|
* |
7844
|
|
|
* @throws Exception |
7845
|
|
|
* |
7846
|
|
|
* @return array |
7847
|
|
|
*/ |
7848
|
|
|
public static function getExpirationDateByRole($status) |
7849
|
|
|
{ |
7850
|
|
|
$status = (int) $status; |
7851
|
|
|
$nbDaysByRole = api_get_configuration_value('user_number_of_days_for_default_expiration_date_per_role'); |
7852
|
|
|
$dates = []; |
7853
|
|
|
if (!empty($nbDaysByRole)) { |
7854
|
|
|
$date = new DateTime(); |
7855
|
|
|
foreach ($nbDaysByRole as $strVariable => $nDays) { |
7856
|
|
|
$constStatus = constant($strVariable); |
7857
|
|
|
if ($status == $constStatus) { |
7858
|
|
|
$duration = "P{$nDays}D"; |
7859
|
|
|
$date->add(new DateInterval($duration)); |
7860
|
|
|
$newExpirationDate = $date->format('Y-m-d H:i'); |
7861
|
|
|
$formatted = api_format_date($newExpirationDate, DATE_TIME_FORMAT_LONG_24H); |
7862
|
|
|
$dates = ['formatted' => $formatted, 'date' => $newExpirationDate]; |
7863
|
|
|
} |
7864
|
|
|
} |
7865
|
|
|
} |
7866
|
|
|
|
7867
|
|
|
return $dates; |
7868
|
|
|
} |
7869
|
|
|
|
7870
|
|
|
public static function getAllowedRolesAsTeacher(): array |
7871
|
|
|
{ |
7872
|
|
|
if (api_get_configuration_value('course_allow_student_role_to_be_teacher')) { |
7873
|
|
|
return [ |
7874
|
|
|
STUDENT, |
7875
|
|
|
COURSEMANAGER, |
7876
|
|
|
SESSIONADMIN, |
7877
|
|
|
]; |
7878
|
|
|
} else { |
7879
|
|
|
return [ |
7880
|
|
|
COURSEMANAGER, |
7881
|
|
|
SESSIONADMIN, |
7882
|
|
|
]; |
7883
|
|
|
} |
7884
|
|
|
} |
7885
|
|
|
|
7886
|
|
|
/** |
7887
|
|
|
* Count users in courses and if they have certificate. |
7888
|
|
|
* This function is resource intensive. |
7889
|
|
|
* |
7890
|
|
|
* @return array |
7891
|
|
|
*/ |
7892
|
|
|
public static function countUsersWhoFinishedCourses() |
7893
|
|
|
{ |
7894
|
|
|
$courses = []; |
7895
|
|
|
$currentAccessUrlId = api_get_current_access_url_id(); |
7896
|
|
|
$sql = "SELECT course.code, cru.user_id |
7897
|
|
|
FROM course_rel_user cru |
7898
|
|
|
JOIN course ON cru.c_id = course.id |
7899
|
|
|
JOIN access_url_rel_user auru on cru.user_id = auru.user_id |
7900
|
|
|
JOIN access_url_rel_course ON course.id = access_url_rel_course.c_id |
7901
|
|
|
WHERE access_url_rel_course.access_url_id = $currentAccessUrlId |
7902
|
|
|
ORDER BY course.code |
7903
|
|
|
"; |
7904
|
|
|
|
7905
|
|
|
$res = Database::query($sql); |
7906
|
|
|
if (Database::num_rows($res) > 0) { |
7907
|
|
|
while ($row = Database::fetch_array($res)) { |
7908
|
|
|
if (!isset($courses[$row['code']])) { |
7909
|
|
|
$courses[$row['code']] = [ |
7910
|
|
|
'subscribed' => 0, |
7911
|
|
|
'finished' => 0, |
7912
|
|
|
]; |
7913
|
|
|
} |
7914
|
|
|
|
7915
|
|
|
$courses[$row['code']]['subscribed']++; |
7916
|
|
|
$entityManager = Database::getManager(); |
7917
|
|
|
$repository = $entityManager->getRepository('ChamiloCoreBundle:GradebookCategory'); |
7918
|
|
|
//todo check when have more than 1 gradebook |
7919
|
|
|
/** @var \Chamilo\CoreBundle\Entity\GradebookCategory $gradebook */ |
7920
|
|
|
$gradebook = $repository->findOneBy(['courseCode' => $row['code']]); |
7921
|
|
|
|
7922
|
|
|
if (!empty($gradebook)) { |
7923
|
|
|
$finished = 0; |
7924
|
|
|
$gb = Category::createCategoryObjectFromEntity($gradebook); |
7925
|
|
|
$finished = $gb->is_certificate_available($row['user_id']); |
7926
|
|
|
if (!empty($finished)) { |
7927
|
|
|
$courses[$row['code']]['finished']++; |
7928
|
|
|
} |
7929
|
|
|
} |
7930
|
|
|
} |
7931
|
|
|
} |
7932
|
|
|
|
7933
|
|
|
return $courses; |
7934
|
|
|
} |
7935
|
|
|
|
7936
|
|
|
/** |
7937
|
|
|
* Count users in sessions and if they have certificate. |
7938
|
|
|
* This function is resource intensive. |
7939
|
|
|
* |
7940
|
|
|
* @return array |
7941
|
|
|
*/ |
7942
|
|
|
public static function countUsersWhoFinishedCoursesInSessions() |
7943
|
|
|
{ |
7944
|
|
|
$coursesInSessions = []; |
7945
|
|
|
$currentAccessUrlId = api_get_current_access_url_id(); |
7946
|
|
|
$sql = "SELECT course.code, srcru.session_id, srcru.user_id, session.name |
7947
|
|
|
FROM session_rel_course_rel_user srcru |
7948
|
|
|
JOIN course ON srcru.c_id = course.id |
7949
|
|
|
JOIN access_url_rel_session aurs on srcru.session_id = aurs.session_id |
7950
|
|
|
JOIN session ON srcru.session_id = session.id |
7951
|
|
|
WHERE aurs.access_url_id = $currentAccessUrlId |
7952
|
|
|
ORDER BY course.code, session.name |
7953
|
|
|
"; |
7954
|
|
|
|
7955
|
|
|
$res = Database::query($sql); |
7956
|
|
|
if (Database::num_rows($res) > 0) { |
7957
|
|
|
while ($row = Database::fetch_array($res)) { |
7958
|
|
|
$index = $row['code'].' ('.$row['name'].')'; |
7959
|
|
|
if (!isset($coursesInSessions[$index])) { |
7960
|
|
|
$coursesInSessions[$index] = [ |
7961
|
|
|
'subscribed' => 0, |
7962
|
|
|
'finished' => 0, |
7963
|
|
|
]; |
7964
|
|
|
} |
7965
|
|
|
|
7966
|
|
|
$coursesInSessions[$index]['subscribed']++; |
7967
|
|
|
$entityManager = Database::getManager(); |
7968
|
|
|
$repository = $entityManager->getRepository('ChamiloCoreBundle:GradebookCategory'); |
7969
|
|
|
/** @var \Chamilo\CoreBundle\Entity\GradebookCategory $gradebook */ |
7970
|
|
|
$gradebook = $repository->findOneBy( |
7971
|
|
|
[ |
7972
|
|
|
'courseCode' => $row['code'], |
7973
|
|
|
'sessionId' => $row['session_id'], |
7974
|
|
|
] |
7975
|
|
|
); |
7976
|
|
|
|
7977
|
|
|
if (!empty($gradebook)) { |
7978
|
|
|
$finished = 0; |
7979
|
|
|
$gb = Category::createCategoryObjectFromEntity($gradebook); |
7980
|
|
|
$finished = $gb->is_certificate_available($row['user_id']); |
7981
|
|
|
if (!empty($finished)) { |
7982
|
|
|
$coursesInSessions[$index]['finished']++; |
7983
|
|
|
} |
7984
|
|
|
} |
7985
|
|
|
} |
7986
|
|
|
} |
7987
|
|
|
|
7988
|
|
|
return $coursesInSessions; |
7989
|
|
|
} |
7990
|
|
|
|
7991
|
|
|
/** |
7992
|
|
|
* Build the active-column of the table to lock or unlock a certain user |
7993
|
|
|
* lock = the user can no longer use this account. |
7994
|
|
|
* |
7995
|
|
|
* @author Patrick Cool <[email protected]>, Ghent University |
7996
|
|
|
* |
7997
|
|
|
* @return string Some HTML-code with the lock/unlock button |
7998
|
|
|
*/ |
7999
|
|
|
public static function getActiveFilterForTable(string $active, string $params, array $row): string |
8000
|
|
|
{ |
8001
|
|
|
if ('1' == $active) { |
8002
|
|
|
$action = 'Lock'; |
8003
|
|
|
$image = 'accept'; |
8004
|
|
|
} elseif ('-1' == $active) { |
8005
|
|
|
$action = 'edit'; |
8006
|
|
|
$image = 'warning'; |
8007
|
|
|
} elseif ('0' == $active) { |
8008
|
|
|
$action = 'Unlock'; |
8009
|
|
|
$image = 'error'; |
8010
|
|
|
} |
8011
|
|
|
|
8012
|
|
|
if ('edit' === $action) { |
|
|
|
|
8013
|
|
|
$langAccountExpired = get_lang('AccountExpired'); |
8014
|
|
|
|
8015
|
|
|
return Display::return_icon( |
8016
|
|
|
$image.'.png', |
|
|
|
|
8017
|
|
|
$langAccountExpired, |
8018
|
|
|
[], |
8019
|
|
|
ICON_SIZE_TINY |
8020
|
|
|
).'<span class="sr-only" aria-hidden="true">'.$langAccountExpired.'</span>'; |
8021
|
|
|
} |
8022
|
|
|
|
8023
|
|
|
if ($row['0'] != api_get_user_id()) { |
8024
|
|
|
$langAction = get_lang(ucfirst($action)); |
8025
|
|
|
// you cannot lock yourself out otherwise you could disable all the |
8026
|
|
|
// accounts including your own => everybody is locked out and nobody |
8027
|
|
|
// can change it anymore. |
8028
|
|
|
return Display::return_icon( |
8029
|
|
|
$image.'.png', |
8030
|
|
|
$langAction, |
8031
|
|
|
['onclick' => 'active_user(this);', 'id' => 'img_'.$row['0'], 'style' => 'cursor: pointer;'], |
8032
|
|
|
ICON_SIZE_TINY |
8033
|
|
|
).'<span class="sr-only" aria-hidden="true">'.$langAction.'</span>'; |
8034
|
|
|
} |
8035
|
|
|
|
8036
|
|
|
return ''; |
8037
|
|
|
} |
8038
|
|
|
|
8039
|
|
|
public static function getScriptFunctionForActiveFilter(): string |
8040
|
|
|
{ |
8041
|
|
|
return 'function active_user(element_div) { |
8042
|
|
|
id_image = $(element_div).attr("id"); |
8043
|
|
|
image_clicked = $(element_div).attr("src"); |
8044
|
|
|
image_clicked_info = image_clicked.split("/"); |
8045
|
|
|
image_real_clicked = image_clicked_info[image_clicked_info.length-1]; |
8046
|
|
|
var status = 1; |
8047
|
|
|
if (image_real_clicked == "accept.png") { |
8048
|
|
|
status = 0; |
8049
|
|
|
} |
8050
|
|
|
user_id = id_image.split("_"); |
8051
|
|
|
ident = "#img_"+user_id[1]; |
8052
|
|
|
if (confirm("'.get_lang('AreYouSureToEditTheUserStatus', '').'")) { |
8053
|
|
|
$.ajax({ |
8054
|
|
|
contentType: "application/x-www-form-urlencoded", |
8055
|
|
|
beforeSend: function(myObject) { |
8056
|
|
|
$(ident).attr("src","'.Display::returnIconPath('loading1.gif').'"); //candy eye stuff |
8057
|
|
|
}, |
8058
|
|
|
type: "GET", |
8059
|
|
|
url: _p.web_ajax + "user_manager.ajax.php?a=active_user", |
8060
|
|
|
data: "user_id=" + user_id[1] + "&status=" + status, |
8061
|
|
|
success: function(data) { |
8062
|
|
|
if (data == 1) { |
8063
|
|
|
$(ident).attr("src", "'.Display::returnIconPath('accept.png', ICON_SIZE_TINY).'"); |
8064
|
|
|
$(ident).attr("title","'.get_lang('Lock').'"); |
8065
|
|
|
} |
8066
|
|
|
if (data == 0) { |
8067
|
|
|
$(ident).attr("src","'.Display::returnIconPath('error.png').'"); |
8068
|
|
|
$(ident).attr("title","'.get_lang('Unlock').'"); |
8069
|
|
|
} |
8070
|
|
|
if (data == -1) { |
8071
|
|
|
$(ident).attr("src", "'.Display::returnIconPath('warning.png').'"); |
8072
|
|
|
$(ident).attr("title","'.get_lang('ActionNotAllowed').'"); |
8073
|
|
|
} |
8074
|
|
|
} |
8075
|
|
|
}); |
8076
|
|
|
} |
8077
|
|
|
}'; |
8078
|
|
|
} |
8079
|
|
|
|
8080
|
|
|
/** |
8081
|
|
|
* Get a list of users with the given e-mail address + their "active" field value (0 or 1). |
8082
|
|
|
* |
8083
|
|
|
* @param string $mail User id |
8084
|
|
|
* |
8085
|
|
|
* @return array List of users e-mails + active field |
8086
|
|
|
*/ |
8087
|
|
|
public static function getUsersByMail(string $mail): array |
8088
|
|
|
{ |
8089
|
|
|
$resultData = Database::select( |
8090
|
|
|
'id, active', |
8091
|
|
|
Database::get_main_table(TABLE_MAIN_USER), |
8092
|
|
|
[ |
8093
|
|
|
'where' => ['email = ?' => $mail], |
8094
|
|
|
], |
8095
|
|
|
'all', |
8096
|
|
|
null |
8097
|
|
|
); |
8098
|
|
|
|
8099
|
|
|
if ($resultData === false) { |
8100
|
|
|
return []; |
8101
|
|
|
} |
8102
|
|
|
|
8103
|
|
|
return $resultData; |
8104
|
|
|
} |
8105
|
|
|
|
8106
|
|
|
/** |
8107
|
|
|
* Get whether we can send an e-mail or not. |
8108
|
|
|
* If the e-mail is not in the database, send the mail. |
8109
|
|
|
* If the e-mail is in the database but none of its occurences is active, don't send. |
8110
|
|
|
* |
8111
|
|
|
* @param string $mail The e-mail address to check |
8112
|
|
|
* |
8113
|
|
|
* @return bool Whether we can send an e-mail or not |
8114
|
|
|
*/ |
8115
|
|
|
public static function isEmailingAllowed(string $mail): bool |
8116
|
|
|
{ |
8117
|
|
|
$list = self::getUsersByMail($mail); |
8118
|
|
|
if (empty($list)) { |
8119
|
|
|
// No e-mail matches, send the mail |
8120
|
|
|
return true; |
8121
|
|
|
} |
8122
|
|
|
$send = false; |
8123
|
|
|
foreach ($list as $id => $user) { |
8124
|
|
|
if ($user['active'] == 1) { |
8125
|
|
|
// as soon as we find at least one active user, send the mail |
8126
|
|
|
return true; |
8127
|
|
|
} |
8128
|
|
|
} |
8129
|
|
|
|
8130
|
|
|
return false; |
8131
|
|
|
} |
8132
|
|
|
|
8133
|
|
|
/** |
8134
|
|
|
* return user hash based on user_id and loggedin user's salt. |
8135
|
|
|
* |
8136
|
|
|
* @param int user_id id of the user for whom we need the hash |
8137
|
|
|
* |
8138
|
|
|
* @return string containing the hash |
8139
|
|
|
*/ |
8140
|
|
|
public static function generateUserHash(int $user_id): string |
8141
|
|
|
{ |
8142
|
|
|
$currentUserId = api_get_user_id(); |
8143
|
|
|
$userManager = self::getManager(); |
8144
|
|
|
/** @var User $user */ |
8145
|
|
|
$user = self::getRepository()->find($currentUserId); |
8146
|
|
|
if (empty($user)) { |
8147
|
|
|
return false; |
|
|
|
|
8148
|
|
|
} |
8149
|
|
|
|
8150
|
|
|
return rawurlencode(api_encrypt_hash($user_id, $user->getSalt())); |
8151
|
|
|
} |
8152
|
|
|
|
8153
|
|
|
/** |
8154
|
|
|
* return decrypted hash or false. |
8155
|
|
|
* |
8156
|
|
|
* @param string hash hash that is to be decrypted |
8157
|
|
|
*/ |
8158
|
|
|
public static function decryptUserHash(string $hash): string |
8159
|
|
|
{ |
8160
|
|
|
$currentUserId = api_get_user_id(); |
8161
|
|
|
$userManager = self::getManager(); |
8162
|
|
|
/** @var User $user */ |
8163
|
|
|
$user = self::getRepository()->find($currentUserId); |
8164
|
|
|
if (empty($user)) { |
8165
|
|
|
return false; |
|
|
|
|
8166
|
|
|
} |
8167
|
|
|
|
8168
|
|
|
return api_decrypt_hash(rawurldecode($hash), $user->getSalt()); |
8169
|
|
|
} |
8170
|
|
|
|
8171
|
|
|
/** |
8172
|
|
|
* @return EncoderFactory |
8173
|
|
|
*/ |
8174
|
|
|
private static function getEncoderFactory() |
8175
|
|
|
{ |
8176
|
|
|
$encryption = self::getPasswordEncryption(); |
8177
|
|
|
$encoders = [ |
8178
|
|
|
'Chamilo\\UserBundle\\Entity\\User' => new \Chamilo\UserBundle\Security\Encoder($encryption), |
8179
|
|
|
]; |
8180
|
|
|
|
8181
|
|
|
return new EncoderFactory($encoders); |
8182
|
|
|
} |
8183
|
|
|
|
8184
|
|
|
/** |
8185
|
|
|
* @return \Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface |
8186
|
|
|
*/ |
8187
|
|
|
private static function getEncoder(User $user) |
8188
|
|
|
{ |
8189
|
|
|
$encoderFactory = self::getEncoderFactory(); |
8190
|
|
|
|
8191
|
|
|
return $encoderFactory->getEncoder($user); |
8192
|
|
|
} |
8193
|
|
|
|
8194
|
|
|
/** |
8195
|
|
|
* Disables or enables a user. |
8196
|
|
|
* |
8197
|
|
|
* @param int $user_id |
8198
|
|
|
* @param int $active Enable or disable |
8199
|
|
|
* |
8200
|
|
|
* @return bool True on success, false on failure |
8201
|
|
|
* @assert (-1,0) === false |
8202
|
|
|
* @assert (1,1) === true |
8203
|
|
|
*/ |
8204
|
|
|
private static function change_active_state($user_id, $active) |
8205
|
|
|
{ |
8206
|
|
|
$user_id = (int) $user_id; |
8207
|
|
|
$active = (int) $active; |
8208
|
|
|
|
8209
|
|
|
if (empty($user_id)) { |
8210
|
|
|
return false; |
8211
|
|
|
} |
8212
|
|
|
|
8213
|
|
|
$table_user = Database::get_main_table(TABLE_MAIN_USER); |
8214
|
|
|
$sql = "UPDATE $table_user SET active = '$active' WHERE id = $user_id"; |
8215
|
|
|
$r = Database::query($sql); |
8216
|
|
|
$ev = LOG_USER_DISABLE; |
8217
|
|
|
if ($active == 1) { |
8218
|
|
|
$ev = LOG_USER_ENABLE; |
8219
|
|
|
} |
8220
|
|
|
if ($r !== false) { |
8221
|
|
|
Event::addEvent($ev, LOG_USER_ID, $user_id); |
8222
|
|
|
} |
8223
|
|
|
|
8224
|
|
|
return $r; |
8225
|
|
|
} |
8226
|
|
|
|
8227
|
|
|
/** |
8228
|
|
|
* Get either a Gravatar URL or complete image tag for a specified email address. |
8229
|
|
|
* |
8230
|
|
|
* @param string $email The email address |
8231
|
|
|
* @param int $s Size in pixels, defaults to 80px [ 1 - 2048 ] |
8232
|
|
|
* @param string $d Default imageset to use [ 404 | mm | identicon | monsterid | wavatar ] |
8233
|
|
|
* @param string $r Maximum rating (inclusive) [ g | pg | r | x ] |
8234
|
|
|
* @param bool $img True to return a complete IMG tag False for just the URL |
8235
|
|
|
* @param array $atts Optional, additional key/value attributes to include in the IMG tag |
8236
|
|
|
* |
8237
|
|
|
* @return string containing either just a URL or a complete image tag |
8238
|
|
|
* @source http://gravatar.com/site/implement/images/php/ |
8239
|
|
|
*/ |
8240
|
|
|
private static function getGravatar( |
8241
|
|
|
$email, |
8242
|
|
|
$s = 80, |
8243
|
|
|
$d = 'mm', |
8244
|
|
|
$r = 'g', |
8245
|
|
|
$img = false, |
8246
|
|
|
$atts = [] |
8247
|
|
|
) { |
8248
|
|
|
$url = 'http://www.gravatar.com/avatar/'; |
8249
|
|
|
if (!empty($_SERVER['HTTPS'])) { |
8250
|
|
|
$url = 'https://secure.gravatar.com/avatar/'; |
8251
|
|
|
} |
8252
|
|
|
$url .= md5(strtolower(trim($email))); |
8253
|
|
|
$url .= "?s=$s&d=$d&r=$r"; |
8254
|
|
|
if ($img) { |
8255
|
|
|
$url = '<img src="'.$url.'"'; |
8256
|
|
|
foreach ($atts as $key => $val) { |
8257
|
|
|
$url .= ' '.$key.'="'.$val.'"'; |
8258
|
|
|
} |
8259
|
|
|
$url .= ' />'; |
8260
|
|
|
} |
8261
|
|
|
|
8262
|
|
|
return $url; |
8263
|
|
|
} |
8264
|
|
|
} |
8265
|
|
|
|
Let?s assume that you have a directory layout like this:
and let?s assume the following content of
Bar.php
:If both files
OtherDir/Foo.php
andSomeDir/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 beforeOtherDir/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: