Completed
Push — 1.11.x ( c88e69...f2c079 )
by José
148:38 queued 115:17
created

UserManager::getUserPicturePathById()   C

Complexity

Conditions 8
Paths 15

Size

Total Lines 51
Code Lines 33

Duplication

Lines 51
Ratio 100 %

Importance

Changes 0
Metric Value
cc 8
eloc 33
nc 15
nop 3
dl 51
loc 51
rs 6.5978
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CoreBundle\Entity\ExtraField as EntityExtraField;
5
use Chamilo\UserBundle\Entity\User;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, User.

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

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

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

// Bar.php
namespace OtherDir;

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

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

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

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

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
6
use Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder;
7
use Symfony\Component\Security\Core\Encoder\EncoderFactory;
8
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
9
use Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder;
10
11
/**
12
 *
13
 * Class UserManager
14
 *
15
 * This library provides functions for user management.
16
 * Include/require it in your code to use its functionality.
17
 * @package chamilo.library
18
 * @author Julio Montoya <[email protected]> Social network groups added 2009/12
19
 *
20
 */
21
class UserManager
22
{
23
    // This constants are deprecated use the constants located in ExtraField
24
    const USER_FIELD_TYPE_TEXT = 1;
25
    const USER_FIELD_TYPE_TEXTAREA = 2;
26
    const USER_FIELD_TYPE_RADIO = 3;
27
    const USER_FIELD_TYPE_SELECT = 4;
28
    const USER_FIELD_TYPE_SELECT_MULTIPLE = 5;
29
    const USER_FIELD_TYPE_DATE = 6;
30
    const USER_FIELD_TYPE_DATETIME = 7;
31
    const USER_FIELD_TYPE_DOUBLE_SELECT = 8;
32
    const USER_FIELD_TYPE_DIVIDER = 9;
33
    const USER_FIELD_TYPE_TAG = 10;
34
    const USER_FIELD_TYPE_TIMEZONE = 11;
35
    const USER_FIELD_TYPE_SOCIAL_PROFILE = 12;
36
    const USER_FIELD_TYPE_FILE = 13;
37
    const USER_FIELD_TYPE_MOBILE_PHONE_NUMBER  = 14;
38
39
    private static $encryptionMethod;
40
41
    /**
42
     * Constructor
43
     * @assert () === null
44
     */
45
    public function __construct()
46
    {
47
    }
48
49
    /**
50
     * Repository is use to query the DB, selects, etc
51
     * @return Chamilo\UserBundle\Entity\Repository\UserRepository
52
     */
53
    public static function getRepository()
54
    {
55
        return Database::getManager()->getRepository('ChamiloUserBundle:User');
56
    }
57
58
    /**
59
     * Create/update/delete methods are available in the UserManager
60
     * (based in the Sonata\UserBundle\Entity\UserManager)
61
     *
62
     * @return Chamilo\UserBundle\Entity\Manager\UserManager
63
     */
64
    public static function getManager()
65
    {
66
        static $userManager;
67
68
        if (!isset($userManager)) {
69
            $encoderFactory = self::getEncoderFactory();
70
            $userManager = new Chamilo\UserBundle\Entity\Manager\UserManager(
71
                $encoderFactory,
72
                new \FOS\UserBundle\Util\Canonicalizer(),
73
                new \FOS\UserBundle\Util\Canonicalizer(),
74
                Database::getManager(),
75
                'Chamilo\\UserBundle\\Entity\\User'
76
            );
77
        }
78
79
        return $userManager;
80
    }
81
82
    /**
83
     * @param string $encryptionMethod
84
     */
85
    public static function setPasswordEncryption($encryptionMethod)
86
    {
87
        self::$encryptionMethod = $encryptionMethod;
88
    }
89
90
    /**
91
     * @return bool|mixed
92
     */
93
    public static function getPasswordEncryption()
94
    {
95
        $encryptionMethod = self::$encryptionMethod;
96
        if (empty($encryptionMethod)) {
97
            $encryptionMethod = api_get_configuration_value('password_encryption');
98
        }
99
100
        return $encryptionMethod;
101
    }
102
103
    /**
104
     * @return EncoderFactory
105
     */
106
    private static function getEncoderFactory()
107
    {
108
        $encryption = self::getPasswordEncryption();
109
        $encoders = array(
110
            'Chamilo\\UserBundle\\Entity\\User' => new \Chamilo\UserBundle\Security\Encoder($encryption)
111
        );
112
113
        $encoderFactory = new EncoderFactory($encoders);
114
115
        return $encoderFactory;
116
    }
117
118
    /**
119
     * @param User $user
120
     *
121
     * @return \Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface
122
     */
123
    private static function getEncoder(User $user)
124
    {
125
        $encoderFactory = self::getEncoderFactory();
126
127
        return $encoderFactory->getEncoder($user);
128
    }
129
130
    /**
131
     * Validates the password
132
     *
133
     * @param $encoded
134
     * @param $raw
135
     * @param $salt
136
     * @return bool
137
     */
138
    public static function isPasswordValid($encoded, $raw, $salt)
139
    {
140
        $encoder = new \Chamilo\UserBundle\Security\Encoder(self::getPasswordEncryption());
141
        $validPassword = $encoder->isPasswordValid($encoded, $raw, $salt);
142
143
        return $validPassword;
144
    }
145
146
    /**
147
     * @param string $raw
148
     * @param User   $user
149
     *
150
     * @return bool
151
     */
152
    public static function encryptPassword($raw, User $user)
153
    {
154
        $encoder = self::getEncoder($user);
155
156
        $encodedPassword = $encoder->encodePassword(
157
            $raw,
158
            $user->getSalt()
159
        );
160
161
        return $encodedPassword;
162
    }
163
164
    /**
165
     * @param int $userId
166
     * @param string $password
167
     *
168
     */
169
    public static function updatePassword($userId, $password)
170
    {
171
        $repository = self::getRepository();
172
        /** @var User $user */
173
        $user = $repository->find($userId);
174
        $userManager = self::getManager();
175
        $user->setPlainPassword($password);
176
        $userManager->updateUser($user, true);
177
    }
178
179
    /**
180
     * Creates a new user for the platform
181
     * @author Hugues Peeters <[email protected]>,
182
     * @author Roan Embrechts <[email protected]>
183
     * @param  string $firstName
184
     * @param  string $lastName
185
     * @param  int    $status (1 for course tutor, 5 for student, 6 for anonymous)
186
     * @param  string $email
187
     * @param  string $loginName
188
     * @param  string $password
189
     * @param  string $official_code Any official code (optional)
190
     * @param  string $language User language    (optional)
191
     * @param  string $phone Phone number    (optional)
192
     * @param  string $picture_uri Picture URI        (optional)
193
     * @param  string $authSource Authentication source    (optional, defaults to 'platform', dependind on constant)
194
     * @param  string $expirationDate Account expiration date (optional, defaults to null)
195
     * @param  int    $active Whether the account is enabled or disabled by default
196
     * @param  int    $hr_dept_id The department of HR in which the user is registered (optional, defaults to 0)
197
     * @param  array  $extra    Extra fields
198
     * @param  string $encrypt_method Encrypt method used if password is given encrypted. Set to an empty string by default
199
     * @param  bool $send_mail
200
     * @param  bool $isAdmin
201
     * @param  string $address
202
     * @param  bool $sendEmailToAllAdmins
203
     * @param FormValidator $form
204
     *
205
     * @return mixed   new user id - if the new user creation succeeds, false otherwise
206
     * @desc The function tries to retrieve user id from the session.
207
     * If it exists, the current user id is the creator id. If a problem arises,
208
     * @assert ('Sam','Gamegie',5,'[email protected]','jo','jo') > 1
209
     * @assert ('Pippin','Took',null,null,'jo','jo') === false
210
     */
211
    public static function create_user(
212
        $firstName,
213
        $lastName,
214
        $status,
215
        $email,
216
        $loginName,
217
        $password,
218
        $official_code = '',
219
        $language = '',
220
        $phone = '',
221
        $picture_uri = '',
222
        $authSource = PLATFORM_AUTH_SOURCE,
223
        $expirationDate = null,
224
        $active = 1,
225
        $hr_dept_id = 0,
226
        $extra = [],
227
        $encrypt_method = '',
228
        $send_mail = false,
229
        $isAdmin = false,
230
        $address = '',
231
        $sendEmailToAllAdmins = false,
232
        $form = null
233
    ) {
234
        $currentUserId = api_get_user_id();
235
        $hook = HookCreateUser::create();
236
        if (!empty($hook)) {
237
            $hook->notifyCreateUser(HOOK_EVENT_TYPE_PRE);
238
        }
239
240
        // First check wether the login already exists
241
        if (!self::is_username_available($loginName)) {
242
            Display::addFlash(
243
                Display::return_message(get_lang('LoginAlreadyTaken'))
244
            );
245
246
            return false;
247
        }
248
249
        global $_configuration;
250
        $original_password = $password;
251
252
        $access_url_id = 1;
253
        if (api_get_multiple_access_url()) {
254
            $access_url_id = api_get_current_access_url_id();
255
        }
256
257 View Code Duplication
        if (isset($_configuration[$access_url_id]) &&
258
            is_array($_configuration[$access_url_id]) &&
259
            isset($_configuration[$access_url_id]['hosting_limit_users']) &&
260
            $_configuration[$access_url_id]['hosting_limit_users'] > 0) {
261
            $num = self::get_number_of_users();
262
            if ($num >= $_configuration[$access_url_id]['hosting_limit_users']) {
263
                api_warn_hosting_contact('hosting_limit_users');
264
                Display::addFlash(Display::return_message(get_lang('PortalUsersLimitReached'), 'warning'));
265
266
                return false;
267
            }
268
        }
269
270 View Code Duplication
        if ($status === 1 &&
271
            isset($_configuration[$access_url_id]) &&
272
            is_array($_configuration[$access_url_id]) &&
273
            isset($_configuration[$access_url_id]['hosting_limit_teachers']) &&
274
            $_configuration[$access_url_id]['hosting_limit_teachers'] > 0
275
        ) {
276
            $num = self::get_number_of_users(1);
277
            if ($num >= $_configuration[$access_url_id]['hosting_limit_teachers']) {
278
                Display::addFlash(Display::return_message(get_lang('PortalTeachersLimitReached'), 'warning'));
279
                api_warn_hosting_contact('hosting_limit_teachers');
280
281
                return false;
282
            }
283
        }
284
285 View Code Duplication
        if (empty($password)) {
286
            if ($authSource === PLATFORM_AUTH_SOURCE) {
287
                Display::addFlash(
288
                    Display::return_message(
289
                        get_lang('ThisFieldIsRequired').': '.get_lang(
290
                            'Password'
291
                        ),
292
                        'warning'
293
                    )
294
                );
295
296
                return false;
297
            }
298
299
            // We use the authSource as password.
300
            // The real validation will be by processed by the auth
301
            // source not Chamilo
302
            $password = $authSource;
303
        }
304
305
        // database table definition
306
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
307
308
        // Checking the user language
309
        $languages = api_get_languages();
310
        $language = strtolower($language);
311
312 View Code Duplication
        if (isset($languages['folder'])) {
313
            if (!in_array($language, $languages['folder'])) {
314
                $language = api_get_setting('platformLanguage');
315
            }
316
        }
317
318
        if (!empty($currentUserId)) {
319
            $creator_id = $currentUserId;
320
        } else {
321
            $creator_id = 0;
322
        }
323
324
        $currentDate = api_get_utc_datetime();
325
        $now = new DateTime();
326
327
        if (empty($expirationDate) || $expirationDate == '0000-00-00 00:00:00') {
328
            // Default expiration date
329
            // if there is a default duration of a valid account then
330
            // we have to change the expiration_date accordingly
331
            // Accept 0000-00-00 00:00:00 as a null value to avoid issues with
332
            // third party code using this method with the previous (pre-1.10)
333
            // value of 0000...
334
            if (api_get_setting('account_valid_duration') != '') {
335
                $expirationDate = new DateTime($currentDate);
336
                $days = intval(api_get_setting('account_valid_duration'));
337
                $expirationDate->modify('+'.$days.' day');
338
            }
339
        } else {
340
            $expirationDate = api_get_utc_datetime($expirationDate);
341
            $expirationDate = new \DateTime($expirationDate, new DateTimeZone('UTC'));
342
        }
343
344
        $userManager = self::getManager();
345
346
        /** @var User $user */
347
        $user = $userManager->createUser();
348
349
        $user
350
            ->setLastname($lastName)
351
            ->setFirstname($firstName)
352
            ->setUsername($loginName)
353
            ->setStatus($status)
354
            ->setPlainPassword($password)
355
            ->setEmail($email)
356
            ->setOfficialCode($official_code)
357
            ->setPictureUri($picture_uri)
358
            ->setCreatorId($creator_id)
359
            ->setAuthSource($authSource)
360
            ->setPhone($phone)
361
            ->setAddress($address)
362
            ->setLanguage($language)
363
            ->setRegistrationDate($now)
364
            ->setHrDeptId($hr_dept_id)
365
            ->setActive($active)
366
            ->setEnabled($active)
367
        ;
368
369
        if (!empty($expirationDate)) {
370
            $user->setExpirationDate($expirationDate);
0 ignored issues
show
Bug introduced by
It seems like $expirationDate defined by parameter $expirationDate on line 223 can also be of type string; however, Chamilo\UserBundle\Entit...er::setExpirationDate() does only seem to accept object<DateTime>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
371
        }
372
373
        $userManager->updateUser($user);
374
        $userId = $user->getId();
375
376
        if (!empty($userId)) {
377
            $return = $userId;
378
            $sql = "UPDATE $table_user SET user_id = $return WHERE id = $return";
379
            Database::query($sql);
380
381
            if ($isAdmin) {
382
                UserManager::add_user_as_admin($user);
383
            }
384
385
            if (api_get_multiple_access_url()) {
386
                UrlManager::add_user_to_url($userId, api_get_current_access_url_id());
387
            } else {
388
                //we are adding by default the access_url_user table with access_url_id = 1
389
                UrlManager::add_user_to_url($userId, 1);
390
            }
391
392
            if (is_array($extra) && count($extra) > 0) {
393
                foreach ($extra as $fname => $fvalue) {
394
                    self::update_extra_field_value($userId, $fname, $fvalue);
395
                }
396
            } else {
397
                // Create notify settings by default
398
                self::update_extra_field_value($userId, 'mail_notify_invitation', '1');
399
                self::update_extra_field_value($userId, 'mail_notify_message', '1');
400
                self::update_extra_field_value($userId, 'mail_notify_group_message', '1');
401
            }
402
403
            self::update_extra_field_value($userId, 'already_logged_in', 'false');
404
405
            if (!empty($email) && $send_mail) {
406
                $recipient_name = api_get_person_name(
407
                    $firstName,
408
                    $lastName,
409
                    null,
410
                    PERSON_NAME_EMAIL_ADDRESS
411
                );
412
                $tplSubject = new Template(null, false, false, false, false, false);
413
                $layoutSubject = $tplSubject->get_template(
414
                    'mail/subject_registration_platform.tpl'
415
                );
416
                $emailSubject = $tplSubject->fetch($layoutSubject);
417
                $sender_name = api_get_person_name(
418
                    api_get_setting('administratorName'),
419
                    api_get_setting('administratorSurname'),
420
                    null,
421
                    PERSON_NAME_EMAIL_ADDRESS
422
                );
423
                $email_admin = api_get_setting('emailAdministrator');
424
425
                if (api_is_multiple_url_enabled()) {
426
                    $access_url_id = api_get_current_access_url_id();
427
                    if ($access_url_id != -1) {
428
                        $url = api_get_access_url($access_url_id);
429
                    }
430
                } else {
431
                    $url = api_get_path(WEB_PATH);
432
                }
433
                $tplContent = new Template(null, false, false, false, false, false);
434
                // variables for the default template
435
                $tplContent->assign('complete_name', stripslashes(api_get_person_name($firstName, $lastName)));
436
                $tplContent->assign('login_name', $loginName);
437
                $tplContent->assign('original_password', stripslashes($original_password));
438
                $tplContent->assign('mailWebPath', $url);
439
440
                $layoutContent = $tplContent->get_template('mail/content_registration_platform.tpl');
441
                $emailBody = $tplContent->fetch($layoutContent);
442
                /* MANAGE EVENT WITH MAIL */
443
                if (EventsMail::check_if_using_class('user_registration')) {
444
                    $values["about_user"] = $return;
445
                    $values["password"] = $original_password;
446
                    $values["send_to"] = array($return);
447
                    $values["prior_lang"] = null;
448
                    EventsDispatcher::events('user_registration', $values);
449
                } else {
450
                    $phoneNumber = isset($extra['mobile_phone_number']) ? $extra['mobile_phone_number'] : null;
451
452
                    $additionalParameters = array(
453
                        'smsType' => SmsPlugin::WELCOME_LOGIN_PASSWORD,
454
                        'userId' => $return,
455
                        'mobilePhoneNumber' => $phoneNumber,
456
                        'password' => $original_password
457
                    );
458
459
                    api_mail_html(
460
                        $recipient_name,
461
                        $email,
462
                        $emailSubject,
463
                        $emailBody,
464
                        $sender_name,
465
                        $email_admin,
466
                        null,
467
                        null,
468
                        null,
469
                        $additionalParameters
470
                    );
471
                }
472
473
                if ($sendEmailToAllAdmins) {
474
                    $adminList = UserManager::get_all_administrators();
475
476
                    $tplContent = new Template(null, false, false, false, false, false);
477
                    // variables for the default template
478
                    $tplContent->assign('complete_name', stripslashes(api_get_person_name($firstName, $lastName)));
479
                    $tplContent->assign('user_added', $user);
480
                    /** @var FormValidator $form */
481
                    $form->freeze();
482
                    $form->removeElement('submit');
483
                    $formData = $form->returnForm();
484
                    $url = api_get_path(WEB_CODE_PATH).'admin/user_information.php?user_id='.$user->getId();
485
                    $tplContent->assign('link', Display::url($url, $url));
486
                    $tplContent->assign('form', $formData);
487
488
                    $layoutContent = $tplContent->get_template('mail/content_registration_platform_to_admin.tpl');
489
                    $emailBody = $tplContent->fetch($layoutContent);
490
                    $subject = get_lang('UserAdded');
491
492
                    foreach ($adminList as $adminId => $data) {
493
                        MessageManager::send_message_simple($adminId, $subject, $emailBody);
494
                    }
495
496
                }
497
                /* ENDS MANAGE EVENT WITH MAIL */
498
            }
499
500
            if (!empty($hook)) {
501
                $hook->setEventData(array(
502
                    'return' => $userId,
503
                    'originalPassword' => $original_password
504
                ));
505
                $hook->notifyCreateUser(HOOK_EVENT_TYPE_POST);
506
            }
507
            Event::addEvent(LOG_USER_CREATE, LOG_USER_ID, $userId);
508
        } else {
509
            Display::addFlash(Display::return_message(get_lang('ErrorContactPlatformAdmin')));
510
511
            return false;
512
        }
513
514
        return $return;
515
    }
516
517
    /**
518
     * Can user be deleted? This function checks whether there's a course
519
     * in which the given user is the
520
     * only course administrator. If that is the case, the user can't be
521
     * deleted because the course would remain without a course admin.
522
     * @param int $user_id The user id
523
     * @return boolean true if user can be deleted
524
     * @assert (null) === false
525
     * @assert (-1) === false
526
     * @assert ('abc') === false
527
     */
528
    public static function can_delete_user($user_id)
529
    {
530
        $deny = api_get_configuration_value('deny_delete_users');
531
532
        if ($deny) {
533
            return false;
534
        }
535
536
        $table_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
537
        if ($user_id != strval(intval($user_id))) {
538
            return false;
539
        }
540
        if ($user_id === false) {
541
            return false;
542
        }
543
        $sql = "SELECT * FROM $table_course_user
544
                WHERE status = 1 AND user_id = ".$user_id;
545
        $res = Database::query($sql);
546
        while ($course = Database::fetch_object($res)) {
547
            $sql = "SELECT id FROM $table_course_user
548
                    WHERE status=1 AND c_id = " . intval($course->c_id);
549
            $res2 = Database::query($sql);
550
            if (Database::num_rows($res2) == 1) {
551
552
                return false;
553
            }
554
        }
555
556
        return true;
557
    }
558
559
    /**
560
     * Delete a user from the platform, and all its belongings. This is a
561
     * very dangerous function that should only be accessible by
562
     * super-admins. Other roles should only be able to disable a user,
563
     * which removes access to the platform but doesn't delete anything.
564
     * @param int The ID of th user to be deleted
565
     * @return boolean true if user is successfully deleted, false otherwise
566
     * @assert (null) === false
567
     * @assert ('abc') === false
568
     */
569
    public static function delete_user($user_id)
570
    {
571
        if ($user_id != strval(intval($user_id))) {
572
            return false;
573
        }
574
575
        if ($user_id === false) {
576
            return false;
577
        }
578
579
        if (!self::can_delete_user($user_id)) {
580
            return false;
581
        }
582
583
        $table_user = Database :: get_main_table(TABLE_MAIN_USER);
584
        $usergroup_rel_user = Database :: get_main_table(TABLE_USERGROUP_REL_USER);
585
        $table_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
586
        $table_course = Database :: get_main_table(TABLE_MAIN_COURSE);
587
        $table_session = Database :: get_main_table(TABLE_MAIN_SESSION);
588
        $table_admin = Database :: get_main_table(TABLE_MAIN_ADMIN);
589
        $table_session_user = Database :: get_main_table(TABLE_MAIN_SESSION_USER);
590
        $table_session_course_user = Database :: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
591
        $table_group = Database :: get_course_table(TABLE_GROUP_USER);
592
        $table_work = Database :: get_course_table(TABLE_STUDENT_PUBLICATION);
593
594
        // Unsubscribe the user from all groups in all his courses
595
        $sql = "SELECT c.id FROM $table_course c, $table_course_user cu
596
                WHERE
597
                    cu.user_id = '".$user_id."' AND
598
                    relation_type<>".COURSE_RELATION_TYPE_RRHH." AND
599
                    c.id = cu.c_id";
600
601
        $res = Database::query($sql);
602
        while ($course = Database::fetch_object($res)) {
603
            $sql = "DELETE FROM $table_group
604
                    WHERE c_id = {$course->id} AND user_id = $user_id";
605
            Database::query($sql);
606
        }
607
608
        // Unsubscribe user from usergroup_rel_user
609
        $sql = "DELETE FROM $usergroup_rel_user WHERE user_id = '".$user_id."'";
610
        Database::query($sql);
611
612
        // Unsubscribe user from all courses
613
        $sql = "DELETE FROM $table_course_user WHERE user_id = '".$user_id."'";
614
        Database::query($sql);
615
616
        // Unsubscribe user from all courses in sessions
617
        $sql = "DELETE FROM $table_session_course_user WHERE user_id = '".$user_id."'";
618
        Database::query($sql);
619
620
        // If the user was added as a id_coach then set the current admin as coach see BT#
621
        $currentUserId = api_get_user_id();
622
        $sql = "UPDATE $table_session SET id_coach = $currentUserId
623
                WHERE id_coach = '".$user_id."'";
624
        Database::query($sql);
625
626
        $sql = "UPDATE $table_session SET id_coach = $currentUserId
627
                WHERE session_admin_id = '".$user_id."'";
628
        Database::query($sql);
629
630
        // Unsubscribe user from all sessions
631
        $sql = "DELETE FROM $table_session_user
632
                WHERE user_id = '".$user_id."'";
633
        Database::query($sql);
634
635
        // Delete user picture
636
        /* TODO: Logic about api_get_setting('split_users_upload_directory') == 'true'
637
        a user has 4 different sized photos to be deleted. */
638
        $user_info = api_get_user_info($user_id);
639
640
        if (strlen($user_info['picture_uri']) > 0) {
641
            $path = self::getUserPathById($user_id, 'system');
642
            $img_path = $path.$user_info['picture_uri'];
643
            if (file_exists($img_path)) {
644
                unlink($img_path);
645
            }
646
        }
647
648
        // Delete the personal course categories
649
        $course_cat_table = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
650
        $sql = "DELETE FROM $course_cat_table WHERE user_id = '".$user_id."'";
651
        Database::query($sql);
652
653
        // Delete user from the admin table
654
        $sql = "DELETE FROM $table_admin WHERE user_id = '".$user_id."'";
655
        Database::query($sql);
656
657
        // Delete the personal agenda-items from this user
658
        $agenda_table = Database :: get_main_table(TABLE_PERSONAL_AGENDA);
659
        $sql = "DELETE FROM $agenda_table WHERE user = '".$user_id."'";
660
        Database::query($sql);
661
662
        $gradebook_results_table = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_RESULT);
663
        $sql = 'DELETE FROM '.$gradebook_results_table.' WHERE user_id = '.$user_id;
664
        Database::query($sql);
665
666
        $extraFieldValue = new ExtraFieldValue('user');
667
        $extraFieldValue->deleteValuesByItem($user_id);
668
669
        UrlManager::deleteUserFromAllUrls($user_id);
670
671
        if (api_get_setting('allow_social_tool') == 'true') {
672
            $userGroup = new UserGroup();
673
            //Delete user from portal groups
674
            $group_list = $userGroup->get_groups_by_user($user_id);
675
            if (!empty($group_list)) {
676
                foreach ($group_list as $group_id => $data) {
677
                    $userGroup->delete_user_rel_group($user_id, $group_id);
678
                }
679
            }
680
681
            // Delete user from friend lists
682
            SocialManager::remove_user_rel_user($user_id, true);
683
        }
684
685
        // Removing survey invitation
686
        SurveyManager::delete_all_survey_invitations_by_user($user_id);
687
688
        // Delete students works
689
        $sql = "DELETE FROM $table_work WHERE user_id = $user_id AND c_id <> 0";
690
        Database::query($sql);
691
692
        $sql = "UPDATE c_item_property SET to_user_id = NULL
693
                WHERE to_user_id = '".$user_id."'";
694
        Database::query($sql);
695
696
        $sql = "UPDATE c_item_property SET insert_user_id = NULL
697
                WHERE insert_user_id = '".$user_id."'";
698
        Database::query($sql);
699
700
        $sql = "UPDATE c_item_property SET lastedit_user_id = NULL
701
                WHERE lastedit_user_id = '".$user_id."'";
702
        Database::query($sql);
703
704
        // Delete user from database
705
        $sql = "DELETE FROM $table_user WHERE id = '".$user_id."'";
706
        Database::query($sql);
707
708
        // Add event to system log
709
        $user_id_manager = api_get_user_id();
710
711
        Event::addEvent(
712
            LOG_USER_DELETE,
713
            LOG_USER_ID,
714
            $user_id,
715
            api_get_utc_datetime(),
716
            $user_id_manager
717
        );
718
719
        Event::addEvent(
720
            LOG_USER_DELETE,
721
            LOG_USER_OBJECT,
722
            $user_info,
723
            api_get_utc_datetime(),
724
            $user_id_manager
725
        );
726
727
        return true;
728
    }
729
730
    /**
731
     * Deletes users completely. Can be called either as:
732
     * - UserManager :: delete_users(1, 2, 3); or
733
     * - UserManager :: delete_users(array(1, 2, 3));
734
     * @param array|int $ids
735
     * @return boolean  True if at least one user was successfuly deleted. False otherwise.
736
     * @author Laurent Opprecht
737
     * @uses UserManager::delete_user() to actually delete each user
738
     * @assert (null) === false
739
     * @assert (-1) === false
740
     * @assert (array(-1)) === false
741
     */
742
    public static function delete_users($ids = array())
743
    {
744
        $result = false;
745
        $ids = is_array($ids) ? $ids : func_get_args();
746
        if (!is_array($ids) || count($ids) == 0) {
747
            return false;
748
        }
749
        $ids = array_map('intval', $ids);
750
        foreach ($ids as $id) {
751
            if (empty($id) || $id < 1) {
752
                continue;
753
            }
754
            $deleted = self::delete_user($id);
755
            $result = $deleted || $result;
756
        }
757
758
        return $result;
759
    }
760
761
    /**
762
     * Disable users. Can be called either as:
763
     * - UserManager :: deactivate_users(1, 2, 3);
764
     * - UserManager :: deactivate_users(array(1, 2, 3));
765
     * @param array|int $ids
766
     * @return boolean
767
     * @author Laurent Opprecht
768
     * @assert (null) === false
769
     * @assert (array(-1)) === false
770
     */
771 View Code Duplication
    public static function deactivate_users($ids = array())
772
    {
773
        if (empty($ids)) {
774
775
            return false;
776
        }
777
778
        $table_user = Database :: get_main_table(TABLE_MAIN_USER);
779
780
        $ids = is_array($ids) ? $ids : func_get_args();
781
        $ids = array_map('intval', $ids);
782
        $ids = implode(',', $ids);
783
784
        $sql = "UPDATE $table_user SET active = 0 WHERE id IN ($ids)";
785
        $r = Database::query($sql);
786
        if ($r !== false) {
787
            Event::addEvent(LOG_USER_DISABLE, LOG_USER_ID, $ids);
788
        }
789
        return $r;
790
    }
791
792
    /**
793
     * Enable users. Can be called either as:
794
     * - UserManager :: activate_users(1, 2, 3);
795
     * - UserManager :: activate_users(array(1, 2, 3));
796
     * @param array|int IDs of the users to enable
797
     * @return boolean
798
     * @author Laurent Opprecht
799
     * @assert (null) === false
800
     * @assert (array(-1)) === false
801
     */
802 View Code Duplication
    public static function activate_users($ids = array())
803
    {
804
        if (empty($ids)) {
805
806
            return false;
807
        }
808
809
        $table_user = Database :: get_main_table(TABLE_MAIN_USER);
810
811
        $ids = is_array($ids) ? $ids : func_get_args();
812
        $ids = array_map('intval', $ids);
813
        $ids = implode(',', $ids);
814
815
        $sql = "UPDATE $table_user SET active = 1 WHERE id IN ($ids)";
816
        $r = Database::query($sql);
817
        if ($r !== false) {
818
            Event::addEvent(LOG_USER_ENABLE, LOG_USER_ID, $ids);
819
        }
820
        return $r;
821
    }
822
823
    /**
824
     * Update user information with new openid
825
     * @param int $user_id
826
     * @param string $openid
827
     * @return boolean true if the user information was updated
828
     * @assert (false,'') === false
829
     * @assert (-1,'') === false
830
     */
831
    public static function update_openid($user_id, $openid)
832
    {
833
        $table_user = Database:: get_main_table(TABLE_MAIN_USER);
834
        if ($user_id != strval(intval($user_id))) {
835
            return false;
836
        }
837
        if ($user_id === false) {
838
            return false;
839
        }
840
        $sql = "UPDATE $table_user SET
841
                openid='".Database::escape_string($openid)."'";
842
        $sql .= " WHERE id= $user_id";
843
844
        return Database::query($sql);
845
    }
846
847
    /**
848
     * Update user information with all the parameters passed to this function
849
     * @param int The ID of the user to be updated
850
     * @param string The user's firstname
851
     * @param string The user's lastname
852
     * @param string The user's username (login)
853
     * @param string The user's password
854
     * @param string The authentication source (default: "platform")
855
     * @param string The user's e-mail address
856
     * @param int The user's status
857
     * @param string The user's official code (usually just an internal institutional code)
858
     * @param string The user's phone number
859
     * @param string The user's picture URL (internal to the Chamilo directory)
860
     * @param int The user ID of the person who registered this user (optional, defaults to null)
861
     * @param int The department of HR in which the user is registered (optional, defaults to 0)
862
     * @param array A series of additional fields to add to this user as extra fields (optional, defaults to null)
863
     * @return boolean|integer False on error, or the user ID if the user information was updated
864
     * @assert (false, false, false, false, false, false, false, false, false, false, false, false, false) === false
865
     */
866
    public static function update_user(
867
        $user_id,
868
        $firstname,
869
        $lastname,
870
        $username,
871
        $password = null,
872
        $auth_source = null,
873
        $email,
874
        $status,
875
        $official_code,
876
        $phone,
877
        $picture_uri,
878
        $expiration_date,
879
        $active,
880
        $creator_id = null,
881
        $hr_dept_id = 0,
882
        $extra = null,
883
        $language = 'english',
884
        $encrypt_method = '',
885
        $send_email = false,
886
        $reset_password = 0,
887
        $address = null
888
    ) {
889
        $hook = HookUpdateUser::create();
890
        if (!empty($hook)) {
891
            $hook->notifyUpdateUser(HOOK_EVENT_TYPE_PRE);
892
        }
893
        $original_password = $password;
894
895
        if ($user_id != strval(intval($user_id))) {
896
            return false;
897
        }
898
899
        if (empty($user_id)) {
900
            return false;
901
        }
902
903
        $userManager = self::getManager();
904
        /** @var Chamilo\UserBundle\Entity\User $user */
905
        $user = self::getRepository()->find($user_id);
906
907
        if (empty($user)) {
908
            return false;
909
        }
910
911
        if ($reset_password == 0) {
912
            $password = null;
913
            $auth_source = $user->getAuthSource();
914
        } elseif ($reset_password == 1) {
915
            $original_password = $password = api_generate_password();
916
            $auth_source = PLATFORM_AUTH_SOURCE;
917
        } elseif ($reset_password == 2) {
918
            $password = $password;
0 ignored issues
show
Bug introduced by
Why assign $password to itself?

This checks looks for cases where a variable has been assigned to itself.

This assignement can be removed without consequences.

Loading history...
919
            $auth_source = PLATFORM_AUTH_SOURCE;
920
        } elseif ($reset_password == 3) {
921
            $password = $password;
0 ignored issues
show
Bug introduced by
Why assign $password to itself?

This checks looks for cases where a variable has been assigned to itself.

This assignement can be removed without consequences.

Loading history...
922
            $auth_source = $auth_source;
0 ignored issues
show
Bug introduced by
Why assign $auth_source to itself?

This checks looks for cases where a variable has been assigned to itself.

This assignement can be removed without consequences.

Loading history...
923
        }
924
925
        // Checking the user language
926
        $languages = api_get_languages();
927
        if (!in_array($language, $languages['folder'])) {
928
            $language = api_get_setting('platformLanguage');
929
        }
930
931
        $change_active = 0;
932
        $isUserActive = $user->getActive();
933
        if ($isUserActive != $active) {
934
            $change_active = 1;
935
        }
936
937
        $originalUsername = $user->getUsername();
938
939
        // If username is different from original then check if it exists.
940
        if ($originalUsername !== $username) {
941
            $available = self::is_username_available($username);
942
            if ($available === false) {
943
                return false;
944
            }
945
        }
946
947
        if (!empty($expiration_date)) {
948
            $expiration_date = api_get_utc_datetime($expiration_date);
949
            $expiration_date = new \DateTime(
950
                $expiration_date,
951
                new DateTimeZone('UTC')
952
            );
953
        }
954
955
        $user
956
            ->setLastname($lastname)
957
            ->setFirstname($firstname)
958
            ->setUsername($username)
959
            ->setStatus($status)
960
            ->setAuthSource($auth_source)
961
            ->setLanguage($language)
962
            ->setEmail($email)
963
            ->setOfficialCode($official_code)
964
            ->setPhone($phone)
965
            ->setAddress($address)
966
            ->setPictureUri($picture_uri)
967
            ->setExpirationDate($expiration_date)
968
            ->setActive($active)
969
            ->setEnabled($active)
970
            ->setHrDeptId($hr_dept_id)
971
        ;
972
973
        if (!is_null($password)) {
974
            $user->setPlainPassword($password);
975
        }
976
977
        $userManager->updateUser($user, true);
978
979
        if ($change_active == 1) {
980
            if ($active == 1) {
981
                $event_title = LOG_USER_ENABLE;
982
            } else {
983
                $event_title = LOG_USER_DISABLE;
984
            }
985
            Event::addEvent($event_title, LOG_USER_ID, $user_id);
986
        }
987
988
        if (is_array($extra) && count($extra) > 0) {
989
            $res = true;
990
            foreach ($extra as $fname => $fvalue) {
991
                $res = $res && self::update_extra_field_value(
992
                    $user_id,
993
                    $fname,
994
                    $fvalue
995
                );
996
            }
997
        }
998
999
        if (!empty($email) && $send_email) {
1000
            $recipient_name = api_get_person_name($firstname, $lastname, null, PERSON_NAME_EMAIL_ADDRESS);
1001
            $emailsubject = '['.api_get_setting('siteName').'] '.get_lang('YourReg').' '.api_get_setting('siteName');
1002
            $sender_name = api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'), null, PERSON_NAME_EMAIL_ADDRESS);
1003
            $email_admin = api_get_setting('emailAdministrator');
1004
1005
            if (api_is_multiple_url_enabled()) {
1006
                $access_url_id = api_get_current_access_url_id();
1007
                if ($access_url_id != -1) {
1008
                    $url = api_get_access_url($access_url_id);
1009
                    $emailbody = get_lang('Dear')." ".stripslashes(api_get_person_name($firstname, $lastname)).",\n\n".
1010
                        get_lang('YouAreReg')." ".api_get_setting('siteName')." ".get_lang('WithTheFollowingSettings')."\n\n".
1011
                        get_lang('Username')." : ".$username.(($reset_password > 0) ? "\n".
1012
                        get_lang('Pass')." : ".stripslashes($original_password) : "")."\n\n".
1013
                        get_lang('Address')." ".api_get_setting('siteName')." ".get_lang('Is')." : ".$url['url']."\n\n".
1014
                        get_lang('Problem')."\n\n".
1015
                        get_lang('SignatureFormula').",\n\n".
1016
                        api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'))."\n".
1017
                        get_lang('Manager')." ".api_get_setting('siteName')."\nT. ".api_get_setting('administratorTelephone')."\n".
1018
                        get_lang('Email')." : ".api_get_setting('emailAdministrator');
1019
                }
1020
            } else {
1021
                $emailbody = get_lang('Dear')." ".stripslashes(api_get_person_name($firstname, $lastname)).",\n\n".
1022
                    get_lang('YouAreReg')." ".api_get_setting('siteName')." ".get_lang('WithTheFollowingSettings')."\n\n".
1023
                    get_lang('Username')." : ".$username.(($reset_password > 0) ? "\n".
1024
                    get_lang('Pass')." : ".stripslashes($original_password) : "")."\n\n".
1025
                    get_lang('Address')." ".api_get_setting('siteName')." ".get_lang('Is')." : ".api_get_path(WEB_PATH)."\n\n".
1026
                    get_lang('Problem')."\n\n".
1027
                    get_lang('SignatureFormula').",\n\n".
1028
                    api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'))."\n".
1029
                    get_lang('Manager')." ".api_get_setting('siteName')."\nT. ".api_get_setting('administratorTelephone')."\n".
1030
                    get_lang('Email')." : ".api_get_setting('emailAdministrator');
1031
            }
1032
1033
            $emailbody = nl2br($emailbody);
1034
            api_mail_html(
1035
                $recipient_name,
1036
                $email,
1037
                $emailsubject,
1038
                $emailbody,
1039
                $sender_name,
1040
                $email_admin
1041
            );
1042
        }
1043
1044
        if (!empty($hook)) {
1045
            $hook->notifyUpdateUser(HOOK_EVENT_TYPE_POST);
1046
        }
1047
1048
        return $user->getId();
1049
    }
1050
1051
    /**
1052
     * Disables or enables a user
1053
     * @param int $user_id
1054
     * @param int $active Enable or disable
1055
     * @return void
1056
     * @assert (-1,0) === false
1057
     * @assert (1,1) === true
1058
     */
1059
    private static function change_active_state($user_id, $active)
1060
    {
1061
        if (strval(intval($user_id)) != $user_id) {
1062
            return false;
1063
        }
1064
        if ($user_id < 1) {
1065
            return false;
1066
        }
1067
        $user_id = intval($user_id);
1068
        $table_user = Database :: get_main_table(TABLE_MAIN_USER);
1069
        $sql = "UPDATE $table_user SET active = '$active' WHERE id = $user_id";
1070
        $r = Database::query($sql);
1071
        $ev = LOG_USER_DISABLE;
1072
        if ($active == 1) {
1073
            $ev = LOG_USER_ENABLE;
1074
        }
1075
        if ($r !== false) {
1076
            Event::addEvent($ev, LOG_USER_ID, $user_id);
1077
        }
1078
1079
        return $r;
1080
    }
1081
1082
    /**
1083
     * Disables a user
1084
     * @param int User id
1085
     * @return bool
1086
     * @uses UserManager::change_active_state() to actually disable the user
1087
     * @assert (0) === false
1088
     */
1089
    public static function disable($user_id)
1090
    {
1091
        if (empty($user_id)) {
1092
            return false;
1093
        }
1094
        self::change_active_state($user_id, 0);
1095
        return true;
1096
    }
1097
1098
    /**
1099
     * Enable a user
1100
     * @param int User id
1101
     * @return bool
1102
     * @uses UserManager::change_active_state() to actually disable the user
1103
     * @assert (0) === false
1104
     */
1105
    public static function enable($user_id)
1106
    {
1107
        if (empty($user_id)) {
1108
            return false;
1109
        }
1110
        self::change_active_state($user_id, 1);
1111
        return true;
1112
    }
1113
1114
    /**
1115
     * Returns the user's id based on the original id and field name in
1116
     * the extra fields. Returns 0 if no user was found. This function is
1117
     * mostly useful in the context of a web services-based sinchronization
1118
     * @param string Original user id
1119
     * @param string Original field name
1120
     * @return int User id
1121
     * @assert ('0','---') === 0
1122
     */
1123 View Code Duplication
    public static function get_user_id_from_original_id($original_user_id_value, $original_user_id_name)
1124
    {
1125
        $t_uf = Database::get_main_table(TABLE_EXTRA_FIELD);
1126
        $t_ufv = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
1127
        $extraFieldType = EntityExtraField::USER_FIELD_TYPE;
1128
        $sql = "SELECT item_id as user_id
1129
                FROM $t_uf uf
1130
                INNER JOIN $t_ufv ufv
1131
                ON ufv.field_id=uf.id
1132
                WHERE
1133
                    variable='$original_user_id_name' AND
1134
                    value='$original_user_id_value' AND
1135
                    extra_field_type = $extraFieldType
1136
                ";
1137
        $res = Database::query($sql);
1138
        $row = Database::fetch_object($res);
1139
        if ($row) {
1140
            return $row->user_id;
1141
        } else {
1142
            return 0;
1143
        }
1144
    }
1145
1146
    /**
1147
     * Check if a username is available
1148
     * @param string $username the wanted username
1149
     * @return boolean true if the wanted username is available
1150
     * @assert ('') === false
1151
     * @assert ('xyzxyzxyz') === true
1152
     */
1153 View Code Duplication
    public static function is_username_available($username)
1154
    {
1155
        if (empty($username)) {
1156
            return false;
1157
        }
1158
        $table_user = Database :: get_main_table(TABLE_MAIN_USER);
1159
        $sql = "SELECT username FROM $table_user
1160
                WHERE username = '".Database::escape_string($username)."'";
1161
        $res = Database::query($sql);
1162
1163
        return Database::num_rows($res) == 0;
1164
    }
1165
1166
    /**
1167
     * Creates a username using person's names, i.e. creates jmontoya from Julio Montoya.
1168
     * @param string $firstname The first name of the user.
1169
     * @param string $lastname The last name of the user.
1170
     * @return string Suggests a username that contains only ASCII-letters and digits,
1171
     * without check for uniqueness within the system.
1172
     * @author Julio Montoya Armas
1173
     * @author Ivan Tcholakov, 2009 - rework about internationalization.
1174
     * @assert ('','') === false
1175
     * @assert ('a','b') === 'ab'
1176
     */
1177
    public static function create_username($firstname, $lastname)
1178
    {
1179
        if (empty($firstname) && empty($lastname)) {
1180
1181
            return false;
1182
        }
1183
1184
        $firstname = api_substr(preg_replace(USERNAME_PURIFIER, '', $firstname), 0, 1); // The first letter only.
1185
        //Looking for a space in the lastname
1186
        $pos = api_strpos($lastname, ' ');
1187
        if ($pos !== false) {
1188
            $lastname = api_substr($lastname, 0, $pos);
1189
        }
1190
1191
        $lastname = preg_replace(USERNAME_PURIFIER, '', $lastname);
1192
        $username = $firstname.$lastname;
1193
        if (empty($username)) {
1194
            $username = 'user';
1195
        }
1196
1197
        $username = URLify::transliterate($username);
1198
1199
        return strtolower(substr($username, 0, USERNAME_MAX_LENGTH - 3));
1200
    }
1201
1202
    /**
1203
     * Creates a unique username, using:
1204
     * 1. the first name and the last name of a user;
1205
     * 2. an already created username but not checked for uniqueness yet.
1206
     * @param string $firstname                The first name of a given user. If the second parameter $lastname is NULL, then this
1207
     * parameter is treated as username which is to be checked for uniqueness and to be modified when it is necessary.
1208
     * @param string $lastname                The last name of the user.
1209
     * @return string                        Returns a username that contains only ASCII-letters and digits, and that is unique within the system.
1210
     * Note: When the method is called several times with same parameters, its results look like the following sequence: ivan, ivan2, ivan3, ivan4, ...
1211
     * @author Ivan Tcholakov, 2009
1212
     */
1213
    public static function create_unique_username($firstname, $lastname = null)
1214
    {
1215
        if (is_null($lastname)) {
1216
            // In this case the actual input parameter $firstname should contain ASCII-letters and digits only.
1217
            // For making this method tolerant of mistakes, let us transliterate and purify the suggested input username anyway.
1218
            // So, instead of the sentence $username = $firstname; we place the following:
1219
            $username = strtolower(preg_replace(USERNAME_PURIFIER, '', $firstname));
1220
        } else {
1221
            $username = self::create_username($firstname, $lastname);
1222
        }
1223
        if (!self::is_username_available($username)) {
0 ignored issues
show
Security Bug introduced by
It seems like $username defined by self::create_username($firstname, $lastname) on line 1221 can also be of type false; however, UserManager::is_username_available() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
1224
            $i = 2;
1225
            $temp_username = substr($username, 0, USERNAME_MAX_LENGTH - strlen((string) $i)).$i;
1226
            while (!self::is_username_available($temp_username)) {
1227
                $i++;
1228
                $temp_username = substr($username, 0, USERNAME_MAX_LENGTH - strlen((string) $i)).$i;
1229
            }
1230
            $username = $temp_username;
1231
        }
1232
1233
        $username = URLify::transliterate($username);
1234
1235
        return $username;
1236
    }
1237
1238
    /**
1239
     * Modifies a given username accordingly to the specification for valid characters and length.
1240
     * @param $username string          The input username.
1241
     * @param bool $strict (optional)   When this flag is TRUE, the result is guaranteed for full compliance,
1242
     * otherwise compliance may be partial. The default value is FALSE.
1243
     * @return string                   The resulting purified username.
1244
     */
1245
    public static function purify_username($username, $strict = false)
1246
    {
1247
        if ($strict) {
1248
            // 1. Conversion of unacceptable letters (latinian letters with accents for example)
1249
            // into ASCII letters in order they not to be totally removed.
1250
            // 2. Applying the strict purifier.
1251
            // 3. Length limitation.
1252
            $return  = api_get_setting('login_is_email') === 'true' ? substr(preg_replace(USERNAME_PURIFIER_MAIL, '', $username), 0, USERNAME_MAX_LENGTH) : substr(preg_replace(USERNAME_PURIFIER, '', $username), 0, USERNAME_MAX_LENGTH);
1253
            $return = URLify::transliterate($return);
1254
1255
            return $return;
1256
        }
1257
1258
        // 1. Applying the shallow purifier.
1259
        // 2. Length limitation.
1260
        return substr(preg_replace(USERNAME_PURIFIER_SHALLOW, '', $username), 0, USERNAME_MAX_LENGTH);
1261
    }
1262
1263
    /**
1264
     * Checks whether the user id exists in the database
1265
     *
1266
     * @param int User id
1267
     * @return bool True if user id was found, false otherwise
1268
     */
1269 View Code Duplication
    public static function is_user_id_valid($userId)
1270
    {
1271
        $resultData = Database::select(
1272
            'COUNT(1) AS count',
1273
            Database::get_main_table(TABLE_MAIN_USER),
1274
            [
1275
                'where' => ['id = ?' => intval($userId)]
1276
            ],
1277
            'first'
1278
        );
1279
1280
        if ($resultData === false) {
1281
            return false;
1282
        }
1283
1284
        return $resultData['count'] > 0;
1285
    }
1286
1287
    /**
1288
     * Checks whether a given username matches to the specification strictly. The empty username is assumed here as invalid.
1289
     * Mostly this function is to be used in the user interface built-in validation routines for providing feedback while usernames are enterd manually.
1290
     * @param string $username The input username.
1291
     * @return bool Returns TRUE if the username is valid, FALSE otherwise.
1292
     */
1293
    public static function is_username_valid($username)
1294
    {
1295
        return !empty($username) && $username == self::purify_username($username, true);
1296
    }
1297
1298
    /**
1299
     * Checks whether a username is empty. If the username contains whitespace characters, such as spaces, tabulators, newlines, etc.,
1300
     * it is assumed as empty too. This function is safe for validation unpurified data (during importing).
1301
     * @param string $username The given username.
1302
     * @return bool  Returns TRUE if length of the username exceeds the limit, FALSE otherwise.
1303
     */
1304
    public static function is_username_empty($username)
1305
    {
1306
        return (strlen(self::purify_username($username, false)) == 0);
1307
    }
1308
1309
    /**
1310
     * Checks whether a username is too long or not.
1311
     * @param string $username The given username, it should contain only ASCII-letters and digits.
1312
     * @return bool Returns TRUE if length of the username exceeds the limit, FALSE otherwise.
1313
     */
1314
    public static function is_username_too_long($username)
1315
    {
1316
        return (strlen($username) > USERNAME_MAX_LENGTH);
1317
    }
1318
1319
    /**
1320
    * Get the users by ID
1321
    * @param array $ids student ids
1322
    * @param string $active
1323
    * @param string $order
1324
    * @param string $limit
1325
    * @return array $result student information
1326
    */
1327
    public static function get_user_list_by_ids($ids = array(), $active = null, $order = null, $limit = null)
1328
    {
1329
        if (empty($ids)) {
1330
1331
            return array();
1332
        }
1333
1334
        $ids = is_array($ids) ? $ids : array($ids);
1335
        $ids = array_map('intval', $ids);
1336
        $ids = implode(',', $ids);
1337
1338
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
1339
        $sql = "SELECT * FROM $tbl_user WHERE id IN ($ids)";
1340
        if (!is_null($active)) {
1341
            $sql .= ' AND active='.($active ? '1' : '0');
1342
        }
1343
1344
        if (!is_null($order)) {
1345
            $order = Database::escape_string($order);
1346
            $sql .= ' ORDER BY ' . $order;
1347
        }
1348
1349
        if (!is_null($limit)) {
1350
            $limit = Database::escape_string($limit);
1351
            $sql .= ' LIMIT ' . $limit;
1352
        }
1353
1354
        $rs = Database::query($sql);
1355
        $result = array();
1356
        while ($row = Database::fetch_array($rs)) {
1357
            $result[] = $row;
1358
        }
1359
1360
        return $result;
1361
    }
1362
1363
    /**
1364
     * Get a list of users of which the given conditions match with an = 'cond'
1365
     * @param array $conditions a list of condition (example : status=>STUDENT)
1366
     * @param array $order_by a list of fields on which sort
1367
     * @return array An array with all users of the platform.
1368
     * @todo optional course code parameter, optional sorting parameters...
1369
     * @todo security filter order by
1370
     */
1371
    public static function get_user_list(
1372
        $conditions = array(),
1373
        $order_by = array(),
1374
        $limit_from = false,
1375
        $limit_to = false
1376
    ) {
1377
        $user_table = Database :: get_main_table(TABLE_MAIN_USER);
1378
        $return_array = array();
1379
        $sql_query = "SELECT * FROM $user_table";
1380
        if (count($conditions) > 0) {
1381
            $sql_query .= ' WHERE ';
1382
            foreach ($conditions as $field => $value) {
1383
                $field = Database::escape_string($field);
1384
                $value = Database::escape_string($value);
1385
                $sql_query .= "$field = '$value'";
1386
            }
1387
        }
1388 View Code Duplication
        if (count($order_by) > 0) {
1389
            $sql_query .= ' ORDER BY '.Database::escape_string(implode(',', $order_by), null, false);
1390
        }
1391
1392
        if (is_numeric($limit_from) && is_numeric($limit_from)) {
1393
            $limit_from = intval($limit_from);
1394
            $limit_to = intval($limit_to);
1395
            $sql_query .= " LIMIT $limit_from, $limit_to";
1396
        }
1397
        $sql_result = Database::query($sql_query);
1398
        while ($result = Database::fetch_array($sql_result)) {
1399
            $result['complete_name'] = api_get_person_name($result['firstname'], $result['lastname']);
1400
            $return_array[] = $result;
1401
        }
1402
        return $return_array;
1403
    }
1404
1405
    /**
1406
     * Get a list of users of which the given conditions match with a LIKE '%cond%'
1407
     * @param array $conditions a list of condition (exemple : status=>STUDENT)
1408
     * @param array $order_by a list of fields on which sort
1409
     * @return array An array with all users of the platform.
1410
     * @todo optional course code parameter, optional sorting parameters...
1411
     * @todo security filter order_by
1412
     */
1413
    public static function get_user_list_like(
1414
        $conditions = array(),
1415
        $order_by = array(),
1416
        $simple_like = false,
1417
        $condition = 'AND'
1418
    ) {
1419
        $user_table = Database :: get_main_table(TABLE_MAIN_USER);
1420
        $tblAccessUrlRelUser = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
1421
        $return_array = array();
1422
        $sql_query = "SELECT * FROM $user_table ";
1423
1424
        if (api_is_multiple_url_enabled()) {
1425
            $sql_query .= " INNER JOIN $tblAccessUrlRelUser auru ON auru.user_id = user.id ";
1426
        }
1427
1428
        if (count($conditions) > 0) {
1429
            $sql_query .= ' WHERE ';
1430
            $temp_conditions = array();
1431
            foreach ($conditions as $field => $value) {
1432
                $field = Database::escape_string($field);
1433
                $value = Database::escape_string($value);
1434 View Code Duplication
                if ($simple_like) {
1435
                    $temp_conditions[] = $field." LIKE '$value%'";
1436
                } else {
1437
                    $temp_conditions[] = $field.' LIKE \'%'.$value.'%\'';
1438
                }
1439
            }
1440
            if (!empty($temp_conditions)) {
1441
                $sql_query .= implode(' '.$condition.' ', $temp_conditions);
1442
            }
1443
1444
            if (api_is_multiple_url_enabled()) {
1445
                $sql_query .= ' AND auru.access_url_id = ' . api_get_current_access_url_id();
1446
            }
1447
        } else {
1448
            if (api_is_multiple_url_enabled()) {
1449
                $sql_query .= ' WHERE auru.access_url_id = ' . api_get_current_access_url_id();
1450
            }
1451
        }
1452 View Code Duplication
        if (count($order_by) > 0) {
1453
            $sql_query .= ' ORDER BY '.Database::escape_string(implode(',', $order_by), null, false);
1454
        }
1455
        $sql_result = Database::query($sql_query);
1456
        while ($result = Database::fetch_array($sql_result)) {
1457
1458
            $result['complete_name'] = api_get_person_name(
1459
                $result['firstname'],
1460
                $result['lastname']
1461
            );
1462
            $return_array[] = $result;
1463
        }
1464
1465
        return $return_array;
1466
    }
1467
1468
    /**
1469
     * Get user picture URL or path from user ID (returns an array).
1470
     * The return format is a complete path, enabling recovery of the directory
1471
     * with dirname() or the file with basename(). This also works for the
1472
     * functions dealing with the user's productions, as they are located in
1473
     * the same directory.
1474
     * @param   integer   $id User ID
1475
     * @param   string    $type Type of path to return (can be 'system', 'web')
1476
     * @param   array $userInfo user information to avoid query the DB
1477
     * returns the /main/img/unknown.jpg image set it at true
1478
     *
1479
     * @return    array     Array of 2 elements: 'dir' and 'file' which contain
1480
     * the dir and file as the name implies if image does not exist it will
1481
     * return the unknow image if anonymous parameter is true if not it returns an empty array
1482
     */
1483 View Code Duplication
    public static function get_user_picture_path_by_id($id, $type = 'web', $userInfo = [])
1484
    {
1485
        switch ($type) {
1486
            case 'system': // Base: absolute system path.
1487
                $base = api_get_path(SYS_CODE_PATH);
1488
                break;
1489
            case 'web': // Base: absolute web path.
1490
            default:
1491
                $base = api_get_path(WEB_CODE_PATH);
1492
                break;
1493
        }
1494
1495
        $anonymousPath = array(
1496
            'dir' => $base.'img/',
1497
            'file' => 'unknown.jpg',
1498
            'email' => ''
1499
        );
1500
1501
        if (empty($id) || empty($type)) {
1502
            return $anonymousPath;
1503
        }
1504
1505
        $id = intval($id);
1506
        if (empty($userInfo)) {
1507
            $user_table = Database:: get_main_table(TABLE_MAIN_USER);
1508
            $sql = "SELECT email, picture_uri FROM $user_table
1509
                    WHERE id=".$id;
1510
            $res = Database::query($sql);
1511
1512
            if (!Database::num_rows($res)) {
1513
                return $anonymousPath;
1514
            }
1515
            $user = Database::fetch_array($res);
1516
            if (empty($user['picture_uri'])) {
1517
                return $anonymousPath;
1518
            }
1519
        } else {
1520
            $user = $userInfo;
1521
        }
1522
1523
        $pictureFilename = trim($user['picture_uri']);
1524
1525
        $dir = self::getUserPathById($id, $type);
1526
1527
        return array(
1528
            'dir' => $dir,
1529
            'file' => $pictureFilename,
1530
            'email' => $user['email']
1531
        );
1532
    }
1533
1534
    /**
1535
     * *** READ BEFORE REVIEW THIS FUNCTION ***
1536
     * This function is a exact copy from get_user_picture_path_by_id() and it was create it to avoid
1537
     * a recursive calls for get_user_picture_path_by_id() in another functions when you update a user picture
1538
     * in same script, so you can find this function usage in update_user_picture() function.
1539
     *
1540
     * @param   integer   $id User ID
1541
     * @param   string    $type Type of path to return (can be 'system', 'web')
1542
     * @param   array $userInfo user information to avoid query the DB
1543
     * returns the /main/img/unknown.jpg image set it at true
1544
     *
1545
     * @return    array     Array of 2 elements: 'dir' and 'file' which contain
1546
     * the dir and file as the name implies if image does not exist it will
1547
     * return the unknow image if anonymous parameter is true if not it returns an empty array
1548
     */
1549 View Code Duplication
    public static function getUserPicturePathById($id, $type = 'web', $userInfo = [])
1550
    {
1551
        switch ($type) {
1552
            case 'system': // Base: absolute system path.
1553
                $base = api_get_path(SYS_CODE_PATH);
1554
                break;
1555
            case 'web': // Base: absolute web path.
1556
            default:
1557
                $base = api_get_path(WEB_CODE_PATH);
1558
                break;
1559
        }
1560
1561
        $anonymousPath = array(
1562
            'dir' => $base.'img/',
1563
            'file' => 'unknown.jpg',
1564
            'email' => ''
1565
        );
1566
1567
        if (empty($id) || empty($type)) {
1568
            return $anonymousPath;
1569
        }
1570
1571
        $id = intval($id);
1572
1573
        if (empty($userInfo)) {
1574
            $user_table = Database:: get_main_table(TABLE_MAIN_USER);
1575
            $sql = "SELECT email, picture_uri FROM $user_table WHERE id=$id";
1576
            $res = Database::query($sql);
1577
1578
            if (!Database::num_rows($res)) {
1579
                return $anonymousPath;
1580
            }
1581
            $user = Database::fetch_array($res);
1582
1583
            if (empty($user['picture_uri'])) {
1584
                return $anonymousPath;
1585
            }
1586
        } else {
1587
            $user = $userInfo;
1588
        }
1589
1590
        $pictureFilename = trim($user['picture_uri']);
1591
1592
        $dir = self::getUserPathById($id, $type);
1593
1594
        return array(
1595
            'dir' => $dir,
1596
            'file' => $pictureFilename,
1597
            'email' => $user['email']
1598
        );
1599
    }
1600
1601
    /**
1602
     * Get user path from user ID (returns an array).
1603
     * The return format is a complete path to a folder ending with "/"
1604
     * In case the first level of subdirectory of users/ does not exist, the
1605
     * function will attempt to create it. Probably not the right place to do it
1606
     * but at least it avoids headaches in many other places.
1607
     * @param   integer $id User ID
1608
     * @param   string  $type Type of path to return (can be 'system', 'web', 'last')
1609
     * @return  string  User folder path (i.e. /var/www/chamilo/app/upload/users/1/1/)
1610
     */
1611
    public static function getUserPathById($id, $type)
1612
    {
1613
        $id = intval($id);
1614
        if (!$id) {
1615
            return null;
1616
        }
1617
1618
        $userPath = "users/$id/";
1619
        if (api_get_setting('split_users_upload_directory') === 'true') {
1620
            $userPath = 'users/'.substr((string) $id, 0, 1).'/'.$id.'/';
1621
            // In exceptional cases, on some portals, the intermediate base user
1622
            // directory might not have been created. Make sure it is before
1623
            // going further.
1624
1625
            $rootPath = api_get_path(SYS_UPLOAD_PATH) . 'users/' . substr((string) $id, 0, 1);
1626
            if (!is_dir($rootPath)) {
1627
                $perm = api_get_permissions_for_new_directories();
1628
                try {
1629
                    mkdir($rootPath, $perm);
1630
                } catch (Exception $e) {
1631
                    error_log($e->getMessage());
1632
                }
1633
            }
1634
        }
1635
        switch ($type) {
1636
            case 'system': // Base: absolute system path.
1637
                $userPath = api_get_path(SYS_UPLOAD_PATH).$userPath;
1638
                break;
1639
            case 'web': // Base: absolute web path.
1640
                $userPath = api_get_path(WEB_UPLOAD_PATH).$userPath;
1641
                break;
1642
            case 'last': // Only the last part starting with users/
1643
                break;
1644
        }
1645
1646
        return $userPath;
1647
    }
1648
1649
    /**
1650
     * Gets the current user image
1651
     * @param string $user_id
1652
     * @param int $size it can be USER_IMAGE_SIZE_SMALL,
1653
     * USER_IMAGE_SIZE_MEDIUM, USER_IMAGE_SIZE_BIG or  USER_IMAGE_SIZE_ORIGINAL
1654
     * @param bool $addRandomId
1655
     * @param array $userInfo to avoid query the DB
1656
     *
1657
     * @return string
1658
     */
1659
    public static function getUserPicture(
1660
        $user_id,
1661
        $size = USER_IMAGE_SIZE_MEDIUM,
1662
        $addRandomId = true,
1663
        $userInfo = []
1664
    ) {
1665
        // Make sure userInfo is defined. Otherwise, define it!
1666
        if (empty($userInfo) || !is_array($userInfo) || count($userInfo) == 0) {
1667
            if (empty($user_id)) {
1668
                return '';
1669
            } else {
1670
                $userInfo = api_get_user_info($user_id);
1671
            }
1672
        }
1673
        $imageWebPath = self::get_user_picture_path_by_id($user_id, 'web', $userInfo);
0 ignored issues
show
Security Bug introduced by
It seems like $userInfo defined by api_get_user_info($user_id) on line 1670 can also be of type false; however, UserManager::get_user_picture_path_by_id() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
1674
        $pictureWebFile = $imageWebPath['file'];
1675
        $pictureWebDir = $imageWebPath['dir'];
1676
1677
        $pictureAnonymousSize = '128';
1678
        $gravatarSize = 22;
1679
        $realSizeName = 'small_';
1680
1681
        switch ($size) {
1682
            case USER_IMAGE_SIZE_SMALL:
1683
                $pictureAnonymousSize = '32';
1684
                $realSizeName = 'small_';
1685
                $gravatarSize = 22;
1686
                break;
1687
            case USER_IMAGE_SIZE_MEDIUM:
1688
                $pictureAnonymousSize = '64';
1689
                $realSizeName = 'medium_';
1690
                $gravatarSize = 50;
1691
                break;
1692
            case USER_IMAGE_SIZE_ORIGINAL:
1693
                $pictureAnonymousSize = '128';
1694
                $realSizeName = '';
1695
                $gravatarSize = 200;
1696
                break;
1697
            case USER_IMAGE_SIZE_BIG:
1698
                $pictureAnonymousSize = '128';
1699
                $realSizeName = 'big_';
1700
                $gravatarSize = 200;
1701
                break;
1702
        }
1703
1704
        $gravatarEnabled = api_get_setting('gravatar_enabled');
1705
        $anonymousPath = Display::returnIconPath('unknown.png', $pictureAnonymousSize);
1706
        if ($pictureWebFile == 'unknown.jpg' || empty($pictureWebFile)) {
1707
1708
            if ($gravatarEnabled === 'true') {
1709
                $file = self::getGravatar(
1710
                    $imageWebPath['email'],
1711
                    $gravatarSize,
1712
                    api_get_setting('gravatar_type')
1713
                );
1714
1715
                if ($addRandomId) {
1716
                    $file .= '&rand='.uniqid();
1717
                }
1718
1719
                return $file;
1720
            }
1721
1722
            return $anonymousPath;
1723
        }
1724
1725
        $pictureSysPath = self::get_user_picture_path_by_id($user_id, 'system');
1726
1727
        $file = $pictureSysPath['dir'].$realSizeName.$pictureWebFile;
1728
        $picture = '';
1729
        if (file_exists($file)) {
1730
            $picture = $pictureWebDir.$realSizeName.$pictureWebFile;
1731
        } else {
1732
            $file = $pictureSysPath['dir'].$pictureWebFile;
1733
            if (file_exists($file) && !is_dir($file)) {
1734
                $picture = $pictureWebFile['dir'].$pictureWebFile;
1735
            }
1736
        }
1737
1738
        if (empty($picture)) {
1739
            return $anonymousPath;
1740
        }
1741
1742
        if ($addRandomId) {
1743
            $picture .= '?rand='.uniqid();
1744
        }
1745
1746
        return $picture;
1747
    }
1748
1749
    /**
1750
     * Creates new user photos in various sizes of a user, or deletes user photos.
1751
     * Note: This method relies on configuration setting from main/inc/conf/profile.conf.php
1752
     * @param   int $user_id The user internal identification number.
1753
     * @param   string $file The common file name for the newly created photos.
1754
     *                       It will be checked and modified for compatibility with the file system.
1755
     *                       If full name is provided, path component is ignored.
1756
     *                       If an empty name is provided, then old user photos are deleted only,
1757
     * @see     UserManager::delete_user_picture() as the prefered way for deletion.
1758
     * @param   string $source_file The full system name of the image from which user photos will be created.
1759
     * @param   string $cropParameters Optional string that contents "x,y,width,height" of a cropped image format
1760
     * @return  string/bool Returns the resulting common file name of created images which usually should be stored in database.
0 ignored issues
show
Documentation introduced by
The doc-type string/bool could not be parsed: Unknown type name "string/bool" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1761
     * When deletion is requested returns empty string. In case of internal error or negative validation returns FALSE.
1762
     */
1763
    public static function update_user_picture($user_id, $file = null, $source_file = null, $cropParameters = '')
1764
    {
1765
        if (empty($user_id)) {
1766
            return false;
1767
        }
1768
        $delete = empty($file);
1769
        if (empty($source_file)) {
1770
            $source_file = $file;
1771
        }
1772
1773
        // User-reserved directory where photos have to be placed.
1774
        $path_info = self::getUserPicturePathById($user_id, 'system');
1775
1776
        $path = $path_info['dir'];
1777
        // If this directory does not exist - we create it.
1778
        if (!file_exists($path)) {
1779
            mkdir($path, api_get_permissions_for_new_directories(), true);
1780
        }
1781
1782
        // The old photos (if any).
1783
        $old_file = $path_info['file'];
1784
1785
        // Let us delete them.
1786 View Code Duplication
        if ($old_file != 'unknown.jpg') {
1787
            if (KEEP_THE_OLD_IMAGE_AFTER_CHANGE) {
1788
                $prefix = 'saved_'.date('Y_m_d_H_i_s').'_'.uniqid('').'_';
1789
                @rename($path.'small_'.$old_file, $path.$prefix.'small_'.$old_file);
1790
                @rename($path.'medium_'.$old_file, $path.$prefix.'medium_'.$old_file);
1791
                @rename($path.'big_'.$old_file, $path.$prefix.'big_'.$old_file);
1792
                @rename($path.$old_file, $path.$prefix.$old_file);
1793
            } else {
1794
                @unlink($path.'small_'.$old_file);
1795
                @unlink($path.'medium_'.$old_file);
1796
                @unlink($path.'big_'.$old_file);
1797
                @unlink($path.$old_file);
1798
            }
1799
        }
1800
1801
        // Exit if only deletion has been requested. Return an empty picture name.
1802
        if ($delete) {
1803
            return '';
1804
        }
1805
1806
        // Validation 2.
1807
        $allowed_types = api_get_supported_image_extensions();
1808
        $file = str_replace('\\', '/', $file);
1809
        $filename = (($pos = strrpos($file, '/')) !== false) ? substr($file, $pos + 1) : $file;
1810
        $extension = strtolower(substr(strrchr($filename, '.'), 1));
1811
        if (!in_array($extension, $allowed_types)) {
1812
            return false;
1813
        }
1814
1815
        // This is the common name for the new photos.
1816
        if (KEEP_THE_NAME_WHEN_CHANGE_IMAGE && $old_file != 'unknown.jpg') {
1817
            $old_extension = strtolower(substr(strrchr($old_file, '.'), 1));
1818
            $filename = in_array($old_extension, $allowed_types) ? substr($old_file, 0, -strlen($old_extension)) : $old_file;
1819
            $filename = (substr($filename, -1) == '.') ? $filename.$extension : $filename.'.'.$extension;
1820
        } else {
1821
            $filename = api_replace_dangerous_char($filename);
1822
            if (PREFIX_IMAGE_FILENAME_WITH_UID) {
1823
                $filename = uniqid('').'_'.$filename;
1824
            }
1825
            // We always prefix user photos with user ids, so on setting
1826
            // api_get_setting('split_users_upload_directory') === 'true'
1827
            // the correspondent directories to be found successfully.
1828
            $filename = $user_id.'_'.$filename;
1829
        }
1830
1831
        //Crop the image to adjust 1:1 ratio
1832
        $image = new Image($source_file);
1833
        $image->crop($cropParameters);
1834
1835
        // Storing the new photos in 4 versions with various sizes.
1836
        $userPath = self::getUserPathById($user_id, 'system');
1837
1838
        // If this path does not exist - we create it.
1839
        if (!file_exists($userPath)) {
1840
            mkdir($userPath, api_get_permissions_for_new_directories(), true);
1841
        }
1842
        $small = new Image($source_file);
1843
        $small->resize(32);
1844
        $small->send_image($userPath.'small_'.$filename);
1845
        $medium = new Image($source_file);
1846
        $medium->resize(85);
1847
        $medium->send_image($userPath.'medium_'.$filename);
1848
        $normal = new Image($source_file);
1849
        $normal->resize(200);
1850
        $normal->send_image($userPath.$filename);
1851
1852
        $big = new Image($source_file); // This is the original picture.
1853
        $big->send_image($userPath.'big_'.$filename);
1854
1855
        $result = $small && $medium && $normal && $big;
1856
1857
        return $result ? $filename : false;
1858
    }
1859
1860
    /**
1861
     * Update User extra field file type into {user_folder}/{$extra_field}
1862
     * @param int $user_id          The user internal identification number
1863
     * @param string $extra_field   The $extra_field The extra field name
1864
     * @param null $file            The filename
1865
     * @param null $source_file     The temporal filename
1866
     * @return bool|null            return filename if success, but false
1867
     */
1868
    public static function update_user_extra_file($user_id, $extra_field = '', $file = null, $source_file = null)
1869
    {
1870
        // Add Filter
1871
        $source_file = Security::filter_filename($source_file);
1872
        $file = Security::filter_filename($file);
1873
1874
        if (empty($user_id)) {
1875
            return false;
1876
        }
1877
1878
        if (empty($source_file)) {
1879
            $source_file = $file;
1880
        }
1881
1882
        // User-reserved directory where extra file have to be placed.
1883
        $path_info = self::get_user_picture_path_by_id($user_id, 'system');
1884
        $path = $path_info['dir'];
1885
        if (!empty($extra_field)) {
1886
            $path .= $extra_field . '/';
1887
        }
1888
        // If this directory does not exist - we create it.
1889
        if (!file_exists($path)) {
1890
            @mkdir($path, api_get_permissions_for_new_directories(), true);
1891
        }
1892
1893
        if (filter_extension($file)) {
1894
            if (@move_uploaded_file($source_file, $path.$file)) {
1895
                if ($extra_field) {
1896
                    return $extra_field.'/'.$file;
1897
                } else {
1898
                    return $file;
1899
                }
1900
            }
1901
        }
1902
        return false; // this should be returned if anything went wrong with the upload
1903
    }
1904
1905
1906
    /**
1907
     * Deletes user photos.
1908
     * Note: This method relies on configuration setting from main/inc/conf/profile.conf.php
1909
     * @param int $user_id            The user internal identitfication number.
1910
     * @return string/bool            Returns empty string on success, FALSE on error.
0 ignored issues
show
Documentation introduced by
The doc-type string/bool could not be parsed: Unknown type name "string/bool" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1911
     */
1912
    public static function delete_user_picture($user_id)
1913
    {
1914
        return self::update_user_picture($user_id);
1915
    }
1916
1917
    /**
1918
     * Returns an XHTML formatted list of productions for a user, or FALSE if he
1919
     * doesn't have any.
1920
     *
1921
     * If there has been a request to remove a production, the function will return
1922
     * without building the list unless forced to do so by the optional second
1923
     * parameter. This increases performance by avoiding to read through the
1924
     * productions on the filesystem before the removal request has been carried
1925
     * out because they'll have to be re-read afterwards anyway.
1926
     *
1927
     * @param   int $user_id    User id
1928
     * @param   bool $force    Optional parameter to force building after a removal request
1929
     * @param   bool $showDelete
1930
     *
1931
     * @return  string A string containing the XHTML code to display the production list, or FALSE
1932
     */
1933
    public static function build_production_list($user_id, $force = false, $showDelete = false)
1934
    {
1935
        if (!$force && !empty($_POST['remove_production'])) {
1936
1937
            return true; // postpone reading from the filesystem
1938
        }
1939
1940
        $productions = self::get_user_productions($user_id);
1941
1942
        if (empty($productions)) {
1943
1944
            return false;
1945
        }
1946
1947
        $production_dir = self::getUserPathById($user_id, 'web');
1948
        $del_image = Display::returnIconPath('delete.png');
1949
        $add_image = Display::returnIconPath('archive.png');
1950
        $del_text = get_lang('Delete');
1951
        $production_list = '';
1952
        if (count($productions) > 0) {
1953
            $production_list = '<div class="files-production"><ul id="productions">';
1954
            foreach ($productions as $file) {
1955
                $production_list .= '<li><img src="'.$add_image.'" /><a href="'.$production_dir.urlencode($file).'" target="_blank">'.htmlentities($file).'</a>';
1956 View Code Duplication
                if ($showDelete) {
1957
                    $production_list .= '&nbsp;&nbsp;<input style="width:16px;" type="image" name="remove_production['.urlencode($file).']" src="'.$del_image.'" alt="'.$del_text.'" title="'.$del_text.' '.htmlentities($file).'" onclick="javascript: return confirmation(\''.htmlentities($file).'\');" /></li>';
1958
                }
1959
            }
1960
            $production_list .= '</ul></div>';
1961
        }
1962
1963
        return $production_list;
1964
    }
1965
1966
    /**
1967
     * Returns an array with the user's productions.
1968
     *
1969
     * @param    $user_id    User id
1970
     * @return   array  An array containing the user's productions
1971
     */
1972
    public static function get_user_productions($user_id)
1973
    {
1974
        $production_repository = self::getUserPathById($user_id, 'system');
1975
        $productions = array();
1976
1977
        if (is_dir($production_repository)) {
1978
            $handle = opendir($production_repository);
1979
            while ($file = readdir($handle)) {
1980
                if ($file == '.' ||
1981
                    $file == '..' ||
1982
                    $file == '.htaccess' ||
1983
                    is_dir($production_repository.$file)
1984
                ) {
1985
                    // skip current/parent directory and .htaccess
1986
                    continue;
1987
                }
1988
1989
                if (preg_match('/('.$user_id.'|[0-9a-f]{13}|saved)_.+\.(png|jpg|jpeg|gif)$/i', $file)) {
1990
                    // User's photos should not be listed as productions.
1991
                    continue;
1992
                }
1993
                $productions[] = $file;
1994
            }
1995
        }
1996
1997
        return $productions;
1998
    }
1999
2000
    /**
2001
     * Remove a user production.
2002
     *
2003
     * @param int $user_id        User id
2004
     * @param string $production    The production to remove
2005
     */
2006
    public static function remove_user_production($user_id, $production)
2007
    {
2008
        $production_path = self::get_user_picture_path_by_id($user_id, 'system');
2009
        $production_file = $production_path['dir'].$production;
2010
        if (is_file($production_file)) {
2011
            unlink($production_file);
2012
            return true;
2013
        }
2014
        return false;
2015
    }
2016
2017
    /**
2018
     * Update an extra field value for a given user
2019
     * @param    integer   $userId User ID
2020
     * @param    string    $variable Field variable name
2021
     * @param    string    $value Field value
2022
     *
2023
     * @return    boolean    true if field updated, false otherwise
2024
     */
2025 View Code Duplication
    public static function update_extra_field_value($userId, $variable, $value = '')
2026
    {
2027
        $extraFieldValue = new ExtraFieldValue('user');
2028
        $params = [
2029
            'item_id' => $userId,
2030
            'variable' => $variable,
2031
            'value' => $value
2032
        ];
2033
2034
        return $extraFieldValue->save($params);
2035
    }
2036
2037
    /**
2038
     * Get an array of extra fields with field details (type, default value and options)
2039
     * @param    integer    Offset (from which row)
2040
     * @param    integer    Number of items
2041
     * @param    integer    Column on which sorting is made
2042
     * @param    string    Sorting direction
2043
     * @param    boolean    Optional. Whether we get all the fields or just the visible ones
2044
     * @param    int        Optional. Whether we get all the fields with field_filter 1 or 0 or everything
2045
     * @return    array    Extra fields details (e.g. $list[2]['type'], $list[4]['options'][2]['title']
2046
     */
2047
    public static function get_extra_fields(
2048
        $from = 0,
2049
        $number_of_items = 0,
2050
        $column = 5,
2051
        $direction = 'ASC',
2052
        $all_visibility = true,
2053
        $field_filter = null
2054
    ) {
2055
        $fields = array();
2056
        $t_uf = Database :: get_main_table(TABLE_EXTRA_FIELD);
2057
        $t_ufo = Database :: get_main_table(TABLE_EXTRA_FIELD_OPTIONS);
2058
        $columns = array(
2059
            'id',
2060
            'variable',
2061
            'field_type',
2062
            'display_text',
2063
            'default_value',
2064
            'field_order',
2065
            'filter'
2066
        );
2067
        $column = intval($column);
2068
        $sort_direction = '';
2069
        if (in_array(strtoupper($direction), array('ASC', 'DESC'))) {
2070
            $sort_direction = strtoupper($direction);
2071
        }
2072
        $extraFieldType = EntityExtraField::USER_FIELD_TYPE;
2073
        $sqlf = "SELECT * FROM $t_uf WHERE extra_field_type = $extraFieldType ";
2074
        if (!$all_visibility) {
2075
            $sqlf .= " AND visible_to_self = 1 ";
2076
        }
2077
        if (!is_null($field_filter)) {
2078
            $field_filter = intval($field_filter);
2079
            $sqlf .= " AND filter = $field_filter ";
2080
        }
2081
        $sqlf .= " ORDER BY ".$columns[$column]." $sort_direction ";
2082
        if ($number_of_items != 0) {
2083
            $sqlf .= " LIMIT ".intval($from).','.intval($number_of_items);
2084
        }
2085
        $resf = Database::query($sqlf);
2086
        if (Database::num_rows($resf) > 0) {
2087
            while ($rowf = Database::fetch_array($resf)) {
2088
                $fields[$rowf['id']] = array(
2089
                    0 => $rowf['id'],
2090
                    1 => $rowf['variable'],
2091
                    2 => $rowf['field_type'],
2092
                    3 => empty($rowf['display_text']) ? '' : $rowf['display_text'],
2093
                    4 => $rowf['default_value'],
2094
                    5 => $rowf['field_order'],
2095
                    6 => $rowf['visible_to_self'],
2096
                    7 => $rowf['changeable'],
2097
                    8 => $rowf['filter'],
2098
                    9 => array(),
2099
                    10 => '<a name="'.$rowf['id'].'"></a>',
2100
                );
2101
2102
                $sqlo = "SELECT * FROM $t_ufo
2103
                         WHERE field_id = ".$rowf['id']."
2104
                         ORDER BY option_order ASC";
2105
                $reso = Database::query($sqlo);
2106
                if (Database::num_rows($reso) > 0) {
2107
                    while ($rowo = Database::fetch_array($reso)) {
2108
                        $fields[$rowf['id']][9][$rowo['id']] = array(
2109
                            0 => $rowo['id'],
2110
                            1 => $rowo['option_value'],
2111
                            2 => empty($rowo['display_text']) ? '' : $rowo['display_text'],
2112
                            3 => $rowo['option_order']
2113
                        );
2114
                    }
2115
                }
2116
            }
2117
        }
2118
2119
        return $fields;
2120
    }
2121
2122
    /**
2123
     * Build a list of extra file already uploaded in $user_folder/{$extra_field}/
2124
     * @param $user_id
2125
     * @param $extra_field
2126
     * @param bool $force
2127
     * @param bool $showDelete
2128
     * @return bool|string
2129
     */
2130
    public static function build_user_extra_file_list($user_id, $extra_field, $force = false, $showDelete = false)
2131
    {
2132
        if (!$force && !empty($_POST['remove_'.$extra_field])) {
2133
            return true; // postpone reading from the filesystem
2134
        }
2135
2136
        $extra_files = self::get_user_extra_files($user_id, $extra_field);
2137
        if (empty($extra_files)) {
2138
            return false;
2139
        }
2140
2141
        $path_info = self::get_user_picture_path_by_id($user_id, 'web');
2142
        $path = $path_info['dir'];
2143
        $del_image = Display::returnIconPath('delete.png');
2144
2145
        $del_text = get_lang('Delete');
2146
        $extra_file_list = '';
2147
        if (count($extra_files) > 0) {
2148
            $extra_file_list = '<div class="files-production"><ul id="productions">';
2149
            foreach ($extra_files as $file) {
2150
                $filename = substr($file,strlen($extra_field)+1);
2151
                $extra_file_list .= '<li>'.Display::return_icon('archive.png').'<a href="'.$path.$extra_field.'/'.urlencode($filename).'" target="_blank">'.htmlentities($filename).'</a> ';
2152 View Code Duplication
                if ($showDelete) {
2153
                    $extra_file_list .= '<input style="width:16px;" type="image" name="remove_extra_' . $extra_field . '['.urlencode($file).']" src="'.$del_image.'" alt="'.$del_text.'" title="'.$del_text.' '.htmlentities($filename).'" onclick="javascript: return confirmation(\''.htmlentities($filename).'\');" /></li>';
2154
                }
2155
            }
2156
            $extra_file_list .= '</ul></div>';
2157
        }
2158
2159
        return $extra_file_list;
2160
    }
2161
2162
    /**
2163
     * Get valid filenames in $user_folder/{$extra_field}/
2164
     * @param $user_id
2165
     * @param $extra_field
2166
     * @param bool $full_path
2167
     * @return array
2168
     */
2169
    public static function get_user_extra_files($user_id, $extra_field, $full_path = false)
2170
    {
2171
        if (!$full_path) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
2172
            // Nothing to do
2173
        } else {
2174
            $path_info = self::get_user_picture_path_by_id($user_id, 'system');
2175
            $path = $path_info['dir'];
2176
        }
2177
        $extra_data = self::get_extra_user_data_by_field($user_id, $extra_field);
2178
        $extra_files = $extra_data[$extra_field];
2179
        if (is_array($extra_files)) {
2180
            foreach ($extra_files as $key => $value) {
2181
                if (!$full_path) {
2182
                    // Relative path from user folder
2183
                    $files[] = $value;
2184
                } else {
2185
                    $files[] = $path.$value;
2186
                }
2187
            }
2188
        } elseif (!empty($extra_files)) {
2189
            if (!$full_path) {
2190
                // Relative path from user folder
2191
                $files[] = $extra_files;
2192
            } else {
2193
                $files[] = $path.$extra_files;
2194
            }
2195
        }
2196
2197
        return $files; // can be an empty array
2198
    }
2199
2200
    /**
2201
     * Remove an {$extra_file} from the user folder $user_folder/{$extra_field}/
2202
     * @param $user_id
2203
     * @param $extra_field
2204
     * @param $extra_file
2205
     * @return bool
2206
     */
2207
    public static function remove_user_extra_file($user_id, $extra_field, $extra_file)
2208
    {
2209
        $extra_file = Security::filter_filename($extra_file);
2210
        $path_info = self::get_user_picture_path_by_id($user_id, 'system');
2211
        if (strpos($extra_file, $extra_field) !== false) {
2212
            $path_extra_file = $path_info['dir'].$extra_file;
2213
        } else {
2214
            $path_extra_file = $path_info['dir'].$extra_field.'/'.$extra_file;
2215
        }
2216
        if (is_file($path_extra_file)) {
2217
            unlink($path_extra_file);
2218
            return true;
2219
        }
2220
        return false;
2221
    }
2222
2223
    /**
2224
     * Creates a new extra field
2225
     * @param    string    $variable Field's internal variable name
2226
     * @param    int       $fieldType  Field's type
2227
     * @param    string    $displayText Field's language var name
2228
     * @param    string    $default Field's default value
2229
     * @return int
2230
     */
2231 View Code Duplication
    public static function create_extra_field($variable, $fieldType, $displayText, $default)
2232
    {
2233
        $extraField = new ExtraField('user');
2234
        $params = [
2235
            'variable' => $variable,
2236
            'field_type' => $fieldType,
2237
            'display_text' => $displayText,
2238
            'default_value' => $default
2239
        ];
2240
2241
        return $extraField->save($params);
2242
    }
2243
2244
    /**
2245
     * Check if a field is available
2246
     * @param    string    $variable
2247
     * @return    boolean
2248
     */
2249
    public static function is_extra_field_available($variable)
2250
    {
2251
        $extraField = new ExtraField('user');
2252
        $data = $extraField->get_handler_field_info_by_field_variable($variable);
2253
2254
        return !empty($data) ? true : false;
2255
    }
2256
2257
    /**
2258
     * Gets user extra fields data
2259
     * @param    integer    User ID
2260
     * @param    boolean    Whether to prefix the fields indexes with "extra_" (might be used by formvalidator)
2261
     * @param    boolean    Whether to return invisible fields as well
2262
     * @param    boolean    Whether to split multiple-selection fields or not
2263
     * @return    array    Array of fields => value for the given user
2264
     */
2265
    public static function get_extra_user_data(
2266
        $user_id,
2267
        $prefix = false,
2268
        $all_visibility = true,
2269
        $splitmultiple = false,
2270
        $field_filter = null
2271
    ) {
2272
        // A sanity check.
2273 View Code Duplication
        if (empty($user_id)) {
2274
            $user_id = 0;
2275
        } else {
2276
            if ($user_id != strval(intval($user_id)))
2277
                return array();
2278
        }
2279
        $extra_data = array();
2280
        $t_uf = Database::get_main_table(TABLE_EXTRA_FIELD);
2281
        $t_ufv = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
2282
        $user_id = intval($user_id);
2283
        $sql = "SELECT f.id as id, f.variable as fvar, f.field_type as type
2284
                FROM $t_uf f
2285
                WHERE
2286
                    extra_field_type = ".EntityExtraField::USER_FIELD_TYPE."
2287
                ";
2288
        $filter_cond = '';
2289
2290
        if (!$all_visibility) {
2291
            if (isset($field_filter)) {
2292
                $field_filter = intval($field_filter);
2293
                $filter_cond .= " AND filter = $field_filter ";
2294
            }
2295
            $sql .= " AND f.visible_to_self = 1 $filter_cond ";
2296
        } else {
2297
            if (isset($field_filter)) {
2298
                $field_filter = intval($field_filter);
2299
                $sql .= " AND filter = $field_filter ";
2300
            }
2301
        }
2302
2303
        $sql .= " ORDER BY f.field_order";
2304
2305
        $res = Database::query($sql);
2306
        if (Database::num_rows($res) > 0) {
2307
            while ($row = Database::fetch_array($res)) {
2308
                if ($row['type'] == self::USER_FIELD_TYPE_TAG) {
2309
                    $tags = self::get_user_tags_to_string($user_id, $row['id'], false);
2310
                    $extra_data['extra_'.$row['fvar']] = $tags;
2311
                } else {
2312
                    $sqlu = "SELECT value as fval
2313
                            FROM $t_ufv
2314
                            WHERE field_id=".$row['id']." AND item_id = ".$user_id;
2315
                    $resu = Database::query($sqlu);
2316
                    // get default value
2317
                    $sql_df = "SELECT default_value as fval_df FROM $t_uf
2318
                               WHERE id=".$row['id'];
2319
                    $res_df = Database::query($sql_df);
2320
2321
                    if (Database::num_rows($resu) > 0) {
2322
                        $rowu = Database::fetch_array($resu);
2323
                        $fval = $rowu['fval'];
2324
                        if ($row['type'] == self::USER_FIELD_TYPE_SELECT_MULTIPLE) {
2325
                            $fval = explode(';', $rowu['fval']);
2326
                        }
2327
                    } else {
2328
                        $row_df = Database::fetch_array($res_df);
2329
                        $fval = $row_df['fval_df'];
2330
                    }
2331
                    // We get here (and fill the $extra_data array) even if there
2332
                    // is no user with data (we fill it with default values)
2333
                    if ($prefix) {
2334 View Code Duplication
                        if ($row['type'] == self::USER_FIELD_TYPE_RADIO) {
2335
                            $extra_data['extra_'.$row['fvar']]['extra_'.$row['fvar']] = $fval;
2336
                        } else {
2337
                            $extra_data['extra_'.$row['fvar']] = $fval;
2338
                        }
2339 View Code Duplication
                    } else {
2340
                        if ($row['type'] == self::USER_FIELD_TYPE_RADIO) {
2341
                            $extra_data['extra_'.$row['fvar']]['extra_'.$row['fvar']] = $fval;
2342
                        } else {
2343
                            $extra_data[$row['fvar']] = $fval;
2344
                        }
2345
                    }
2346
                }
2347
            }
2348
        }
2349
2350
        return $extra_data;
2351
    }
2352
2353
    /** Get extra user data by field
2354
     * @param int    user ID
2355
     * @param string the internal variable name of the field
2356
     * @return array with extra data info of a user i.e array('field_variable'=>'value');
2357
     */
2358
    public static function get_extra_user_data_by_field(
2359
        $user_id,
2360
        $field_variable,
2361
        $prefix = false,
2362
        $all_visibility = true,
2363
        $splitmultiple = false
2364
    ) {
2365
        // A sanity check.
2366 View Code Duplication
        if (empty($user_id)) {
2367
            $user_id = 0;
2368
        } else {
2369
            if ($user_id != strval(intval($user_id)))
2370
                return array();
2371
        }
2372
        $extra_data = array();
2373
        $t_uf = Database::get_main_table(TABLE_EXTRA_FIELD);
2374
        $t_ufv = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
2375
        $user_id = intval($user_id);
2376
2377
        $sql = "SELECT f.id as id, f.variable as fvar, f.field_type as type
2378
                FROM $t_uf f
2379
                WHERE f.variable = '$field_variable' ";
2380
2381
        if (!$all_visibility) {
2382
            $sql .= " AND f.visible_to_self = 1 ";
2383
        }
2384
2385
        $sql .= " AND extra_field_type = ".EntityExtraField::USER_FIELD_TYPE;
2386
2387
        $sql .= " ORDER BY f.field_order";
2388
2389
        $res = Database::query($sql);
2390
        if (Database::num_rows($res) > 0) {
2391
            while ($row = Database::fetch_array($res)) {
2392
                $sqlu = "SELECT value as fval FROM $t_ufv v INNER JOIN $t_uf f
2393
                         ON (v.field_id = f.id)
2394
                         WHERE
2395
                            extra_field_type = ".EntityExtraField::USER_FIELD_TYPE." AND
2396
                            field_id = ".$row['id']." AND
2397
                            item_id = ".$user_id;
2398
                $resu = Database::query($sqlu);
2399
                $fval = '';
2400
                if (Database::num_rows($resu) > 0) {
2401
                    $rowu = Database::fetch_array($resu);
2402
                    $fval = $rowu['fval'];
2403
                    if ($row['type'] == self::USER_FIELD_TYPE_SELECT_MULTIPLE) {
2404
                        $fval = explode(';', $rowu['fval']);
2405
                    }
2406
                }
2407
                if ($prefix) {
2408
                    $extra_data['extra_'.$row['fvar']] = $fval;
2409
                } else {
2410
                    $extra_data[$row['fvar']] = $fval;
2411
                }
2412
            }
2413
        }
2414
2415
        return $extra_data;
2416
    }
2417
2418
    /**
2419
     * Get the extra field information for a certain field (the options as well)
2420
     * @param  int     $variable The name of the field we want to know everything about
2421
     * @return array   Array containing all the information about the extra profile field
2422
     * (first level of array contains field details, then 'options' sub-array contains options details,
2423
     * as returned by the database)
2424
     * @author Julio Montoya
2425
     * @since v1.8.6
2426
     */
2427
    public static function get_extra_field_information_by_name($variable)
2428
    {
2429
        $extraField = new ExtraField('user');
2430
2431
        return $extraField->get_handler_field_info_by_field_variable($variable);
2432
    }
2433
2434
    /**
2435
     * Get the extra field information for user tag (the options as well)
2436
     * @param  int     $variable The name of the field we want to know everything about
2437
     * @return array   Array containing all the information about the extra profile field
2438
     * (first level of array contains field details, then 'options' sub-array contains options details,
2439
     * as returned by the database)
2440
     * @author José Loguercio
2441
     * @since v1.11.0
2442
     */
2443
    public static function get_extra_field_tags_information_by_name($variable)
2444
    {
2445
        $extraField = new ExtraField('user');
2446
2447
        return $extraField->get_handler_field_info_by_tags($variable);
2448
    }
2449
2450
    /**
2451
     * @param string $type
2452
     *
2453
     * @return array
2454
     */
2455
    public static function get_all_extra_field_by_type($type)
2456
    {
2457
        $extraField = new ExtraField('user');
2458
2459
        return $extraField->get_all_extra_field_by_type($type);
2460
    }
2461
2462
    /**
2463
     * Get all the extra field information of a certain field (also the options)
2464
     *
2465
     * @param int $fieldId the ID of the field we want to know everything of
2466
     * @return array $return containing all th information about the extra profile field
2467
     * @author Julio Montoya
2468
     * @deprecated
2469
     * @since v1.8.6
2470
     */
2471
    public static function get_extra_field_information($fieldId)
2472
    {
2473
        $extraField = new ExtraField('user');
2474
2475
        return $extraField->getFieldInfoByFieldId($fieldId);
2476
    }
2477
2478
    /** Get extra user data by value
2479
     * @param string $variable the internal variable name of the field
2480
     * @param string $value the internal value of the field
2481
     * @param bool $all_visibility
2482
     *
2483
     * @return array with extra data info of a user i.e array('field_variable'=>'value');
2484
     */
2485
     public static function get_extra_user_data_by_value($variable, $value, $all_visibility = true)
2486
    {
2487
        $extraFieldValue = new ExtraFieldValue('user');
2488
        $extraField = new ExtraField('user');
2489
2490
        $info = $extraField->get_handler_field_info_by_field_variable($variable);
2491
2492
        if (false === $info) {
2493
            return [];
2494
        }
2495
2496
        $data = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
2497
            $variable,
2498
            $value,
2499
            false,
2500
            false,
2501
            true
2502
        );
2503
2504
        $result = [];
2505
        if (!empty($data)) {
2506
            foreach ($data as $item) {
2507
                $result[] = $item['item_id'];
2508
            }
2509
        }
2510
2511
        return $result;
2512
    }
2513
2514
    /**
2515
     * Get extra user data by tags value
2516
     *
2517
     * @param int $fieldId the ID of the field we want to know everything of
2518
     * @param string $tag the tag name for search
2519
     * @return array with extra data info of a user
2520
     * @author José Loguercio
2521
     * @since v1.11.0
2522
     */
2523
    public static function get_extra_user_data_by_tags($fieldId, $tag)
2524
    {
2525
        $extraField = new ExtraField('user');
2526
        $result = $extraField->getAllUserPerTag($fieldId, $tag);
2527
        $array = [];
2528
        foreach ($result as $index => $user) {
2529
            $array[] = $user['user_id'];
2530
        }
2531
        return $array;
2532
    }
2533
2534
    /**
2535
     * Get extra user data by field variable
2536
     * @param string    field variable
2537
     * @return array    data
2538
     */
2539
    public static function get_extra_user_data_by_field_variable($field_variable)
2540
    {
2541
        $extra_information_by_variable = self::get_extra_field_information_by_name($field_variable);
2542
        $field_id = intval($extra_information_by_variable['id']);
2543
2544
        $extraField = new ExtraFieldValue('user');
2545
        $data = $extraField->getValuesByFieldId($field_id);
2546
2547
        if (!empty($data) > 0) {
2548
            foreach ($data as $row) {
0 ignored issues
show
Bug introduced by
The expression $data of type array|false is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
2549
                $user_id = $row['item_id'];
2550
                $data[$user_id] = $row;
2551
            }
2552
        }
2553
2554
        return $data;
2555
    }
2556
2557
    /**
2558
     * Get extra user data tags by field variable
2559
     *
2560
     * @param string    field variable
2561
     * @return array    data
2562
     */
2563
    public static function get_extra_user_data_for_tags($field_variable)
2564
    {
2565
        $extra_information_by_variable = self::get_extra_field_tags_information_by_name($field_variable);
2566
2567
        return $extra_information_by_variable;
2568
    }
2569
2570
    /**
2571
     * Gives a list of [session_category][session_id] for the current user.
2572
     * @param integer $user_id
2573
     * @param boolean whether to fill the first element or not (to give space for courses out of categories)
2574
     * @param boolean  optional true if limit time from session is over, false otherwise
2575
     * @param boolean $ignoreTimeLimit ignore time start/end
2576
     * @return array  list of statuses [session_category][session_id]
2577
     *
2578
     * @todo ensure multiple access urls are managed correctly
2579
     */
2580
    public static function get_sessions_by_category(
2581
        $user_id,
2582
        $is_time_over = true,
2583
        $ignore_visibility_for_admins = false,
2584
        $ignoreTimeLimit = false
2585
    ) {
2586
        if ($user_id != strval(intval($user_id))) {
2587
            return array();
2588
        }
2589
2590
        // Get the list of sessions per user
2591
        $now = new DateTime('now', new DateTimeZone('UTC'));
2592
2593
        $dql = "SELECT DISTINCT
2594
                    s.id,
2595
                    s.name,
2596
                    s.accessStartDate AS access_start_date,
2597
                    s.accessEndDate AS access_end_date,
2598
                    sc.id AS session_category_id,
2599
                    sc.name AS session_category_name,
2600
                    sc.dateStart AS session_category_date_start,
2601
                    sc.dateEnd AS session_category_date_end,
2602
                    s.coachAccessStartDate AS coach_access_start_date,
2603
                    s.coachAccessEndDate AS coach_access_end_date
2604
                FROM ChamiloCoreBundle:Session AS s
2605
                LEFT JOIN ChamiloCoreBundle:SessionCategory AS sc WITH s.category = sc
2606
                LEFT JOIN ChamiloCoreBundle:SessionRelCourseRelUser AS scu WITH scu.session = s
2607
                WHERE scu.user = :user OR s.generalCoach = :user
2608
                ORDER BY sc.name, s.name";
2609
2610
        $dql = Database::getManager()
2611
            ->createQuery($dql)
2612
            ->setParameters(['user' => $user_id])
2613
        ;
2614
2615
        $sessionData = $dql->getResult();
2616
        $categories = [];
2617
2618
        foreach ($sessionData as $row) {
2619
            // User portal filters:
2620
            if ($ignoreTimeLimit === false) {
2621
                if ($is_time_over) {
2622
                    // History
2623
                    if (empty($row['access_end_date'])) {
2624
                        continue;
2625
                    }
2626
2627
                    if (!empty($row['access_end_date'])) {
2628
                        if ($row['access_end_date'] > $now) {
2629
                            continue;
2630
                        }
2631
2632
                    }
2633
                } else {
2634
                    // Current user portal
2635
                    if (api_is_allowed_to_create_course()) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
2636
                        // Teachers can access the session depending in the access_coach date
2637
                    } else {
2638
                        if (isset($row['access_end_date']) &&
2639
                            !empty($row['access_end_date'])
2640
                        ) {
2641
                            if ($row['access_end_date'] <= $now) {
2642
                                continue;
2643
                            }
2644
                        }
2645
                    }
2646
                }
2647
            }
2648
2649
            $categories[$row['session_category_id']]['session_category'] = array(
2650
                'id' => $row['session_category_id'],
2651
                'name' => $row['session_category_name'],
2652
                'date_start' => $row['session_category_date_start'] ? $row['session_category_date_start']->format('Y-m-d H:i:s') : null,
2653
                'date_end' => $row['session_category_date_end'] ? $row['session_category_date_end']->format('Y-m-d H:i:s') : null
2654
            );
2655
2656
            $session_id = $row['id'];
2657
            $courseList = UserManager::get_courses_list_by_session(
2658
                $user_id,
2659
                $session_id
2660
            );
2661
2662
            $visibility = api_get_session_visibility(
2663
                $session_id,
2664
                null,
2665
                $ignore_visibility_for_admins
2666
            );
2667
2668 View Code Duplication
            if ($visibility != SESSION_VISIBLE) {
2669
                // Course Coach session visibility.
2670
                $blockedCourseCount = 0;
2671
                $closedVisibilityList = array(
2672
                    COURSE_VISIBILITY_CLOSED,
2673
                    COURSE_VISIBILITY_HIDDEN
2674
                );
2675
2676
                foreach ($courseList as $course) {
2677
                    // Checking session visibility
2678
                    $sessionCourseVisibility = api_get_session_visibility(
2679
                        $session_id,
2680
                        $course['real_id'],
2681
                        $ignore_visibility_for_admins
2682
                    );
2683
2684
                    $courseIsVisible = !in_array(
2685
                        $course['visibility'],
2686
                        $closedVisibilityList
2687
                    );
2688
                    if ($courseIsVisible === false || $sessionCourseVisibility == SESSION_INVISIBLE) {
2689
                        $blockedCourseCount++;
2690
                    }
2691
                }
2692
2693
                // If all courses are blocked then no show in the list.
2694
                if ($blockedCourseCount === count($courseList)) {
2695
                    $visibility = SESSION_INVISIBLE;
2696
                } else {
2697
                    $visibility = SESSION_VISIBLE;
2698
                }
2699
            }
2700
2701
            switch ($visibility) {
2702
                case SESSION_VISIBLE_READ_ONLY:
2703
                case SESSION_VISIBLE:
2704
                case SESSION_AVAILABLE:
2705
                    break;
2706
                case SESSION_INVISIBLE:
2707
                    if ($ignore_visibility_for_admins === false) {
2708
                        continue 2;
2709
                    }
2710
            }
2711
2712
            $categories[$row['session_category_id']]['sessions'][$row['id']] = array(
2713
                'session_name' => $row['name'],
2714
                'session_id' => $row['id'],
2715
                'access_start_date' => $row['access_start_date'] ? $row['access_start_date']->format('Y-m-d H:i:s') : null,
2716
                'access_end_date' => $row['access_end_date'] ? $row['access_end_date']->format('Y-m-d H:i:s') : null,
2717
                'coach_access_start_date' => $row['coach_access_start_date'] ? $row['coach_access_start_date']->format('Y-m-d H:i:s') : null,
2718
                'coach_access_end_date' => $row['coach_access_end_date'] ? $row['coach_access_end_date']->format('Y-m-d H:i:s') : null,
2719
                'courses' => $courseList
2720
            );
2721
        }
2722
2723
        return $categories;
2724
    }
2725
2726
    /**
2727
     * Gives a list of [session_id-course_code] => [status] for the current user.
2728
     * @param integer $user_id
2729
     * @param int $sessionLimit
2730
     * @return array  list of statuses (session_id-course_code => status)
2731
     */
2732
    public static function get_personal_session_course_list($user_id, $sessionLimit = null)
2733
    {
2734
        // Database Table Definitions
2735
        $tbl_course = Database :: get_main_table(TABLE_MAIN_COURSE);
2736
        $tbl_user = Database :: get_main_table(TABLE_MAIN_USER);
2737
        $tbl_session = Database :: get_main_table(TABLE_MAIN_SESSION);
2738
        $tbl_session_user = Database :: get_main_table(TABLE_MAIN_SESSION_USER);
2739
        $tbl_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
2740
        $tbl_session_course_user = Database :: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2741
2742
        if ($user_id != strval(intval($user_id))) {
2743
            return array();
2744
        }
2745
2746
        // We filter the courses from the URL
2747
        $join_access_url = $where_access_url = '';
2748
2749 View Code Duplication
        if (api_get_multiple_access_url()) {
2750
            $access_url_id = api_get_current_access_url_id();
2751
            if ($access_url_id != -1) {
2752
                $tbl_url_course = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2753
                $join_access_url = "LEFT JOIN $tbl_url_course url_rel_course ON url_rel_course.c_id = course.id";
2754
                $where_access_url = " AND access_url_id = $access_url_id ";
2755
            }
2756
        }
2757
2758
        // Courses in which we subscribed out of any session
2759
        $tbl_user_course_category = Database :: get_main_table(TABLE_USER_COURSE_CATEGORY);
2760
2761
        $sql = "SELECT
2762
                    course.code,
2763
                    course_rel_user.status course_rel_status,
2764
                    course_rel_user.sort sort,
2765
                    course_rel_user.user_course_cat user_course_cat
2766
                 FROM $tbl_course_user course_rel_user
2767
                 LEFT JOIN $tbl_course course
2768
                 ON course.id = course_rel_user.c_id
2769
                 LEFT JOIN $tbl_user_course_category user_course_category
2770
                 ON course_rel_user.user_course_cat = user_course_category.id
2771
                 $join_access_url
2772
                 WHERE
2773
                    course_rel_user.user_id = '".$user_id."' AND
2774
                    course_rel_user.relation_type <> ".COURSE_RELATION_TYPE_RRHH."
2775
                    $where_access_url
2776
                 ORDER BY user_course_category.sort, course_rel_user.sort, course.title ASC";
2777
2778
        $course_list_sql_result = Database::query($sql);
2779
2780
        $personal_course_list = array();
2781
        if (Database::num_rows($course_list_sql_result) > 0) {
2782
            while ($result_row = Database::fetch_array($course_list_sql_result, 'ASSOC')) {
2783
                $course_info = api_get_course_info($result_row['code']);
2784
                $result_row['course_info'] = $course_info;
2785
                $personal_course_list[] = $result_row;
2786
            }
2787
        }
2788
2789
        $coachCourseConditions = null;
2790
2791
        // Getting sessions that are related to a coach in the session_rel_course_rel_user table
2792
2793
        if (api_is_allowed_to_create_course()) {
2794
            $sessionListFromCourseCoach = array();
2795
            $sql =" SELECT DISTINCT session_id
2796
                    FROM $tbl_session_course_user
2797
                    WHERE user_id = $user_id AND status = 2 ";
2798
2799
            $result = Database::query($sql);
2800
            if (Database::num_rows($result)) {
2801
                $result = Database::store_result($result);
0 ignored issues
show
Bug introduced by
It seems like $result can be null; however, store_result() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
2802
                foreach ($result as $session) {
2803
                    $sessionListFromCourseCoach[]= $session['session_id'];
2804
                }
2805
            }
2806
            if (!empty($sessionListFromCourseCoach)) {
2807
                $condition = implode("','", $sessionListFromCourseCoach);
2808
                $coachCourseConditions = " OR ( s.id IN ('$condition'))";
2809
            }
2810
        }
2811
2812
        // Get the list of sessions where the user is subscribed
2813
        // This is divided into two different queries
2814
        $sessions = array();
2815
2816
        $sessionLimitRestriction = '';
2817
        if (!empty($sessionLimit)) {
2818
            $sessionLimit = (int) $sessionLimit;
2819
            $sessionLimitRestriction = "LIMIT $sessionLimit";
2820
        }
2821
2822
        $sql = "SELECT DISTINCT s.id, name, access_start_date, access_end_date
2823
                FROM $tbl_session_user su INNER JOIN $tbl_session s
2824
                ON (s.id = su.session_id)
2825
                WHERE (
2826
                    su.user_id = $user_id AND
2827
                    su.relation_type <> ".SESSION_RELATION_TYPE_RRHH."
2828
                )
2829
                $coachCourseConditions
2830
                ORDER BY access_start_date, access_end_date, name
2831
                $sessionLimitRestriction
2832
        ";
2833
2834
        $result = Database::query($sql);
2835
        if (Database::num_rows($result)>0) {
2836
            while ($row = Database::fetch_assoc($result)) {
2837
                $sessions[$row['id']] = $row;
2838
            }
2839
        }
2840
2841
        $sql = "SELECT DISTINCT
2842
                id, name, access_start_date, access_end_date
2843
                FROM $tbl_session s
2844
                WHERE (
2845
                    id_coach = $user_id
2846
                )
2847
                $coachCourseConditions
2848
                ORDER BY access_start_date, access_end_date, name";
2849
2850
        $result = Database::query($sql);
2851
        if (Database::num_rows($result)>0) {
2852
            while ($row = Database::fetch_assoc($result)) {
2853
                if (empty($sessions[$row['id']])) {
2854
                    $sessions[$row['id']] = $row;
2855
                }
2856
            }
2857
        }
2858
2859
        if (api_is_allowed_to_create_course()) {
2860
            foreach ($sessions as $enreg) {
2861
                $session_id = $enreg['id'];
2862
                $session_visibility = api_get_session_visibility($session_id);
2863
2864
                if ($session_visibility == SESSION_INVISIBLE) {
2865
                    continue;
2866
                }
2867
2868
                // This query is horribly slow when more than a few thousand
2869
                // users and just a few sessions to which they are subscribed
2870
                $sql = "SELECT DISTINCT
2871
                        course.code code,
2872
                        course.title i,
2873
                        ".(api_is_western_name_order() ? "CONCAT(user.firstname,' ',user.lastname)" : "CONCAT(user.lastname,' ',user.firstname)")." t,
2874
                        email, course.course_language l,
2875
                        1 sort,
2876
                        category_code user_course_cat,
2877
                        access_start_date,
2878
                        access_end_date,
2879
                        session.id as session_id,
2880
                        session.name as session_name
2881
                    FROM $tbl_session_course_user as session_course_user
2882
                        INNER JOIN $tbl_course AS course
2883
                            ON course.id = session_course_user.c_id
2884
                        INNER JOIN $tbl_session as session
2885
                            ON session.id = session_course_user.session_id
2886
                        LEFT JOIN $tbl_user as user
2887
                            ON user.id = session_course_user.user_id OR session.id_coach = user.id
2888
                    WHERE
2889
                        session_course_user.session_id = $session_id AND (
2890
                            (session_course_user.user_id = $user_id AND session_course_user.status = 2)
2891
                            OR session.id_coach = $user_id
2892
                        )
2893
                    ORDER BY i";
2894
                $course_list_sql_result = Database::query($sql);
2895 View Code Duplication
                while ($result_row = Database::fetch_array($course_list_sql_result, 'ASSOC')) {
2896
                    $result_row['course_info'] = api_get_course_info($result_row['code']);
2897
                    $key = $result_row['session_id'].' - '.$result_row['code'];
2898
                    $personal_course_list[$key] = $result_row;
2899
                }
2900
            }
2901
        }
2902
2903
        foreach ($sessions as $enreg) {
2904
            $session_id = $enreg['id'];
2905
            $session_visibility = api_get_session_visibility($session_id);
2906
            if ($session_visibility == SESSION_INVISIBLE) {
2907
                continue;
2908
            }
2909
2910
            /* This query is very similar to the above query,
2911
               but it will check the session_rel_course_user table if there are courses registered to our user or not */
2912
            $sql = "SELECT DISTINCT
2913
                course.code code,
2914
                course.title i, CONCAT(user.lastname,' ',user.firstname) t,
2915
                email,
2916
                course.course_language l,
2917
                1 sort,
2918
                category_code user_course_cat,
2919
                access_start_date,
2920
                access_end_date,
2921
                session.id as session_id,
2922
                session.name as session_name,
2923
                IF((session_course_user.user_id = 3 AND session_course_user.status=2),'2', '5')
2924
            FROM $tbl_session_course_user as session_course_user
2925
            INNER JOIN $tbl_course AS course
2926
            ON course.id = session_course_user.c_id AND session_course_user.session_id = $session_id
2927
            INNER JOIN $tbl_session as session 
2928
            ON session_course_user.session_id = session.id
2929
            LEFT JOIN $tbl_user as user ON user.id = session_course_user.user_id
2930
            WHERE session_course_user.user_id = $user_id
2931
            ORDER BY i";
2932
2933
            $course_list_sql_result = Database::query($sql);
2934 View Code Duplication
            while ($result_row = Database::fetch_array($course_list_sql_result, 'ASSOC')) {
2935
                $result_row['course_info'] = api_get_course_info($result_row['code']);
2936
                $key = $result_row['session_id'].' - '.$result_row['code'];
2937
                if (!isset($personal_course_list[$key])) {
2938
                    $personal_course_list[$key] = $result_row;
2939
                }
2940
            }
2941
        }
2942
2943
        return $personal_course_list;
2944
    }
2945
2946
    /**
2947
     * Gives a list of courses for the given user in the given session
2948
     * @param integer $user_id
2949
     * @param integer $session_id
2950
     * @return array  list of statuses (session_id-course_code => status)
2951
     */
2952
    public static function get_courses_list_by_session($user_id, $session_id)
2953
    {
2954
        // Database Table Definitions
2955
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2956
        $tableCourse = Database::get_main_table(TABLE_MAIN_COURSE);
2957
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2958
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2959
2960
        $user_id = intval($user_id);
2961
        $session_id = intval($session_id);
2962
        //we filter the courses from the URL
2963
        $join_access_url = $where_access_url = '';
2964
2965
        if (api_get_multiple_access_url()) {
2966
            $urlId = api_get_current_access_url_id();
2967
            if ($urlId != -1) {
2968
                $tbl_url_session = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
2969
                $join_access_url = " ,  $tbl_url_session url_rel_session ";
2970
                $where_access_url = " AND access_url_id = $urlId AND url_rel_session.session_id = $session_id ";
2971
            }
2972
        }
2973
2974
        /* This query is very similar to the query below, but it will check the
2975
        session_rel_course_user table if there are courses registered
2976
        to our user or not */
2977
2978
        $sql = "SELECT DISTINCT
2979
                    c.visibility,
2980
                    c.id as real_id,                    
2981
                    sc.position
2982
                FROM $tbl_session_course_user as scu
2983
                INNER JOIN $tbl_session_course sc
2984
                ON (scu.session_id = sc.session_id AND scu.c_id = sc.c_id)
2985
                INNER JOIN $tableCourse as c
2986
                ON (scu.c_id = c.id)
2987
                $join_access_url
2988
                WHERE
2989
                    scu.user_id = $user_id AND
2990
                    scu.session_id = $session_id
2991
                    $where_access_url
2992
                ORDER BY sc.position ASC";
2993
2994
        $personal_course_list = array();
2995
        $courses = array();
2996
2997
        $result = Database::query($sql);
2998
        if (Database::num_rows($result) > 0) {
2999
            while ($result_row = Database::fetch_array($result, 'ASSOC')) {
3000
                $result_row['status'] = 5;
3001
                if (!in_array($result_row['real_id'], $courses)) {
3002
                    $personal_course_list[] = $result_row;
3003
                    $courses[] = $result_row['real_id'];
3004
                }
3005
            }
3006
        }
3007
3008
        if (api_is_allowed_to_create_course()) {
3009
            $sql = "SELECT DISTINCT
3010
                        c.visibility, 
3011
                        c.id as real_id,
3012
                        sc.position
3013
                    FROM $tbl_session_course_user as scu
3014
                    INNER JOIN $tbl_session as s
3015
                    ON (scu.session_id = s.id)
3016
                    INNER JOIN $tbl_session_course sc
3017
                    ON (scu.session_id = sc.session_id AND scu.c_id = sc.c_id)
3018
                    INNER JOIN $tableCourse as c
3019
                    ON (scu.c_id = c.id)
3020
                    $join_access_url
3021
                    WHERE
3022
                      s.id = $session_id AND
3023
                      (
3024
                        (scu.user_id = $user_id AND scu.status=2) OR
3025
                        s.id_coach = $user_id
3026
                      )
3027
                    $where_access_url
3028
                    ORDER BY sc.position ASC";
3029
            $result = Database::query($sql);
3030
3031
            if (Database::num_rows($result) > 0) {
3032
                while ($result_row = Database::fetch_array($result, 'ASSOC')) {
3033
                    $result_row['status'] = 2;
3034
                    if (!in_array($result_row['real_id'], $courses)) {
3035
                        $personal_course_list[] = $result_row;
3036
                        $courses[] = $result_row['real_id'];
3037
                    }
3038
                }
3039
            }
3040
        }
3041
3042
        if (api_is_drh()) {
3043
            $session_list = SessionManager::get_sessions_followed_by_drh($user_id);
3044
            $session_list = array_keys($session_list);
3045
            if (in_array($session_id, $session_list)) {
3046
                $course_list = SessionManager::get_course_list_by_session_id($session_id);
3047
                if (!empty($course_list)) {
3048
                    foreach ($course_list as $course) {
0 ignored issues
show
Bug introduced by
The expression $course_list of type integer|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
3049
                        $personal_course_list[] = $course;
3050
                    }
3051
                }
3052
            }
3053
        } else {
3054
            //check if user is general coach for this session
3055
            $sessionInfo = api_get_session_info($session_id);
3056
            if ($sessionInfo['id_coach'] == $user_id) {
3057
                $course_list = SessionManager::get_course_list_by_session_id($session_id);
3058
3059
                if (!empty($course_list)) {
3060
                    foreach ($course_list as $course) {
0 ignored issues
show
Bug introduced by
The expression $course_list of type integer|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
3061
                        if (!in_array($course['id'], $courses)) {
3062
                            $personal_course_list[] = $course;
3063
                        }
3064
                    }
3065
                }
3066
            }
3067
        }
3068
3069
        return $personal_course_list;
3070
    }
3071
3072
    /**
3073
     * Get user id from a username
3074
     * @param    string    $username
3075
     * @return    int        User ID (or false if not found)
3076
     */
3077
    public static function get_user_id_from_username($username)
3078
    {
3079
        if (empty($username)) {
3080
3081
            return false;
3082
        }
3083
        $username = trim($username);
3084
        $username = Database::escape_string($username);
3085
        $t_user = Database::get_main_table(TABLE_MAIN_USER);
3086
        $sql = "SELECT id FROM $t_user WHERE username = '$username'";
3087
        $res = Database::query($sql);
3088
3089
        if ($res === false) {
3090
            return false;
3091
        }
3092
        if (Database::num_rows($res) !== 1) {
3093
            return false;
3094
        }
3095
        $row = Database::fetch_array($res);
3096
3097
        return $row['id'];
3098
    }
3099
3100
    /**
3101
     * Get the users files upload from his share_folder
3102
     * @param    string  $user_id   User ID
3103
     * @param   string  $course course directory
3104
     * @param   string  $resourcetype resourcetype: images, all
3105
     * @return    int        User ID (or false if not found)
3106
     */
3107
    public static function get_user_upload_files_by_course($user_id, $course, $resourcetype = 'all')
3108
    {
3109
        $return = '';
3110
        if (!empty($user_id) && !empty($course)) {
3111
            $user_id = intval($user_id);
3112
            $path = api_get_path(SYS_COURSE_PATH).$course.'/document/shared_folder/sf_user_'.$user_id.'/';
3113
            $web_path = api_get_path(WEB_COURSE_PATH).$course.'/document/shared_folder/sf_user_'.$user_id.'/';
3114
            $file_list = array();
3115
3116
            if (is_dir($path)) {
3117
                $handle = opendir($path);
3118
                while ($file = readdir($handle)) {
3119
                    if ($file == '.' || $file == '..' || $file == '.htaccess' || is_dir($path.$file)) {
3120
                        continue; // skip current/parent directory and .htaccess
3121
                    }
3122
                    $file_list[] = $file;
3123
                }
3124
                if (count($file_list) > 0) {
3125
                    $return = "<h4>$course</h4>";
3126
                    $return .= '<ul class="thumbnails">';
3127
                }
3128
                $extensionList = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'tif'];
3129
                foreach ($file_list as $file) {
3130
                    if ($resourcetype == "all") {
3131
                        $return .= '<li><a href="'.$web_path.urlencode($file).'" target="_blank">'.htmlentities($file).'</a></li>';
3132
                    } elseif ($resourcetype == "images") {
3133
                        //get extension
3134
                        $ext = explode('.', $file);
3135
                        if (isset($ext[1]) && in_array($ext[1], $extensionList)) {
3136
                            $return .= '<li class="span2">
3137
                                            <a class="thumbnail" href="'.$web_path.urlencode($file).'" target="_blank">
3138
                                                <img src="'.$web_path.urlencode($file).'" >
3139
                                            </a>
3140
                                        </li>';
3141
                        }
3142
                    }
3143
                }
3144
                if (count($file_list) > 0) {
3145
                    $return .= '</ul>';
3146
                }
3147
            }
3148
        }
3149
3150
        return $return;
3151
    }
3152
3153
    /**
3154
     * Gets the API key (or keys) and return them into an array
3155
     * @param   int     Optional user id (defaults to the result of api_get_user_id())
3156
     * @return  array   Non-indexed array containing the list of API keys for this user, or FALSE on error
3157
     */
3158
    public static function get_api_keys($user_id = null, $api_service = 'dokeos')
3159
    {
3160
        if ($user_id != strval(intval($user_id)))
3161
            return false;
3162
        if (empty($user_id)) {
3163
            $user_id = api_get_user_id();
3164
        }
3165
        if ($user_id === false)
3166
            return false;
3167
        $service_name = Database::escape_string($api_service);
3168
        if (is_string($service_name) === false) {
3169
            return false;
3170
        }
3171
        $t_api = Database::get_main_table(TABLE_MAIN_USER_API_KEY);
3172
        $sql = "SELECT * FROM $t_api WHERE user_id = $user_id AND api_service='$api_service';";
3173
        $res = Database::query($sql);
3174
        if ($res === false)
3175
            return false; //error during query
3176
        $num = Database::num_rows($res);
3177
        if ($num == 0)
3178
            return false;
3179
        $list = array();
3180
        while ($row = Database::fetch_array($res)) {
3181
            $list[$row['id']] = $row['api_key'];
3182
        }
3183
        return $list;
3184
    }
3185
3186
    /**
3187
     * Adds a new API key to the users' account
3188
     * @param   int     Optional user ID (defaults to the results of api_get_user_id())
3189
     * @return  boolean True on success, false on failure
3190
     */
3191
    public static function add_api_key($user_id = null, $api_service = 'dokeos')
3192
    {
3193
        if ($user_id != strval(intval($user_id)))
3194
            return false;
3195
        if (empty($user_id)) {
3196
            $user_id = api_get_user_id();
3197
        }
3198
        if ($user_id === false)
3199
            return false;
3200
        $service_name = Database::escape_string($api_service);
3201
        if (is_string($service_name) === false) {
3202
            return false;
3203
        }
3204
        $t_api = Database::get_main_table(TABLE_MAIN_USER_API_KEY);
3205
        $md5 = md5((time() + ($user_id * 5)) - rand(10000, 10000)); //generate some kind of random key
3206
        $sql = "INSERT INTO $t_api (user_id, api_key,api_service) VALUES ($user_id,'$md5','$service_name')";
3207
        $res = Database::query($sql);
3208
        if ($res === false)
3209
            return false; //error during query
3210
        $num = Database::insert_id();
3211
        return ($num == 0) ? false : $num;
3212
    }
3213
3214
    /**
3215
     * Deletes an API key from the user's account
3216
     * @param   int     API key's internal ID
3217
     * @return  boolean True on success, false on failure
3218
     */
3219
    public static function delete_api_key($key_id)
3220
    {
3221
        if ($key_id != strval(intval($key_id)))
3222
            return false;
3223
        if ($key_id === false)
3224
            return false;
3225
        $t_api = Database::get_main_table(TABLE_MAIN_USER_API_KEY);
3226
        $sql = "SELECT * FROM $t_api WHERE id = ".$key_id;
3227
        $res = Database::query($sql);
3228
        if ($res === false)
3229
            return false; //error during query
3230
        $num = Database::num_rows($res);
3231
        if ($num !== 1)
3232
            return false;
3233
        $sql = "DELETE FROM $t_api WHERE id = ".$key_id;
3234
        $res = Database::query($sql);
3235
        if ($res === false)
3236
            return false; //error during query
3237
        return true;
3238
    }
3239
3240
    /**
3241
     * Regenerate an API key from the user's account
3242
     * @param   int     user ID (defaults to the results of api_get_user_id())
3243
     * @param   string  API key's internal ID
3244
     * @return  int        num
3245
     */
3246
    public static function update_api_key($user_id, $api_service)
3247
    {
3248
        if ($user_id != strval(intval($user_id)))
3249
            return false;
3250
        if ($user_id === false)
3251
            return false;
3252
        $service_name = Database::escape_string($api_service);
3253
        if (is_string($service_name) === false) {
3254
            return false;
3255
        }
3256
        $t_api = Database::get_main_table(TABLE_MAIN_USER_API_KEY);
3257
        $sql = "SELECT id FROM $t_api WHERE user_id=".$user_id." AND api_service='".$api_service."'";
3258
        $res = Database::query($sql);
3259
        $num = Database::num_rows($res);
3260
        if ($num == 1) {
3261
            $id_key = Database::fetch_array($res, 'ASSOC');
3262
            self::delete_api_key($id_key['id']);
3263
            $num = self::add_api_key($user_id, $api_service);
3264
        } elseif ($num == 0) {
3265
            $num = self::add_api_key($user_id, $api_service);
3266
        }
3267
        return $num;
3268
    }
3269
3270
    /**
3271
     * @param   int     user ID (defaults to the results of api_get_user_id())
3272
     * @param   string    API key's internal ID
3273
     * @return  int    row ID, or return false if not found
3274
     */
3275
    public static function get_api_key_id($user_id, $api_service)
3276
    {
3277
        if ($user_id != strval(intval($user_id)))
3278
            return false;
3279
        if ($user_id === false)
3280
            return false;
3281
        if (empty($api_service))
3282
            return false;
3283
        $t_api = Database::get_main_table(TABLE_MAIN_USER_API_KEY);
3284
        $api_service = Database::escape_string($api_service);
3285
        $sql = "SELECT id FROM $t_api WHERE user_id=".$user_id." AND api_service='".$api_service."'";
3286
        $res = Database::query($sql);
3287
        if (Database::num_rows($res) < 1) {
3288
            return false;
3289
        }
3290
        $row = Database::fetch_array($res, 'ASSOC');
3291
        return $row['id'];
3292
    }
3293
3294
    /**
3295
     * Checks if a user_id is platform admin
3296
     * @param   int user ID
3297
     * @return  boolean True if is admin, false otherwise
3298
     * @see main_api.lib.php::api_is_platform_admin() for a context-based check
3299
     */
3300
    public static function is_admin($user_id)
3301
    {
3302
        if (empty($user_id) or $user_id != strval(intval($user_id))) {
3303
            return false;
3304
        }
3305
        $admin_table = Database::get_main_table(TABLE_MAIN_ADMIN);
3306
        $sql = "SELECT * FROM $admin_table WHERE user_id = $user_id";
3307
        $res = Database::query($sql);
3308
3309
        return Database::num_rows($res) === 1;
3310
    }
3311
3312
    /**
3313
     * Get the total count of users
3314
     * @param   int     Status of users to be counted
3315
     * @param   int     Access URL ID (optional)
3316
     * @return    mixed    Number of users or false on error
3317
     */
3318
    public static function get_number_of_users($status = 0, $access_url_id = null)
3319
    {
3320
        $t_u = Database::get_main_table(TABLE_MAIN_USER);
3321
        $t_a = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
3322
        $sql = "SELECT count(*) FROM $t_u u";
3323
        $sql2 = '';
3324
        if (is_int($status) && $status > 0) {
3325
            $sql2 .= " WHERE u.status = $status ";
3326
        }
3327
        if (!empty($access_url_id) && $access_url_id == intval($access_url_id)) {
3328
            $sql .= ", $t_a a ";
3329
            $sql2 .= " AND a.access_url_id = $access_url_id AND u.id = a.user_id ";
3330
        }
3331
        $sql = $sql.$sql2;
3332
        $res = Database::query($sql);
3333
        if (Database::num_rows($res) === 1) {
3334
            return (int) Database::result($res, 0, 0);
3335
        }
3336
        return false;
3337
    }
3338
3339
    /**
3340
     * @author Isaac flores <[email protected]>
3341
     * @param string The email administrator
3342
     * @param integer The user id
3343
     * @param string The message title
3344
     * @param string The content message
3345
     */
3346
    public static function send_message_in_outbox($email_administrator, $user_id, $title, $content)
3347
    {
3348
        $table_message = Database::get_main_table(TABLE_MESSAGE);
3349
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
3350
        $title = api_utf8_decode($title);
3351
        $content = api_utf8_decode($content);
3352
        $email_administrator = Database::escape_string($email_administrator);
3353
        //message in inbox
3354
        $sql_message_outbox = 'SELECT id from '.$table_user.' WHERE email="'.$email_administrator.'" ';
3355
        //$num_row_query = Database::num_rows($sql_message_outbox);
3356
        $res_message_outbox = Database::query($sql_message_outbox);
3357
        $array_users_administrator = array();
3358
        while ($row_message_outbox = Database::fetch_array($res_message_outbox, 'ASSOC')) {
3359
            $array_users_administrator[] = $row_message_outbox['id'];
3360
        }
3361
        //allow to insert messages in outbox
3362
        for ($i = 0; $i < count($array_users_administrator); $i++) {
3363
            $sql_insert_outbox = "INSERT INTO $table_message(user_sender_id, user_receiver_id, msg_status, send_date, title, content ) ".
3364
                " VALUES (".
3365
                "'".(int) $user_id."', '".(int) ($array_users_administrator[$i])."', '4', '".api_get_utc_datetime()."','".Database::escape_string($title)."','".Database::escape_string($content)."'".
3366
                ")";
3367
            Database::query($sql_insert_outbox);
3368
        }
3369
    }
3370
3371
    /**
3372
     *
3373
     * Gets the tags of a specific field_id
3374
     * USER TAGS
3375
     *
3376
     * Instructions to create a new user tag by Julio Montoya <[email protected]>
3377
     *
3378
     * 1. Create a new extra field in main/admin/user_fields.php with the "TAG" field type make it available and visible.
3379
     *    Called it "books" for example.
3380
     * 2. Go to profile main/auth/profile.php There you will see a special input (facebook style) that will show suggestions of tags.
3381
     * 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
3382
     * 4. Tags are independent this means that tags can't be shared between tags + book + hobbies.
3383
     * 5. Test and enjoy.
3384
     *
3385
     * @param string $tag
3386
     * @param int $field_id field_id
3387
     * @param string $return_format how we are going to result value in array or in a string (json)
3388
     * @param $limit
3389
     *
3390
     * @return mixed
3391
     *
3392
     */
3393
    public static function get_tags($tag, $field_id, $return_format = 'json', $limit = 10)
3394
    {
3395
        // database table definition
3396
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3397
        $field_id = intval($field_id);
3398
        $limit = intval($limit);
3399
        $tag = trim(Database::escape_string($tag));
3400
3401
        // all the information of the field
3402
        $sql = "SELECT DISTINCT id, tag from $table_user_tag
3403
                WHERE field_id = $field_id AND tag LIKE '$tag%' ORDER BY tag LIMIT $limit";
3404
        $result = Database::query($sql);
3405
        $return = array();
3406 View Code Duplication
        if (Database::num_rows($result) > 0) {
3407
            while ($row = Database::fetch_array($result, 'ASSOC')) {
3408
                $return[] = array('key' => $row['tag'], 'value' => $row['tag']);
3409
            }
3410
        }
3411
        if ($return_format === 'json') {
3412
            $return = json_encode($return);
3413
        }
3414
3415
        return $return;
3416
    }
3417
3418
    /**
3419
     * @param int $field_id
3420
     * @param int $limit
3421
     *
3422
     * @return array
3423
     */
3424
    public static function get_top_tags($field_id, $limit = 100)
3425
    {
3426
        // database table definition
3427
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3428
        $table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
3429
        $field_id = intval($field_id);
3430
        $limit = intval($limit);
3431
        // all the information of the field
3432
        $sql = "SELECT count(*) count, tag FROM $table_user_tag_values  uv
3433
                INNER JOIN $table_user_tag ut
3434
                ON(ut.id = uv.tag_id)
3435
                WHERE field_id = $field_id
3436
                GROUP BY tag_id
3437
                ORDER BY count DESC
3438
                LIMIT $limit";
3439
        $result = Database::query($sql);
3440
        $return = array();
3441
        if (Database::num_rows($result) > 0) {
3442
            while ($row = Database::fetch_array($result, 'ASSOC')) {
3443
                $return[] = $row;
3444
            }
3445
        }
3446
        return $return;
3447
    }
3448
3449
    /**
3450
     * Get user's tags
3451
     * @param int $user_id
3452
     * @param int $field_id
3453
     *
3454
     * @return array
3455
     */
3456
    public static function get_user_tags($user_id, $field_id)
3457
    {
3458
        // database table definition
3459
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3460
        $table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
3461
        $field_id = intval($field_id);
3462
        $user_id = intval($user_id);
3463
3464
        // all the information of the field
3465
        $sql = "SELECT ut.id, tag, count
3466
                FROM $table_user_tag ut
3467
                INNER JOIN $table_user_tag_values uv
3468
                ON (uv.tag_id=ut.ID)
3469
                WHERE field_id = $field_id AND user_id = $user_id
3470
                ORDER BY tag";
3471
        $result = Database::query($sql);
3472
        $return = array();
3473 View Code Duplication
        if (Database::num_rows($result) > 0) {
3474
            while ($row = Database::fetch_array($result, 'ASSOC')) {
3475
                $return[$row['id']] = array('tag' => $row['tag'], 'count' => $row['count']);
3476
            }
3477
        }
3478
3479
        return $return;
3480
    }
3481
3482
    /**
3483
     * Get user's tags
3484
     * @param int $user_id
3485
     * @param int $field_id
3486
     * @param bool $show_links show links or not
3487
     *
3488
     * @return array
3489
     */
3490
    public static function get_user_tags_to_string($user_id, $field_id, $show_links = true)
3491
    {
3492
        // database table definition
3493
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3494
        $table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
3495
        $field_id = intval($field_id);
3496
        $user_id = intval($user_id);
3497
3498
        // all the information of the field
3499
        $sql = "SELECT ut.id, tag,count FROM $table_user_tag ut
3500
                INNER JOIN $table_user_tag_values uv
3501
                ON (uv.tag_id = ut.id)
3502
                WHERE field_id = $field_id AND user_id = $user_id
3503
                ORDER BY tag";
3504
3505
        $result = Database::query($sql);
3506
        $return = array();
3507 View Code Duplication
        if (Database::num_rows($result) > 0) {
3508
            while ($row = Database::fetch_array($result, 'ASSOC')) {
3509
                $return[$row['id']] = array('tag' => $row['tag'], 'count' => $row['count']);
3510
            }
3511
        }
3512
        $user_tags = $return;
3513
        $tag_tmp = array();
3514
        foreach ($user_tags as $tag) {
3515
            if ($show_links) {
3516
                $tag_tmp[] = '<a href="'.api_get_path(WEB_PATH).'main/search/index.php?q='.$tag['tag'].'">'.$tag['tag'].'</a>';
3517
            } else {
3518
                $tag_tmp[] = $tag['tag'];
3519
            }
3520
        }
3521
3522
        if (is_array($user_tags) && count($user_tags) > 0) {
3523
            $return = implode(', ', $tag_tmp);
3524
        } else {
3525
3526
            return '';
3527
        }
3528
3529
        return $return;
3530
    }
3531
3532
    /**
3533
     * Get the tag id
3534
     * @param int $tag
3535
     * @param int $field_id
3536
     * @return int returns 0 if fails otherwise the tag id
3537
     */
3538
    public static function get_tag_id($tag, $field_id)
3539
    {
3540
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3541
        $tag = Database::escape_string($tag);
3542
        $field_id = intval($field_id);
3543
        //with COLLATE latin1_bin to select query in a case sensitive mode
3544
        $sql = "SELECT id FROM $table_user_tag
3545
                WHERE tag LIKE '$tag' AND field_id = $field_id";
3546
        $result = Database::query($sql);
3547
        if (Database::num_rows($result) > 0) {
3548
            $row = Database::fetch_array($result, 'ASSOC');
3549
3550
            return $row['id'];
3551
        } else {
3552
3553
            return 0;
3554
        }
3555
    }
3556
3557
    /**
3558
     * Get the tag id
3559
     * @param int $tag_id
3560
     * @param int $field_id
3561
     *
3562
     * @return int 0 if fails otherwise the tag id
3563
     */
3564
    public static function get_tag_id_from_id($tag_id, $field_id)
3565
    {
3566
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3567
        $tag_id = intval($tag_id);
3568
        $field_id = intval($field_id);
3569
        $sql = "SELECT id FROM $table_user_tag
3570
                WHERE id = '$tag_id' AND field_id = $field_id";
3571
        $result = Database::query($sql);
3572
        if (Database::num_rows($result) > 0) {
3573
            $row = Database::fetch_array($result, 'ASSOC');
3574
            return $row['id'];
3575
        } else {
3576
            return false;
3577
        }
3578
    }
3579
3580
    /**
3581
     * Adds a user-tag value
3582
     * @param mixed $tag
3583
     * @param int $user_id
3584
     * @param int $field_id field id of the tag
3585
     * @return bool
3586
     */
3587
    public static function add_tag($tag, $user_id, $field_id)
3588
    {
3589
        // database table definition
3590
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3591
        $table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
3592
        $tag = trim(Database::escape_string($tag));
3593
        $user_id = intval($user_id);
3594
        $field_id = intval($field_id);
3595
3596
        $tag_id = UserManager::get_tag_id($tag, $field_id);
3597
3598
        /* IMPORTANT
3599
         *  @todo we don't create tags with numbers
3600
         *
3601
         */
3602
        if (is_numeric($tag)) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
3603
            //the form is sending an id this means that the user select it from the list so it MUST exists
3604
            /* $new_tag_id = UserManager::get_tag_id_from_id($tag,$field_id);
3605
              if ($new_tag_id !== false) {
3606
              $sql = "UPDATE $table_user_tag SET count = count + 1 WHERE id  = $new_tag_id";
3607
              $result = Database::query($sql);
3608
              $last_insert_id = $new_tag_id;
3609
              } else {
3610
              $sql = "INSERT INTO $table_user_tag (tag, field_id,count) VALUES ('$tag','$field_id', count + 1)";
3611
              $result = Database::query($sql);
3612
              $last_insert_id = Database::insert_id();
3613
              } */
3614
        }
3615
3616
        //this is a new tag
3617
        if ($tag_id == 0) {
3618
            //the tag doesn't exist
3619
            $sql = "INSERT INTO $table_user_tag (tag, field_id,count) VALUES ('$tag','$field_id', count + 1)";
3620
             Database::query($sql);
3621
            $last_insert_id = Database::insert_id();
3622
        } else {
3623
            //the tag exists we update it
3624
            $sql = "UPDATE $table_user_tag SET count = count + 1 WHERE id  = $tag_id";
3625
             Database::query($sql);
3626
            $last_insert_id = $tag_id;
3627
        }
3628
3629
        if (!empty($last_insert_id) && ($last_insert_id != 0)) {
3630
            //we insert the relationship user-tag
3631
            $sql = "SELECT tag_id FROM $table_user_tag_values
3632
                    WHERE user_id = $user_id AND tag_id = $last_insert_id ";
3633
            $result = Database::query($sql);
3634
            //if the relationship does not exist we create it
3635
            if (Database::num_rows($result) == 0) {
3636
                $sql = "INSERT INTO $table_user_tag_values SET user_id = $user_id, tag_id = $last_insert_id";
3637
                Database::query($sql);
3638
            }
3639
        }
3640
    }
3641
3642
    /**
3643
     * Deletes an user tag
3644
     * @param int $user_id
3645
     * @param int $field_id
3646
     *
3647
     */
3648
    public static function delete_user_tags($user_id, $field_id)
3649
    {
3650
        // database table definition
3651
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3652
        $table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
3653
        $tags = UserManager::get_user_tags($user_id, $field_id);
3654
        if (is_array($tags) && count($tags) > 0) {
3655
            foreach ($tags as $key => $tag) {
3656
                if ($tag['count'] > '0') {
3657
                    $sql = "UPDATE $table_user_tag SET count = count - 1  WHERE id = $key ";
3658
                    Database::query($sql);
3659
                }
3660
                $sql = "DELETE FROM $table_user_tag_values
3661
                        WHERE user_id = $user_id AND tag_id = $key";
3662
                Database::query($sql);
3663
            }
3664
        }
3665
    }
3666
3667
    /**
3668
     * Process the tag list comes from the UserManager::update_extra_field_value() function
3669
     * @param array $tags the tag list that will be added
3670
     * @param int $user_id
3671
     * @param int $field_id
3672
     *
3673
     * @return bool
3674
     */
3675
    public static function process_tags($tags, $user_id, $field_id)
3676
    {
3677
        // We loop the tags and add it to the DB
3678
        if (is_array($tags)) {
3679
            foreach ($tags as $tag) {
3680
                UserManager::add_tag($tag, $user_id, $field_id);
3681
            }
3682
        } else {
3683
            UserManager::add_tag($tags, $user_id, $field_id);
3684
        }
3685
3686
        return true;
3687
    }
3688
3689
    /**
3690
     * Returns a list of all administrators
3691
     *
3692
     * @return array
3693
     */
3694
    public static function get_all_administrators()
3695
    {
3696
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
3697
        $table_admin = Database::get_main_table(TABLE_MAIN_ADMIN);
3698
        $tbl_url_rel_user = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
3699
        $access_url_id = api_get_current_access_url_id();
3700
        if (api_get_multiple_access_url()) {
3701
            $sql = "SELECT admin.user_id, username, firstname, lastname, email, active
3702
                    FROM $tbl_url_rel_user as url
3703
                    INNER JOIN $table_admin as admin
3704
                    ON (admin.user_id=url.user_id)
3705
                    INNER JOIN $table_user u
3706
                    ON (u.id=admin.user_id)
3707
                    WHERE access_url_id ='".$access_url_id."'";
3708
        } else {
3709
            $sql = "SELECT admin.user_id, username, firstname, lastname, email, active
3710
                    FROM $table_admin as admin
3711
                    INNER JOIN $table_user u
3712
                    ON (u.id=admin.user_id)";
3713
        }
3714
        $result = Database::query($sql);
3715
        $return = array();
3716
        if (Database::num_rows($result) > 0) {
3717
            while ($row = Database::fetch_array($result, 'ASSOC')) {
3718
                $return[$row['user_id']] = $row;
3719
            }
3720
        }
3721
3722
        return $return;
3723
    }
3724
3725
    /**
3726
     * Search an user (tags, first name, last name and email )
3727
     * @param string $tag
3728
     * @param int $field_id field id of the tag
3729
     * @param int $from where to start in the query
3730
     * @param int $number_of_items
3731
     * @param bool $getCount get count or not
3732
     * @return array
3733
     */
3734
    public static function get_all_user_tags(
3735
        $tag,
3736
        $field_id = 0,
3737
        $from = 0,
3738
        $number_of_items = 10,
3739
        $getCount = false
3740
    ) {
3741
        $user_table = Database::get_main_table(TABLE_MAIN_USER);
3742
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3743
        $table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
3744
        $access_url_rel_user_table = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
3745
3746
        $field_id = intval($field_id);
3747
        $from = intval($from);
3748
        $number_of_items = intval($number_of_items);
3749
3750
        $where_field = "";
3751
        $where_extra_fields = UserManager::get_search_form_where_extra_fields();
3752
        if ($field_id != 0) {
3753
            $where_field = " field_id = $field_id AND ";
3754
        }
3755
3756
        // all the information of the field
3757
3758
        if ($getCount) {
3759
            $select = "SELECT count(DISTINCT u.id) count";
3760
        } else {
3761
            $select = "SELECT DISTINCT u.id, u.username, firstname, lastname, email, tag, picture_uri";
3762
        }
3763
3764
        $sql = " $select
3765
                FROM $user_table u
3766
                INNER JOIN $access_url_rel_user_table url_rel_user
3767
                ON (u.id = url_rel_user.user_id)
3768
                LEFT JOIN $table_user_tag_values uv
3769
                ON (u.id AND uv.user_id AND uv.user_id = url_rel_user.user_id)
3770
                LEFT JOIN $table_user_tag ut ON (uv.tag_id = ut.id)
3771
                WHERE
3772
                    ($where_field tag LIKE '".Database::escape_string($tag."%")."') OR
3773
                    (
3774
                        u.firstname LIKE '".Database::escape_string("%".$tag."%")."' OR
3775
                        u.lastname LIKE '".Database::escape_string("%".$tag."%")."' OR
3776
                        u.username LIKE '".Database::escape_string("%".$tag."%")."' OR
3777
                        concat(u.firstname, ' ', u.lastname) LIKE '".Database::escape_string("%".$tag."%")."' OR
3778
                        concat(u.lastname, ' ', u.firstname) LIKE '".Database::escape_string("%".$tag."%")."'
3779
                     )
3780
                     ".(!empty($where_extra_fields) ? $where_extra_fields : '')."
3781
                     AND url_rel_user.access_url_id=".api_get_current_access_url_id();
3782
3783
        $keyword_active = true;
3784
        // only active users
3785
        if ($keyword_active) {
3786
            $sql .= " AND u.active='1'";
3787
        }
3788
        // avoid anonymous
3789
        $sql .= " AND u.status <> 6 ";
3790
        $sql .= " ORDER BY username";
3791
        $sql .= " LIMIT $from , $number_of_items";
3792
3793
        $result = Database::query($sql);
3794
        $return = array();
3795
3796
        if (Database::num_rows($result) > 0) {
3797
            if ($getCount) {
3798
                $row = Database::fetch_array($result, 'ASSOC');
3799
                return $row['count'];
3800
            }
3801
            while ($row = Database::fetch_array($result, 'ASSOC')) {
3802
                if (isset($return[$row['id']]) &&
3803
                    !empty($return[$row['id']]['tag'])
3804
                ) {
3805
                    $url = Display::url(
3806
                        $row['tag'],
3807
                        api_get_path(WEB_PATH).'main/social/search.php?q='.$row['tag'],
3808
                        array('class' => 'tag')
3809
                    );
3810
                    $row['tag'] = $url;
3811
                }
3812
                $return[$row['id']] = $row;
3813
            }
3814
        }
3815
3816
        return $return;
3817
    }
3818
3819
    /**
3820
      * Get extra filtrable user fields (only type select)
3821
      * @return array
3822
      */
3823
    public static function get_extra_filtrable_fields()
3824
    {
3825
        $extraFieldList = UserManager::get_extra_fields();
3826
3827
        $extraFiltrableFields = array();
3828 View Code Duplication
        if (is_array($extraFieldList)) {
3829
            foreach ($extraFieldList as $extraField) {
3830
                // If is enabled to filter and is a "<select>" field type
3831
                if ($extraField[8] == 1 && $extraField[2] == 4) {
3832
                    $extraFiltrableFields[] = array(
3833
                        'name' => $extraField[3],
3834
                        'variable' => $extraField[1],
3835
                        'data' => $extraField[9]
3836
                    );
3837
                }
3838
            }
3839
        }
3840
3841
        if (is_array($extraFiltrableFields) && count($extraFiltrableFields) > 0) {
3842
            return $extraFiltrableFields;
3843
        }
3844
    }
3845
3846
    /**
3847
      * Get extra where clauses for finding users based on extra filtrable user fields (type select)
3848
      * @return string With AND clauses based on user's ID which have the values to search in extra user fields
3849
      */
3850
    public static function get_search_form_where_extra_fields()
3851
    {
3852
        $useExtraFields = false;
3853
        $extraFields = UserManager::get_extra_filtrable_fields();
3854
        $extraFieldResult = array();
3855 View Code Duplication
        if (is_array($extraFields) && count($extraFields)>0 ) {
3856
            foreach ($extraFields as $extraField) {
3857
                $varName = 'field_'.$extraField['variable'];
3858
                if (UserManager::is_extra_field_available($extraField['variable'])) {
3859
                    if (isset($_GET[$varName]) && $_GET[$varName]!='0') {
3860
                        $useExtraFields = true;
3861
                        $extraFieldResult[]= UserManager::get_extra_user_data_by_value(
3862
                            $extraField['variable'],
3863
                            $_GET[$varName]
3864
                        );
3865
                    }
3866
                }
3867
            }
3868
        }
3869
3870
        if ($useExtraFields) {
3871
            $finalResult = array();
3872
            if (count($extraFieldResult)>1) {
3873
                for ($i=0; $i < count($extraFieldResult) -1; $i++) {
3874
                if (is_array($extraFieldResult[$i]) && is_array($extraFieldResult[$i+1])) {
3875
                        $finalResult  = array_intersect($extraFieldResult[$i], $extraFieldResult[$i+1]);
3876
                    }
3877
                }
3878
            } else {
3879
                $finalResult = $extraFieldResult[0];
3880
            }
3881
3882
            if (is_array($finalResult) && count($finalResult)>0) {
3883
                $whereFilter = " AND u.id IN  ('".implode("','", $finalResult)."') ";
3884
            } else {
3885
                //no results
3886
                $whereFilter = " AND u.id  = -1 ";
3887
            }
3888
3889
            return $whereFilter;
3890
        }
3891
    }
3892
3893
    /**
3894
     * Show the search form
3895
     * @param string $query the value of the search box
3896
     * @return string HTML form
3897
     */
3898
    public static function get_search_form($query, $defaultParams = [])
3899
    {
3900
        $searchType = isset($_GET['search_type']) ? $_GET['search_type'] : null;
3901
        $form = new FormValidator(
3902
            'search_user',
3903
            'get',
3904
            api_get_path(WEB_PATH).'main/social/search.php',
3905
            '',
3906
            array(),
3907
            FormValidator::LAYOUT_HORIZONTAL
3908
        );
3909
3910
        $form->addText('q', get_lang('UsersGroups'), false);
3911
        $options = array(
3912
            0 => get_lang('Select'),
3913
            1 => get_lang('User'),
3914
            2 => get_lang('Group'),
3915
        );
3916
        $form->addSelect(
3917
            'search_type',
3918
            get_lang('Type'),
3919
            $options,
3920
            array('onchange' => 'javascript: extra_field_toogle();')
3921
        );
3922
3923
        // Extra fields
3924
3925
        $extraFields = UserManager::get_extra_filtrable_fields();
3926
        $defaults = [];
3927
        if (is_array($extraFields) && count($extraFields) > 0) {
3928
            foreach ($extraFields as $extraField) {
3929
                $varName = 'field_'.$extraField['variable'];
3930
3931
                $options = [
3932
                    0 => get_lang('Select')
3933
                ];
3934
                foreach ($extraField['data'] as $option) {
3935
                    $checked = '';
3936
                    if (isset($_GET[$varName])) {
3937
                        if ($_GET[$varName] == $option[1]) {
3938
                            $defaults[$option[1]] = true;
3939
                        }
3940
                    }
3941
3942
                    $options[$option[1]] = $option[1];
3943
                }
3944
                $form->addSelect($varName, $extraField['name'], $options);
3945
            }
3946
        }
3947
3948
        $defaults['search_type'] = intval($searchType);
3949
        $defaults['q'] = api_htmlentities(Security::remove_XSS($query));
3950
3951
        if (!empty($defaultParams)) {
3952
            $defaults = array_merge($defaults, $defaultParams);
3953
        }
3954
        $form->setDefaults($defaults);
3955
3956
        $form->addButtonSearch(get_lang('Search'));
3957
3958
        $js = '<script>
3959
        extra_field_toogle();
3960
        function extra_field_toogle() {
3961
            if (jQuery("select[name=search_type]").val() != "1") { jQuery(".extra_field").hide(); } else { jQuery(".extra_field").show(); }
3962
        }
3963
        </script>';
3964
3965
        return $js.$form->returnForm();
3966
    }
3967
3968
    /**
3969
     * Shows the user menu
3970
     */
3971
    public static function show_menu()
3972
    {
3973
        echo '<div class="actions">';
3974
        echo '<a href="/main/auth/profile.php">'.Display::return_icon('profile.png').' '.get_lang('PersonalData').'</a>';
3975
        echo '<a href="/main/messages/inbox.php">'.Display::return_icon('inbox.png').' '.get_lang('Inbox').'</a>';
3976
        echo '<a href="/main/messages/outbox.php">'.Display::return_icon('outbox.png').' '.get_lang('Outbox').'</a>';
3977
        echo '<span style="float:right; padding-top:7px;">'.
3978
        '<a href="/main/auth/profile.php?show=1">'.Display::return_icon('edit.gif').' '.get_lang('Configuration').'</a>';
3979
        '</span>';
3980
        echo '</div>';
3981
    }
3982
3983
    /**
3984
     * Allow to register contact to social network
3985
     * @param int $friend_id user friend id
3986
     * @param int $my_user_id user id
3987
     * @param int $relation_type relation between users see constants definition
3988
     */
3989
    public static function relate_users($friend_id, $my_user_id, $relation_type)
3990
    {
3991
        $tbl_my_friend = Database :: get_main_table(TABLE_MAIN_USER_REL_USER);
3992
3993
        $friend_id = intval($friend_id);
3994
        $my_user_id = intval($my_user_id);
3995
        $relation_type = intval($relation_type);
3996
3997
        $sql = 'SELECT COUNT(*) as count FROM '.$tbl_my_friend.'
3998
                WHERE
3999
                    friend_user_id='.$friend_id.' AND
4000
                    user_id='.$my_user_id.' AND
4001
                    relation_type <> '.USER_RELATION_TYPE_RRHH.' ';
4002
        $result = Database::query($sql);
4003
        $row = Database :: fetch_array($result, 'ASSOC');
4004
        $current_date = date('Y-m-d H:i:s');
4005
4006
        if ($row['count'] == 0) {
4007
            $sql = 'INSERT INTO '.$tbl_my_friend.'(friend_user_id,user_id,relation_type,last_edit)
4008
                    VALUES ('.$friend_id.','.$my_user_id.','.$relation_type.',"'.$current_date.'")';
4009
            Database::query($sql);
4010
            return true;
4011
        }
4012
4013
        $sql = 'SELECT COUNT(*) as count, relation_type  FROM '.$tbl_my_friend.'
4014
                WHERE
4015
                    friend_user_id='.$friend_id.' AND
4016
                    user_id='.$my_user_id.' AND
4017
                    relation_type <> '.USER_RELATION_TYPE_RRHH.' ';
4018
        $result = Database::query($sql);
4019
        $row = Database :: fetch_array($result, 'ASSOC');
4020
4021
        if ($row['count'] == 1) {
4022
            //only for the case of a RRHH
4023
            if ($row['relation_type'] != $relation_type && $relation_type == USER_RELATION_TYPE_RRHH) {
4024
                $sql = 'INSERT INTO '.$tbl_my_friend.'(friend_user_id,user_id,relation_type,last_edit)
4025
                        VALUES ('.$friend_id.','.$my_user_id.','.$relation_type.',"'.$current_date.'")';
4026
            } else {
4027
                $sql = 'UPDATE '.$tbl_my_friend.' SET relation_type='.$relation_type.'
4028
                        WHERE friend_user_id='.$friend_id.' AND user_id='.$my_user_id;
4029
            }
4030
            Database::query($sql);
4031
4032
            return true;
4033
        }
4034
4035
        return false;
4036
    }
4037
4038
    /**
4039
     * Deletes a contact
4040
     * @param int user friend id
4041
     * @param bool true will delete ALL friends relationship from $friend_id
4042
     * @author isaac flores paz <[email protected]>
4043
     * @author Julio Montoya <[email protected]> Cleaning code
4044
     */
4045
    public static function remove_user_rel_user($friend_id, $real_removed = false, $with_status_condition = '')
4046
    {
4047
        $tbl_my_friend = Database :: get_main_table(TABLE_MAIN_USER_REL_USER);
4048
        $tbl_my_message = Database :: get_main_table(TABLE_MESSAGE);
4049
        $friend_id = intval($friend_id);
4050
4051
        if ($real_removed) {
4052
            $extra_condition = '';
4053
            if ($with_status_condition != '') {
4054
                $extra_condition = ' AND relation_type = '.intval($with_status_condition);
4055
            }
4056
            $sql = 'DELETE FROM '.$tbl_my_friend.'
4057
                    WHERE relation_type <> '.USER_RELATION_TYPE_RRHH.' AND friend_user_id='.$friend_id.' '.$extra_condition;
4058
            Database::query($sql);
4059
            $sql= 'DELETE FROM '.$tbl_my_friend.'
4060
                   WHERE relation_type <> '.USER_RELATION_TYPE_RRHH.' AND user_id='.$friend_id.' '.$extra_condition;
4061
            Database::query($sql);
4062
        } else {
4063
            $user_id = api_get_user_id();
4064
            $sql = 'SELECT COUNT(*) as count FROM '.$tbl_my_friend.'
4065
                    WHERE
4066
                        user_id='.$user_id.' AND
4067
                        relation_type NOT IN('.USER_RELATION_TYPE_DELETED.', '.USER_RELATION_TYPE_RRHH.') AND
4068
                        friend_user_id='.$friend_id;
4069
            $result = Database::query($sql);
4070
            $row = Database :: fetch_array($result, 'ASSOC');
4071
            if ($row['count'] == 1) {
4072
                //Delete user rel user
4073
                $sql_i = 'UPDATE '.$tbl_my_friend.' SET relation_type='.USER_RELATION_TYPE_DELETED.'
4074
                          WHERE user_id='.$user_id.' AND friend_user_id='.$friend_id;
4075
                $sql_j = 'UPDATE '.$tbl_my_message.' SET msg_status='.MESSAGE_STATUS_INVITATION_DENIED.'
4076
                          WHERE user_receiver_id='.$user_id.' AND user_sender_id='.$friend_id.' AND update_date="0000-00-00 00:00:00" ';
4077
                //Delete user
4078
                $sql_ij = 'UPDATE '.$tbl_my_friend.'  SET relation_type='.USER_RELATION_TYPE_DELETED.'
4079
                           WHERE user_id='.$friend_id.' AND friend_user_id='.$user_id;
4080
                $sql_ji = 'UPDATE '.$tbl_my_message.' SET msg_status='.MESSAGE_STATUS_INVITATION_DENIED.'
4081
                           WHERE user_receiver_id='.$friend_id.' AND user_sender_id='.$user_id.' AND update_date="0000-00-00 00:00:00" ';
4082
                Database::query($sql_i);
4083
                Database::query($sql_j);
4084
                Database::query($sql_ij);
4085
                Database::query($sql_ji);
4086
            }
4087
        }
4088
    }
4089
4090
    /**
4091
     * @param int $userId
4092
     * @return array
4093
     */
4094
    public static function getDrhListFromUser($userId)
4095
    {
4096
        $tblUser = Database::get_main_table(TABLE_MAIN_USER);
4097
        $tblUserRelUser = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
4098
        $tblUserRelAccessUrl = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
4099
        $userId = intval($userId);
4100
4101
        $orderBy = null;
4102
        if (api_is_western_name_order()) {
4103
            $orderBy .= " ORDER BY firstname, lastname ";
4104
        } else {
4105
            $orderBy .= " ORDER BY lastname, firstname ";
4106
        }
4107
4108
        $sql = "SELECT u.id, username, u.firstname, u.lastname
4109
                FROM $tblUser u
4110
                INNER JOIN $tblUserRelUser uru ON (uru.friend_user_id = u.id)
4111
                INNER JOIN $tblUserRelAccessUrl a ON (a.user_id = u.id)
4112
                WHERE
4113
                    access_url_id = ".api_get_current_access_url_id()." AND
4114
                    uru.user_id = '$userId' AND
4115
                    relation_type = '".USER_RELATION_TYPE_RRHH."'
4116
                $orderBy
4117
                ";
4118
        $result = Database::query($sql);
4119
4120
        return Database::store_result($result);
4121
    }
4122
4123
    /**
4124
     * get users followed by human resource manager
4125
     * @param int $userId
4126
     * @param int $userStatus (STUDENT, COURSEMANAGER, etc)
4127
     * @param bool $getOnlyUserId
4128
     * @param bool $getSql
4129
     * @param bool $getCount
4130
     * @param int $from
4131
     * @param int $numberItems
4132
     * @param int $column
4133
     * @param string $direction
4134
     * @param int $active
4135
     * @param string $lastConnectionDate
4136
     * @return array     users
4137
     */
4138 View Code Duplication
    public static function get_users_followed_by_drh(
4139
        $userId,
4140
        $userStatus = 0,
4141
        $getOnlyUserId = false,
4142
        $getSql = false,
4143
        $getCount = false,
4144
        $from = null,
4145
        $numberItems = null,
4146
        $column = null,
4147
        $direction = null,
4148
        $active = null,
4149
        $lastConnectionDate = null
4150
    ) {
4151
        return self::getUsersFollowedByUser(
4152
            $userId,
4153
            $userStatus,
4154
            $getOnlyUserId,
4155
            $getSql,
4156
            $getCount,
4157
            $from,
4158
            $numberItems,
4159
            $column,
4160
            $direction,
4161
            $active,
4162
            $lastConnectionDate,
4163
            DRH
4164
        );
4165
    }
4166
4167
    /**
4168
    * Get users followed by human resource manager
4169
    * @param int $userId
4170
    * @param int  $userStatus Filter users by status (STUDENT, COURSEMANAGER, etc)
4171
    * @param bool $getOnlyUserId
4172
    * @param bool $getSql
4173
    * @param bool $getCount
4174
    * @param int $from
4175
    * @param int $numberItems
4176
    * @param int $column
4177
    * @param string $direction
4178
    * @param int $active
4179
    * @param string $lastConnectionDate
4180
    * @param int $status the function is called by who? COURSEMANAGER, DRH?
4181
    * @param string $keyword
4182
     *
4183
    * @return array user list
4184
    */
4185
    public static function getUsersFollowedByUser(
4186
        $userId,
4187
        $userStatus = null,
4188
        $getOnlyUserId = false,
4189
        $getSql = false,
4190
        $getCount = false,
4191
        $from = null,
4192
        $numberItems = null,
4193
        $column = null,
4194
        $direction = null,
4195
        $active = null,
4196
        $lastConnectionDate = null,
4197
        $status = null,
4198
        $keyword = null
4199
    ) {
4200
        // Database Table Definitions
4201
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
4202
        $tbl_user_rel_user = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
4203
        $tbl_user_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
4204
4205
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
4206
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4207
4208
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4209
        $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
4210
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
4211
4212
        $userId = intval($userId);
4213
4214
        $limitCondition = '';
4215
4216 View Code Duplication
        if (isset($from) && isset($numberItems)) {
4217
            $from = intval($from);
4218
            $numberItems = intval($numberItems);
4219
            $limitCondition = "LIMIT $from, $numberItems";
4220
        }
4221
4222
        $column = Database::escape_string($column);
4223
        $direction = in_array(strtolower($direction), array('asc', 'desc')) ? $direction : null;
4224
4225
        $userConditions = '';
4226
        if (!empty($userStatus)) {
4227
            $userConditions .= ' AND u.status = '.intval($userStatus);
4228
        }
4229
4230
        $select = " SELECT DISTINCT u.id user_id, u.username, u.lastname, u.firstname, u.email ";
4231
        if ($getOnlyUserId) {
4232
            $select = " SELECT DISTINCT u.id user_id";
4233
        }
4234
4235
        $masterSelect = "SELECT DISTINCT * FROM ";
4236
4237
        if ($getCount) {
4238
            $masterSelect = "SELECT COUNT(DISTINCT(user_id)) as count FROM ";
4239
            $select = " SELECT DISTINCT(u.id) user_id";
4240
        }
4241
4242
        if (!is_null($active)) {
4243
            $active = intval($active);
4244
            $userConditions .= " AND u.active = $active ";
4245
        }
4246
4247 View Code Duplication
        if (!empty($keyword)) {
4248
            $keyword = Database::escape_string($keyword);
4249
            $userConditions .= " AND (
4250
                u.username LIKE '%$keyword%' OR
4251
                u.firstname LIKE '%$keyword%' OR
4252
                u.lastname LIKE '%$keyword%' OR
4253
                u.official_code LIKE '%$keyword%' OR
4254
                u.email LIKE '%$keyword%'
4255
            )";
4256
        }
4257
4258
        if (!empty($lastConnectionDate)) {
4259
            $lastConnectionDate = Database::escape_string($lastConnectionDate);
4260
            $userConditions .=  " AND u.last_login <= '$lastConnectionDate' ";
4261
        }
4262
4263
        $courseConditions = null;
4264
        $sessionConditionsCoach = null;
4265
        $sessionConditionsTeacher = null;
4266
        $drhConditions = null;
4267
        $teacherSelect = null;
4268
4269
        switch ($status) {
4270
            case DRH:
4271
                $drhConditions .= " AND
4272
                    friend_user_id = '$userId' AND
4273
                    relation_type = '".USER_RELATION_TYPE_RRHH."'
4274
                ";
4275
                break;
4276
            case COURSEMANAGER:
4277
                $drhConditions .= " AND
4278
                    friend_user_id = '$userId' AND
4279
                    relation_type = '".USER_RELATION_TYPE_RRHH."'
4280
                ";
4281
4282
                $sessionConditionsCoach .= " AND
4283
                    (s.id_coach = '$userId')
4284
                ";
4285
4286
                $sessionConditionsTeacher .= " AND
4287
                    (scu.status = 2 AND scu.user_id = '$userId')
4288
                ";
4289
4290
                $teacherSelect =
4291
                "UNION ALL (
4292
                        $select
4293
                        FROM $tbl_user u
4294
                        INNER JOIN $tbl_session_rel_user sru ON (sru.user_id = u.id)
4295
                        WHERE
4296
                            (
4297
                                sru.session_id IN (
4298
                                    SELECT DISTINCT(s.id) FROM $tbl_session s INNER JOIN
4299
                                    $tbl_session_rel_access_url session_rel_access_rel_user
4300
                                    ON session_rel_access_rel_user.session_id = s.id
4301
                                    WHERE access_url_id = ".api_get_current_access_url_id()."
4302
                                    $sessionConditionsCoach                                  
4303
                                ) OR sru.session_id IN (
4304
                                    SELECT DISTINCT(s.id) FROM $tbl_session s
4305
                                    INNER JOIN $tbl_session_rel_access_url url
4306
                                    ON (url.session_id = s.id)
4307
                                    INNER JOIN $tbl_session_rel_course_rel_user scu
4308
                                    ON (scu.session_id = s.id)
4309
                                    WHERE access_url_id = ".api_get_current_access_url_id()."
4310
                                    $sessionConditionsTeacher
4311
                                )
4312
                            )                            
4313
                            $userConditions
4314
                    )
4315
                    UNION ALL(
4316
                        $select
4317
                        FROM $tbl_user u
4318
                        INNER JOIN $tbl_course_user cu ON (cu.user_id = u.id)
4319
                        WHERE cu.c_id IN (
4320
                            SELECT DISTINCT(c_id) FROM $tbl_course_user
4321
                            WHERE user_id = $userId AND status = ".COURSEMANAGER."
4322
                        )
4323
                        $userConditions
4324
                    )"
4325
                ;
4326
                break;
4327
            case STUDENT_BOSS:
4328
                $drhConditions = " AND friend_user_id = $userId AND relation_type = " . USER_RELATION_TYPE_BOSS;
4329
                break;
4330
        }
4331
4332
        $join = null;
4333
        $sql = " $masterSelect
4334
                (
4335
                    (
4336
                        $select
4337
                        FROM $tbl_user u
4338
                        INNER JOIN $tbl_user_rel_user uru ON (uru.user_id = u.id)
4339
                        LEFT JOIN $tbl_user_rel_access_url a ON (a.user_id = u.id)
4340
                        $join
4341
                        WHERE
4342
                            access_url_id = ".api_get_current_access_url_id()."
4343
                            $drhConditions
4344
                            $userConditions
4345
                    )
4346
                    $teacherSelect
4347
4348
                ) as t1";
4349
4350
        if ($getSql) {
4351
            return $sql;
4352
        }
4353
        if ($getCount) {
4354
            $result = Database::query($sql);
4355
            $row = Database::fetch_array($result);
4356
            return $row['count'];
4357
        }
4358
4359
        $orderBy = null;
4360
        if ($getOnlyUserId == false) {
4361
            if (api_is_western_name_order()) {
4362
                $orderBy .= " ORDER BY firstname, lastname ";
4363
            } else {
4364
                $orderBy .= " ORDER BY lastname, firstname ";
4365
            }
4366
4367 View Code Duplication
            if (!empty($column) && !empty($direction)) {
4368
                // Fixing order due the UNIONs
4369
                $column = str_replace('u.', '', $column);
4370
                $orderBy = " ORDER BY $column $direction ";
4371
            }
4372
        }
4373
4374
        $sql .= $orderBy;
4375
        $sql .= $limitCondition;
4376
4377
        $result = Database::query($sql);
4378
        $users = array();
4379
        if (Database::num_rows($result) > 0) {
4380
4381
            while ($row = Database::fetch_array($result)) {
4382
                $users[$row['user_id']] = $row;
4383
            }
4384
        }
4385
4386
        return $users;
4387
    }
4388
4389
    /**
4390
     * Subscribes users to human resource manager (Dashboard feature)
4391
     * @param   int    $hr_dept_id
4392
     * @param   array   $users_id
4393
     * @param   int     affected rows
4394
     * */
4395
    public static function subscribeUsersToHRManager($hr_dept_id, $users_id)
4396
    {
4397
        return self::subscribeUsersToUser($hr_dept_id, $users_id, USER_RELATION_TYPE_RRHH);
4398
    }
4399
4400
    /**
4401
     * Add subscribed users to a user by relation type
4402
     * @param int $userId The user id
4403
     * @param array $subscribedUsersId The id of suscribed users
4404
     * @param string $relationType The relation type
4405
     * @param bool $deleteUsersBeforeInsert
4406
     */
4407
    public static function subscribeUsersToUser($userId, $subscribedUsersId, $relationType, $deleteUsersBeforeInsert = false)
4408
    {
4409
        $userRelUserTable = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
4410
        $userRelAccessUrlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
4411
4412
        $userId = intval($userId);
4413
        $relationType = intval($relationType);
4414
        $affectedRows = 0;
4415
4416
        if (api_get_multiple_access_url()) {
4417
            // Deleting assigned users to hrm_id
4418
            $sql = "SELECT s.user_id FROM $userRelUserTable s 
4419
                    INNER JOIN $userRelAccessUrlTable a ON (a.user_id = s.user_id) 
4420
                    WHERE 
4421
                        friend_user_id = $userId AND 
4422
                        relation_type = $relationType AND 
4423
                        access_url_id = " . api_get_current_access_url_id();
4424
        } else {
4425
            $sql = "SELECT user_id FROM $userRelUserTable 
4426
                    WHERE friend_user_id = $userId 
4427
                    AND relation_type = $relationType";
4428
        }
4429
        $result = Database::query($sql);
4430
4431
        if (Database::num_rows($result) > 0) {
4432
            while ($row = Database::fetch_array($result)) {
4433
                $sql = "DELETE FROM $userRelUserTable 
4434
                        WHERE 
4435
                          user_id = {$row['user_id']} AND 
4436
                          friend_user_id = $userId AND 
4437
                          relation_type = $relationType";
4438
                Database::query($sql);
4439
            }
4440
        }
4441
4442
        if ($deleteUsersBeforeInsert) {
4443
            $sql = "DELETE FROM $userRelUserTable 
4444
                    WHERE 
4445
                        user_id = $userId AND
4446
                        relation_type = $relationType";
4447
            Database::query($sql);
4448
        }
4449
4450
        // Inserting new user list
4451
        if (is_array($subscribedUsersId)) {
4452
            foreach ($subscribedUsersId as $subscribedUserId) {
4453
                $subscribedUserId = intval($subscribedUserId);
4454
4455
                $sql = "INSERT IGNORE INTO $userRelUserTable (user_id, friend_user_id, relation_type)
4456
                        VALUES ($subscribedUserId, $userId, $relationType)";
4457
4458
                $result = Database::query($sql);
4459
                $affectedRows = Database::affected_rows($result);
4460
            }
4461
        }
4462
4463
        return $affectedRows;
4464
    }
4465
4466
    /**
4467
     * This function check if an user is followed by human resources manager
4468
     * @param     int     $user_id
4469
     * @param    int      $hr_dept_id  Human resources manager
4470
     * @return    bool
4471
     */
4472
    public static function is_user_followed_by_drh($user_id, $hr_dept_id)
4473
    {
4474
        // Database table and variables Definitions
4475
        $tbl_user_rel_user = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
4476
        $user_id = intval($user_id);
4477
        $hr_dept_id = intval($hr_dept_id);
4478
        $result = false;
4479
4480
        $sql = "SELECT user_id FROM $tbl_user_rel_user
4481
                WHERE
4482
                    user_id = $user_id AND
4483
                    friend_user_id = $hr_dept_id AND
4484
                    relation_type = ".USER_RELATION_TYPE_RRHH;
4485
        $rs = Database::query($sql);
4486
        if (Database::num_rows($rs) > 0) {
4487
            $result = true;
4488
        }
4489
        return $result;
4490
    }
4491
4492
    /**
4493
     * get user id of teacher or session administrator
4494
     * @param array $courseInfo
4495
     *
4496
     * @return int The user id
4497
     */
4498
    public static function get_user_id_of_course_admin_or_session_admin($courseInfo)
4499
    {
4500
        $session = api_get_session_id();
4501
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
4502
        $table_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4503
        $table_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4504
        $courseId = $courseInfo['real_id'];
4505
4506
        if ($session == 0 || is_null($session)) {
4507
            $sql = 'SELECT u.id uid FROM '.$table_user.' u
4508
                    INNER JOIN '.$table_course_user.' ru
4509
                    ON ru.user_id = u.id
4510
                    WHERE
4511
                        ru.status = 1 AND
4512
                        ru.c_id = "'.$courseId.'" ';
4513
            $rs = Database::query($sql);
4514
            $num_rows = Database::num_rows($rs);
4515
            if ($num_rows == 1) {
4516
                $row = Database::fetch_array($rs);
4517
                return $row['uid'];
4518
            } else {
4519
                $my_num_rows = $num_rows;
4520
                $my_user_id = Database::result($rs, $my_num_rows - 1, 'uid');
4521
4522
                return $my_user_id;
4523
            }
4524
        } elseif ($session > 0) {
4525
            $sql = 'SELECT u.id uid FROM '.$table_user.' u
4526
                    INNER JOIN '.$table_session_course_user.' sru
4527
                    ON sru.user_id=u.id
4528
                    WHERE
4529
                        sru.c_id="'.$courseId.'" AND
4530
                        sru.status=2';
4531
            $rs = Database::query($sql);
4532
            $row = Database::fetch_array($rs);
4533
4534
            return $row['uid'];
4535
        }
4536
    }
4537
4538
    /**
4539
     * Determines if a user is a gradebook certified
4540
     * @param int $cat_id The category id of gradebook
4541
     * @param int $user_id The user id
4542
     * @return boolean
4543
     */
4544
    public static function is_user_certified($cat_id, $user_id)
4545
    {
4546
        $table_certificate = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
4547
        $sql = 'SELECT path_certificate FROM '.$table_certificate.'
4548
                WHERE
4549
                    cat_id="'.intval($cat_id).'" AND
4550
                    user_id="'.intval($user_id).'"';
4551
        $rs = Database::query($sql);
4552
        $row = Database::fetch_array($rs);
4553
        if ($row['path_certificate'] == '' || is_null($row['path_certificate'])) {
4554
            return false;
4555
        } else {
4556
            return true;
4557
        }
4558
    }
4559
4560
    /**
4561
     * Gets the info about a gradebook certificate for a user by course
4562
     * @param string $course_code The course code
4563
     * @param int $user_id The user id
4564
     * @return array  if there is not information return false
4565
     */
4566
    public static function get_info_gradebook_certificate($course_code, $user_id)
4567
    {
4568
        $tbl_grade_certificate = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
4569
        $tbl_grade_category = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
4570
        $session_id = api_get_session_id();
4571
4572
        if (empty($session_id)) {
4573
            $session_condition = ' AND (session_id = "" OR session_id = 0 OR session_id IS NULL )';
4574
        } else {
4575
            $session_condition = " AND session_id = $session_id";
4576
        }
4577
4578
        $sql = 'SELECT * FROM '.$tbl_grade_certificate.' WHERE cat_id = (SELECT id FROM '.$tbl_grade_category.'
4579
                WHERE
4580
                    course_code = "'.Database::escape_string($course_code).'" '.$session_condition.' LIMIT 1 ) AND
4581
                    user_id='.intval($user_id);
4582
4583
        $rs = Database::query($sql);
4584
        if (Database::num_rows($rs) > 0) {
4585
            $row = Database::fetch_array($rs, 'ASSOC');
4586
            $score = $row['score_certificate'];
4587
            $category_id = $row['cat_id'];
4588
            $cat = Category::load($category_id);
4589
            $displayscore = ScoreDisplay::instance();
4590
            if (isset($cat) && $displayscore->is_custom()) {
4591
                $grade = $displayscore->display_score(array($score, $cat[0]->get_weight()), SCORE_DIV_PERCENT_WITH_CUSTOM);
4592
            } else {
4593
                $grade = $displayscore->display_score(array($score, $cat[0]->get_weight()));
4594
            }
4595
            $row['grade'] = $grade;
4596
4597
            return $row;
4598
        }
4599
4600
        return false;
4601
    }
4602
4603
    /**
4604
     * Gets the user path of user certificated
4605
     * @param int The user id
4606
     * @return array  containing path_certificate and cat_id
4607
     */
4608
    public static function get_user_path_certificate($user_id)
4609
    {
4610
        $my_certificate = array();
4611
        $table_certificate = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
4612
        $table_gradebook_category = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
4613
4614
        $session_id = api_get_session_id();
4615
        $user_id = intval($user_id);
4616 View Code Duplication
        if ($session_id == 0 || is_null($session_id)) {
4617
            $sql_session = 'AND (session_id='.intval($session_id).' OR isnull(session_id)) ';
4618
        } elseif ($session_id > 0) {
4619
            $sql_session = 'AND session_id='.intval($session_id);
4620
        } else {
4621
            $sql_session = '';
4622
        }
4623
        $sql = "SELECT tc.path_certificate,tc.cat_id,tgc.course_code,tgc.name
4624
                FROM $table_certificate tc, $table_gradebook_category tgc
4625
                WHERE tgc.id = tc.cat_id AND tc.user_id = $user_id
4626
                ORDER BY tc.date_certificate DESC 
4627
                LIMIT 5";
4628
4629
        $rs = Database::query($sql);
4630
        while ($row = Database::fetch_array($rs)) {
4631
            $my_certificate[] = $row;
4632
        }
4633
        return $my_certificate;
4634
    }
4635
4636
    /**
4637
     * This function check if the user is a coach inside session course
4638
     * @param  int  $user_id    User id
4639
     * @param  int  $courseId
4640
     * @param  int  $session_id
4641
     * @return bool    True if the user is a coach
4642
     *
4643
     */
4644 View Code Duplication
    public static function is_session_course_coach($user_id, $courseId, $session_id)
4645
    {
4646
        $tbl_session_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4647
        // Protect data
4648
        $user_id = intval($user_id);
4649
        $courseId = intval($courseId);
4650
        $session_id = intval($session_id);
4651
        $result = false;
4652
4653
        $sql = "SELECT session_id FROM $tbl_session_course_rel_user
4654
                WHERE
4655
                  session_id = $session_id AND
4656
                  c_id = $courseId AND
4657
                  user_id = $user_id AND
4658
                  status = 2 ";
4659
        $res = Database::query($sql);
4660
4661
        if (Database::num_rows($res) > 0) {
4662
            $result = true;
4663
        }
4664
        return $result;
4665
    }
4666
4667
    /**
4668
     * This function returns an icon path that represents the favicon of the website of which the url given.
4669
     * Defaults to the current Chamilo favicon
4670
     * @param    string    $url1 URL of website where to look for favicon.ico
4671
     * @param    string    $url2 Optional second URL of website where to look for favicon.ico
4672
     * @return    string    Path of icon to load
4673
     */
4674
    public static function get_favicon_from_url($url1, $url2 = null)
4675
    {
4676
        $icon_link = '';
4677
        $url = $url1;
4678
        if (empty($url1)) {
4679
            $url = $url2;
4680
            if (empty($url)) {
4681
                $url = api_get_access_url(api_get_current_access_url_id());
4682
                $url = $url[0];
4683
            }
4684
        }
4685
        if (!empty($url)) {
4686
            $pieces = parse_url($url);
4687
            $icon_link = $pieces['scheme'].'://'.$pieces['host'].'/favicon.ico';
4688
        }
4689
        return $icon_link;
4690
    }
4691
4692
    /**
4693
     *
4694
     * @param int   student id
4695
     * @param int   years
4696
     * @param bool  show warning_message
4697
     * @param bool  return_timestamp
4698
     */
4699
    public static function delete_inactive_student($student_id, $years = 2, $warning_message = false, $return_timestamp = false)
4700
    {
4701
        $tbl_track_login = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
4702
        $sql = 'SELECT login_date FROM '.$tbl_track_login.'
4703
                WHERE login_user_id = '.intval($student_id).'
4704
                ORDER BY login_date DESC LIMIT 0,1';
4705
        if (empty($years)) {
4706
            $years = 1;
4707
        }
4708
        $inactive_time = $years * 31536000;  //1 year
4709
        $rs = Database::query($sql);
4710
        if (Database::num_rows($rs) > 0) {
4711
            if ($last_login_date = Database::result($rs, 0, 0)) {
4712
                $last_login_date = api_get_local_time($last_login_date, null, date_default_timezone_get());
4713
                if ($return_timestamp) {
4714
                    return api_strtotime($last_login_date);
4715
                } else {
4716
                    if (!$warning_message) {
4717
                        return api_format_date($last_login_date, DATE_FORMAT_SHORT);
4718
                    } else {
4719
                        $timestamp = api_strtotime($last_login_date);
4720
                        $currentTimestamp = time();
4721
4722
                        //If the last connection is > than 7 days, the text is red
4723
                        //345600 = 7 days in seconds 63072000= 2 ans
4724
                        // if ($currentTimestamp - $timestamp > 184590 )
4725
                        if ($currentTimestamp - $timestamp > $inactive_time && UserManager::delete_user($student_id)) {
4726
                            Display :: display_normal_message(get_lang('UserDeleted'));
0 ignored issues
show
Deprecated Code introduced by
The method Display::display_normal_message() has been deprecated with message: use Display::addFlash with Display::return_message($message, 'normal');

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
4727
                            echo '<p>', 'id', $student_id, ':', $last_login_date, '</p>';
4728
                        }
4729
                    }
4730
                }
4731
            }
4732
        }
4733
        return false;
4734
    }
4735
4736
    /**
4737
     * @param FormValidator $form
4738
     * @param $extra_data
4739
     * @param $form_name
4740
     * @param bool $admin_permissions
4741
     * @param null $user_id
4742
     * @deprecated
4743
     * @return array
4744
     */
4745
    public static function set_extra_fields_in_form(
4746
        $form,
4747
        $extra_data,
4748
        $admin_permissions = false,
4749
        $user_id = null
4750
    ) {
4751
        $user_id = intval($user_id);
4752
4753
        // EXTRA FIELDS
4754
        $extra = UserManager::get_extra_fields(0, 50, 5, 'ASC');
4755
        $jquery_ready_content = null;
4756
        foreach ($extra as $field_details) {
4757
4758
            if (!$admin_permissions) {
4759
                if ($field_details[6] == 0) {
4760
                    continue;
4761
                }
4762
            }
4763
4764
            switch ($field_details[2]) {
4765 View Code Duplication
                case ExtraField::FIELD_TYPE_TEXT:
4766
                    $form->addElement('text', 'extra_'.$field_details[1], $field_details[3], array('size' => 40));
4767
                    $form->applyFilter('extra_'.$field_details[1], 'stripslashes');
4768
                    $form->applyFilter('extra_'.$field_details[1], 'trim');
4769
                    $form->applyFilter('extra_'.$field_details[1], 'html_filter');
4770
4771
                    if (!$admin_permissions) {
4772
                        if ($field_details[7] == 0) {
4773
                            $form->freeze('extra_'.$field_details[1]);
4774
                        }
4775
                    }
4776
                    break;
4777 View Code Duplication
                case ExtraField::FIELD_TYPE_TEXTAREA:
4778
                    $form->addHtmlEditor(
4779
                        'extra_'.$field_details[1],
4780
                        $field_details[3],
4781
                        false,
4782
                        false,
4783
                        array('ToolbarSet' => 'Profile', 'Width' => '100%', 'Height' => '130')
4784
                    );
4785
                    $form->applyFilter('extra_'.$field_details[1], 'stripslashes');
4786
                    $form->applyFilter('extra_'.$field_details[1], 'trim');
4787
                    if (!$admin_permissions) {
4788
                        if ($field_details[7] == 0)
4789
                            $form->freeze('extra_'.$field_details[1]);
4790
                    }
4791
                    break;
4792
                case ExtraField::FIELD_TYPE_RADIO:
4793
                    $group = array();
4794 View Code Duplication
                    foreach ($field_details[9] as $option_id => $option_details) {
4795
                        $options[$option_details[1]] = $option_details[2];
4796
                        $group[] = $form->createElement(
4797
                            'radio',
4798
                            'extra_'.$field_details[1],
4799
                            $option_details[1],
4800
                            $option_details[2].'<br />',
4801
                            $option_details[1]
4802
                        );
4803
                    }
4804
                    $form->addGroup($group, 'extra_'.$field_details[1], $field_details[3]);
4805
                    if (!$admin_permissions) {
4806
                        if ($field_details[7] == 0) {
4807
                            $form->freeze('extra_'.$field_details[1]);
4808
                        }
4809
                    }
4810
                    break;
4811
                case ExtraField::FIELD_TYPE_SELECT:
4812
                    $get_lang_variables = false;
4813 View Code Duplication
                    if (in_array(
4814
                        $field_details[1],
4815
                        array(
4816
                            'mail_notify_message',
4817
                            'mail_notify_invitation',
4818
                            'mail_notify_group_message',
4819
                        )
4820
                    )) {
4821
                        $get_lang_variables = true;
4822
                    }
4823
                    $options = array();
4824
4825
                    foreach ($field_details[9] as $option_id => $option_details) {
4826
                        if ($get_lang_variables) {
4827
                            $options[$option_details[1]] = get_lang($option_details[2]);
4828
                        } else {
4829
                            $options[$option_details[1]] = $option_details[2];
4830
                        }
4831
                    }
4832
4833
                    if ($get_lang_variables) {
4834
                        $field_details[3] = get_lang($field_details[3]);
4835
                    }
4836
4837
                    $form->addElement(
4838
                        'select',
4839
                        'extra_'.$field_details[1],
4840
                        $field_details[3],
4841
                        $options,
4842
                        array('id' => 'extra_' . $field_details[1])
4843
                    );
4844
4845
                    if (!$admin_permissions) {
4846
                        if ($field_details[7] == 0)
4847
                            $form->freeze('extra_'.$field_details[1]);
4848
                    }
4849
                    break;
4850
                case ExtraField::FIELD_TYPE_SELECT_MULTIPLE:
4851
                    $options = array();
4852
                    foreach ($field_details[9] as $option_id => $option_details) {
4853
                        $options[$option_details[1]] = $option_details[2];
4854
                    }
4855
                    $form->addElement(
4856
                        'select',
4857
                        'extra_'.$field_details[1],
4858
                        $field_details[3],
4859
                        $options,
4860
                        array('multiple' => 'multiple')
4861
                    );
4862
                    if (!$admin_permissions) {
4863
                        if ($field_details[7] == 0)
4864
                            $form->freeze('extra_'.$field_details[1]);
4865
                    }
4866
                    break;
4867 View Code Duplication
                case ExtraField::FIELD_TYPE_DATE:
4868
                    $form->addDatePicker('extra_'.$field_details[1], $field_details[3]);
4869
                    $defaults['extra_'.$field_details[1]] = date('Y-m-d 12:00:00');
4870
                    $form->setDefaults($defaults);
4871
                    if (!$admin_permissions) {
4872
                        if ($field_details[7] == 0)
4873
                            $form->freeze('extra_'.$field_details[1]);
4874
                    }
4875
                    $form->applyFilter('theme', 'trim');
4876
                    break;
4877 View Code Duplication
                case ExtraField::FIELD_TYPE_DATETIME:
4878
                    $form->addDateTimePicker('extra_'.$field_details[1], $field_details[3]);
4879
                    $defaults['extra_'.$field_details[1]] = date('Y-m-d 12:00:00');
4880
                    $form->setDefaults($defaults);
4881
                    if (!$admin_permissions) {
4882
                        if ($field_details[7] == 0)
4883
                            $form->freeze('extra_'.$field_details[1]);
4884
                    }
4885
                    $form->applyFilter('theme', 'trim');
4886
                    break;
4887
                case ExtraField::FIELD_TYPE_DOUBLE_SELECT:
4888
                    foreach ($field_details[9] as $key => $element) {
4889
                        if ($element[2][0] == '*') {
4890
                            $values['*'][$element[0]] = str_replace('*', '', $element[2]);
4891
                        } else {
4892
                            $values[0][$element[0]] = $element[2];
4893
                        }
4894
                    }
4895
4896
                    $group = '';
4897
                    $group[] = $form->createElement('select', 'extra_'.$field_details[1], '', $values[0], '');
4898
                    $group[] = $form->createElement('select', 'extra_'.$field_details[1].'*', '', $values['*'], '');
4899
                    $form->addGroup($group, 'extra_'.$field_details[1], $field_details[3]);
4900
4901
                    if (!$admin_permissions) {
4902
                        if ($field_details[7] == 0)
4903
                            $form->freeze('extra_'.$field_details[1]);
4904
                    }
4905
4906
                    /* Recoding the selected values for double : if the user has
4907
                    selected certain values, we have to assign them to the
4908
                    correct select form */
4909
                    if (array_key_exists('extra_'.$field_details[1], $extra_data)) {
4910
                        // exploding all the selected values (of both select forms)
4911
                        $selected_values = explode(';', $extra_data['extra_'.$field_details[1]]);
4912
                        $extra_data['extra_'.$field_details[1]] = array();
4913
4914
                        // looping through the selected values and assigning the selected values to either the first or second select form
4915
                        foreach ($selected_values as $key => $selected_value) {
4916
                            if (array_key_exists($selected_value, $values[0])) {
4917
                                $extra_data['extra_'.$field_details[1]]['extra_'.$field_details[1]] = $selected_value;
4918
                            } else {
4919
                                $extra_data['extra_'.$field_details[1]]['extra_'.$field_details[1].'*'] = $selected_value;
4920
                            }
4921
                        }
4922
                    }
4923
                    break;
4924
                case ExtraField::FIELD_TYPE_DIVIDER:
4925
                    $form->addElement('static', $field_details[1], '<br /><strong>'.$field_details[3].'</strong>');
4926
                    break;
4927
                case ExtraField::FIELD_TYPE_TAG:
4928
                    //the magic should be here
4929
                    $user_tags = UserManager::get_user_tags($user_id, $field_details[0]);
4930
4931
                    $tag_list = '';
4932
                    if (is_array($user_tags) && count($user_tags) > 0) {
4933
                        foreach ($user_tags as $tag) {
4934
                            $tag_list .= '<option value="'.$tag['tag'].'" class="selected">'.$tag['tag'].'</option>';
4935
                        }
4936
                    }
4937
4938
                    $multi_select = '<select id="extra_'.$field_details[1].'" name="extra_'.$field_details[1].'">
4939
                                    '.$tag_list.'
4940
                                    </select>';
4941
4942
                    $form->addElement('label', $field_details[3], $multi_select);
4943
                    $url = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php';
4944
                    $complete_text = get_lang('StartToType');
4945
                    //if cache is set to true the jquery will be called 1 time
4946
                    $jquery_ready_content = <<<EOF
4947
                    $("#extra_$field_details[1]").fcbkcomplete({
4948
                        json_url: "$url?a=search_tags&field_id=$field_details[0]",
4949
                        cache: false,
4950
                        filter_case: true,
4951
                        filter_hide: true,
4952
                        complete_text:"$complete_text",
4953
                        firstselected: true,
4954
                        //onremove: "testme",
4955
                        //onselect: "testme",
4956
                        filter_selected: true,
4957
                        newel: true
4958
                    });
4959
EOF;
4960
                    break;
4961
                case ExtraField::FIELD_TYPE_TIMEZONE:
4962
                    $form->addElement('select', 'extra_'.$field_details[1], $field_details[3], api_get_timezones(), '');
4963
                    if ($field_details[7] == 0)
4964
                        $form->freeze('extra_'.$field_details[1]);
4965
                    break;
4966
                case ExtraField::FIELD_TYPE_SOCIAL_PROFILE:
4967
                    // get the social network's favicon
4968
                    $icon_path = UserManager::get_favicon_from_url($extra_data['extra_'.$field_details[1]], $field_details[4]);
4969
                    // special hack for hi5
4970
                    $leftpad = '1.7';
4971
                    $top = '0.4';
4972
                    $domain = parse_url($icon_path, PHP_URL_HOST);
4973
                    if ($domain == 'www.hi5.com' or $domain == 'hi5.com') {
4974
                        $leftpad = '3';
4975
                        $top = '0';
4976
                    }
4977
                    // print the input field
4978
                    $form->addElement(
4979
                        'text',
4980
                        'extra_'.$field_details[1],
4981
                        $field_details[3],
4982
                        array(
4983
                            'size' => 60,
4984
                            'style' => 'background-image: url(\''.$icon_path.'\'); background-repeat: no-repeat; background-position: 0.4em '.$top.'em; padding-left: '.$leftpad.'em; '
4985
                        )
4986
                    );
4987
                    $form->applyFilter('extra_'.$field_details[1], 'stripslashes');
4988
                    $form->applyFilter('extra_'.$field_details[1], 'trim');
4989
                    if ($field_details[7] == 0)
4990
                        $form->freeze('extra_'.$field_details[1]);
4991
                    break;
4992
                case ExtraField::FIELD_TYPE_FILE:
4993
                    $extra_field = 'extra_'.$field_details[1];
4994
                    $form->addElement('file', $extra_field, $field_details[3], null, '');
4995
                    if ($extra_file_list = UserManager::build_user_extra_file_list($user_id, $field_details[1], '', true)) {
4996
                        $form->addElement('static', $extra_field . '_list', null, $extra_file_list);
4997
                    }
4998
                    if ($field_details[7] == 0) {
4999
                        $form->freeze($extra_field);
5000
                    }
5001
                    break;
5002 View Code Duplication
                case ExtraField::FIELD_TYPE_MOBILE_PHONE_NUMBER:
5003
                    $form->addElement(
5004
                        'text',
5005
                        'extra_'.$field_details[1],
5006
                        $field_details[3]." (".get_lang('CountryDialCode').")",
5007
                        array('size' => 40, 'placeholder'  => '(xx)xxxxxxxxx')
5008
                    );
5009
                    $form->applyFilter('extra_'.$field_details[1], 'stripslashes');
5010
                    $form->applyFilter('extra_'.$field_details[1], 'trim');
5011
                    $form->applyFilter('extra_'.$field_details[1], 'mobile_phone_number_filter');
5012
                    $form->addRule(
5013
                        'extra_'.$field_details[1],
5014
                        get_lang('MobilePhoneNumberWrong'),
5015
                        'mobile_phone_number'
5016
                    );
5017
                    if (!$admin_permissions) {
5018
                        if ($field_details[7] == 0) {
5019
                            $form->freeze('extra_'.$field_details[1]);
5020
                        }
5021
                    }
5022
                    break;
5023
            }
5024
        }
5025
        $return = array();
5026
        $return['jquery_ready_content'] = $jquery_ready_content;
5027
        return $return;
5028
    }
5029
5030
    /**
5031
     * @return array
5032
     */
5033
    public static function get_user_field_types()
5034
    {
5035
        $types = array();
5036
        $types[self::USER_FIELD_TYPE_TEXT] = get_lang('FieldTypeText');
5037
        $types[self::USER_FIELD_TYPE_TEXTAREA] = get_lang('FieldTypeTextarea');
5038
        $types[self::USER_FIELD_TYPE_RADIO] = get_lang('FieldTypeRadio');
5039
        $types[self::USER_FIELD_TYPE_SELECT] = get_lang('FieldTypeSelect');
5040
        $types[self::USER_FIELD_TYPE_SELECT_MULTIPLE] = get_lang('FieldTypeSelectMultiple');
5041
        $types[self::USER_FIELD_TYPE_DATE] = get_lang('FieldTypeDate');
5042
        $types[self::USER_FIELD_TYPE_DATETIME] = get_lang('FieldTypeDatetime');
5043
        $types[self::USER_FIELD_TYPE_DOUBLE_SELECT] = get_lang('FieldTypeDoubleSelect');
5044
        $types[self::USER_FIELD_TYPE_DIVIDER] = get_lang('FieldTypeDivider');
5045
        $types[self::USER_FIELD_TYPE_TAG] = get_lang('FieldTypeTag');
5046
        $types[self::USER_FIELD_TYPE_TIMEZONE] = get_lang('FieldTypeTimezone');
5047
        $types[self::USER_FIELD_TYPE_SOCIAL_PROFILE] = get_lang('FieldTypeSocialProfile');
5048
        $types[self::USER_FIELD_TYPE_FILE] = get_lang('FieldTypeFile');
5049
        $types[self::USER_FIELD_TYPE_MOBILE_PHONE_NUMBER] = get_lang('FieldTypeMobilePhoneNumber');
5050
5051
        return $types;
5052
    }
5053
5054
    /**
5055
     * @param User $user
5056
     */
5057
    public static function add_user_as_admin(User $user)
5058
    {
5059
        $table_admin = Database :: get_main_table(TABLE_MAIN_ADMIN);
5060
        if ($user) {
5061
            $userId = $user->getId();
5062
5063
            if (!self::is_admin($userId)) {
5064
                $sql = "INSERT INTO $table_admin SET user_id = $userId";
5065
                Database::query($sql);
5066
            }
5067
5068
            $user->addRole('ROLE_SUPER_ADMIN');
5069
            self::getManager()->updateUser($user, true);
5070
        }
5071
    }
5072
5073
    /**
5074
     * @param int $userId
5075
     */
5076
    public static function remove_user_admin($userId)
5077
    {
5078
        $table_admin = Database :: get_main_table(TABLE_MAIN_ADMIN);
5079
        $userId = intval($userId);
5080
        if (self::is_admin($userId)) {
5081
            $sql = "DELETE FROM $table_admin WHERE user_id = $userId";
5082
            Database::query($sql);
5083
        }
5084
    }
5085
5086
    /**
5087
     * @param string $from
5088
     * @param string $to
5089
     */
5090
    public static function update_all_user_languages($from, $to)
5091
    {
5092
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
5093
        $from = Database::escape_string($from);
5094
        $to = Database::escape_string($to);
5095
5096
        if (!empty($to) && !empty($from)) {
5097
            $sql = "UPDATE $table_user SET language = '$to'
5098
                    WHERE language = '$from'";
5099
            Database::query($sql);
5100
        }
5101
    }
5102
5103
    /**
5104
     * Subscribe boss to students
5105
     *
5106
     * @param int $bossId The boss id
5107
     * @param array $usersId The users array
5108
     * @return int Affected rows
5109
     */
5110
    public static function subscribeBossToUsers($bossId, $usersId)
5111
    {
5112
        return self::subscribeUsersToUser($bossId, $usersId, USER_RELATION_TYPE_BOSS);
5113
    }
5114
5115
    /**
5116
     * Subscribe boss to students
5117
     *
5118
     * @param int $studentId
5119
     * @param array $bossList
5120
     * @return int Affected rows
5121
     */
5122
    public static function subscribeUserToBossList($studentId, $bossList)
5123
    {
5124
        if ($bossList) {
5125
            $studentId = (int) $studentId;
5126
            $userRelUserTable = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
5127
            $sql = "DELETE FROM $userRelUserTable 
5128
                    WHERE user_id = $studentId AND relation_type = ".USER_RELATION_TYPE_BOSS;
5129
            Database::query($sql);
5130
5131
            foreach ($bossList as $bossId) {
5132
                $bossId = (int) $bossId;
5133
                $sql = "INSERT IGNORE INTO $userRelUserTable (user_id, friend_user_id, relation_type)
5134
                        VALUES ($studentId, $bossId, ".USER_RELATION_TYPE_BOSS.")";
5135
5136
                Database::query($sql);
5137
            }
5138
        }
5139
    }
5140
5141
    /**
5142
     * Get users followed by student boss
5143
     * @param int $userId
5144
     * @param int $userStatus (STUDENT, COURSEMANAGER, etc)
5145
     * @param bool $getOnlyUserId
5146
     * @param bool $getSql
5147
     * @param bool $getCount
5148
     * @param int $from
5149
     * @param int $numberItems
5150
     * @param int $column
5151
     * @param string $direction
5152
     * @param int $active
5153
     * @param string $lastConnectionDate
5154
     * @return array     users
5155
     */
5156 View Code Duplication
    public static function getUsersFollowedByStudentBoss(
5157
        $userId,
5158
        $userStatus = 0,
5159
        $getOnlyUserId = false,
5160
        $getSql = false,
5161
        $getCount = false,
5162
        $from = null,
5163
        $numberItems = null,
5164
        $column = null,
5165
        $direction = null,
5166
        $active = null,
5167
        $lastConnectionDate = null
5168
    ){
5169
        return self::getUsersFollowedByUser(
5170
            $userId,
5171
            $userStatus,
5172
            $getOnlyUserId,
5173
            $getSql,
5174
            $getCount,
5175
            $from,
5176
            $numberItems,
5177
            $column,
5178
            $direction,
5179
            $active,
5180
            $lastConnectionDate,
5181
            STUDENT_BOSS
5182
        );
5183
    }
5184
5185
    /**
5186
     * Get the teacher (users with COURSEMANGER status) list
5187
     * @return array The list
5188
     */
5189
    public static function getTeachersList()
5190
    {
5191
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
5192
5193
        $resultData = Database::select('user_id, lastname, firstname, username', $userTable, array(
5194
            'where' => array(
5195
                'status = ?' => COURSEMANAGER
5196
            )
5197
        ));
5198
5199
        foreach ($resultData as &$teacherData) {
5200
            $teacherData['completeName'] = api_get_person_name($teacherData['firstname'], $teacherData['lastname']);
5201
        }
5202
5203
        return $resultData;
5204
    }
5205
5206
    /**
5207
     * @return array
5208
     */
5209 View Code Duplication
    public static function getOfficialCodeGrouped()
5210
    {
5211
        $user = Database::get_main_table(TABLE_MAIN_USER);
5212
        $sql = "SELECT DISTINCT official_code
5213
                FROM $user
5214
                GROUP BY official_code";
5215
        $result = Database::query($sql);
5216
5217
        $values = Database::store_result($result, 'ASSOC');
5218
5219
        $result = array();
5220
        foreach ($values as $value) {
5221
            $result[$value['official_code']] = $value['official_code'];
5222
        }
5223
        return $result;
5224
    }
5225
5226
    /**
5227
     * @param string $officialCode
5228
     * @return array
5229
     */
5230
    public static function getUsersByOfficialCode($officialCode)
5231
    {
5232
        $user = Database::get_main_table(TABLE_MAIN_USER);
5233
        $officialCode = Database::escape_string($officialCode);
5234
5235
        $sql = "SELECT DISTINCT id
5236
                FROM $user
5237
                WHERE official_code = '$officialCode'
5238
                ";
5239
        $result = Database::query($sql);
5240
5241
        $users = array();
5242
        while ($row = Database::fetch_array($result)) {
5243
            $users[] = $row['id'];
5244
        }
5245
        return $users;
5246
    }
5247
5248
    /**
5249
     * Calc the expended time (in seconds) by a user in a course
5250
     * @param int $userId The user id
5251
     * @param int $courseId The course id
5252
     * @param int $sessionId Optional. The session id
5253
     * @param string $from Optional. From date
5254
     * @param string $until Optional. Until date
5255
     * @return int The time
5256
     */
5257
    public static function getTimeSpentInCourses($userId, $courseId, $sessionId = 0, $from = '', $until = '')
5258
    {
5259
        $userId = intval($userId);
5260
        $sessionId = intval($sessionId);
5261
5262
        $trackCourseAccessTable = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5263
5264
        $whereConditions = array(
5265
            'user_id = ? ' => $userId,
5266
            'AND c_id = ? ' => $courseId,
5267
            'AND session_id = ? ' => $sessionId
5268
        );
5269
5270 View Code Duplication
        if (!empty($from) && !empty($until)) {
5271
            $whereConditions["AND (login_course_date >= '?' "] = $from;
5272
            $whereConditions["AND logout_course_date <= DATE_ADD('?', INTERVAL 1 DAY)) "] = $until;
5273
        }
5274
5275
        $trackResult = Database::select(
5276
            'SUM(UNIX_TIMESTAMP(logout_course_date) - UNIX_TIMESTAMP(login_course_date)) as total_time',
5277
            $trackCourseAccessTable,
5278
            array(
5279
                'where' => $whereConditions
5280
            ), 'first'
5281
        );
5282
5283
        if ($trackResult != false) {
5284
            return $trackResult['total_time'] ? $trackResult['total_time'] : 0;
5285
        }
5286
5287
        return 0;
5288
    }
5289
5290
    /**
5291
     * Get the boss user ID from a followed user id
5292
     * @param $userId
5293
     * @return bool
5294
     */
5295 View Code Duplication
    public static function getFirstStudentBoss($userId)
5296
    {
5297
        $userId = intval($userId);
5298
        if ($userId > 0) {
5299
            $userRelTable = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
5300
            $row = Database::select(
5301
                'DISTINCT friend_user_id AS boss_id',
5302
                $userRelTable,
5303
                array(
5304
                    'where' => array(
5305
                        'user_id = ? AND relation_type = ? LIMIT 1' => array(
5306
                            $userId,
5307
                            USER_RELATION_TYPE_BOSS,
5308
                        )
5309
                    )
5310
                )
5311
            );
5312
            if (!empty($row)) {
5313
5314
                return $row[0]['boss_id'];
5315
            }
5316
        }
5317
5318
        return false;
5319
    }
5320
5321
    /**
5322
     * Get the boss user ID from a followed user id
5323
     * @param $userId
5324
     * @return bool
5325
     */
5326 View Code Duplication
    public static function getStudentBossList($userId)
5327
    {
5328
        $userId = intval($userId);
5329
        if ($userId > 0) {
5330
            $userRelTable = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
5331
            $result = Database::select(
5332
                'DISTINCT friend_user_id AS boss_id',
5333
                $userRelTable,
5334
                array(
5335
                    'where' => array(
5336
                        'user_id = ? AND relation_type = ? ' => array(
5337
                            $userId,
5338
                            USER_RELATION_TYPE_BOSS,
5339
                        )
5340
                    )
5341
                ),
5342
                'all'
5343
            );
5344
5345
            return $result;
5346
        }
5347
5348
        return false;
5349
    }
5350
5351
    /**
5352
     * @param int $bossId
5353
     * @param int $studentId
5354
     *
5355
     * @return bool
5356
     */
5357
    public static function userIsBossOfStudent($bossId, $studentId)
5358
    {
5359
        $result = false;
5360
        $bossList = UserManager::getStudentBossList($studentId);
5361
        if ($bossList) {
5362
            $bossList = array_column($bossList, 'boss_id');
5363
            if (in_array($bossId, $bossList)) {
5364
                $result = true;
5365
            }
5366
        }
5367
5368
        return $result;
5369
    }
5370
5371
    /**
5372
     * Get either a Gravatar URL or complete image tag for a specified email address.
5373
     *
5374
     * @param string $email The email address
5375
     * @param string $s Size in pixels, defaults to 80px [ 1 - 2048 ]
5376
     * @param string $d Default imageset to use [ 404 | mm | identicon | monsterid | wavatar ]
5377
     * @param string $r Maximum rating (inclusive) [ g | pg | r | x ]
5378
     * @param boole $img True to return a complete IMG tag False for just the URL
5379
     * @param array $atts Optional, additional key/value attributes to include in the IMG tag
5380
     * @return String containing either just a URL or a complete image tag
5381
     * @source http://gravatar.com/site/implement/images/php/
5382
     */
5383
    private static function getGravatar(
5384
        $email,
5385
        $s = 80,
5386
        $d = 'mm',
5387
        $r = 'g',
5388
        $img = false,
5389
        $atts = array()
5390
    ) {
5391
        $url = 'http://www.gravatar.com/avatar/';
5392
        if (!empty($_SERVER['HTTPS'])) {
5393
            $url = 'https://secure.gravatar.com/avatar/';
5394
        }
5395
        $url .= md5( strtolower( trim( $email ) ) );
5396
        $url .= "?s=$s&d=$d&r=$r";
5397
        if ( $img ) {
5398
            $url = '<img src="' . $url . '"';
5399
            foreach ( $atts as $key => $val )
5400
                $url .= ' ' . $key . '="' . $val . '"';
5401
            $url .= ' />';
5402
        }
5403
        return $url;
5404
    }
5405
5406
    /**
5407
     * Displays the name of the user and makes the link to the user profile
5408
     * @param array $userInfo
5409
     *
5410
     * @return string
5411
     */
5412
    public static function getUserProfileLink($userInfo)
5413
    {
5414
        if (isset($userInfo) && isset($userInfo['user_id'])) {
5415
            return Display::url(
5416
                $userInfo['complete_name_with_username'],
5417
                $userInfo['profile_url']
5418
            );
5419
        } else {
5420
            return get_lang('Anonymous');
5421
        }
5422
    }
5423
5424
    /**
5425
     * Displays the name of the user and makes the link to the user profile
5426
     *
5427
     * @param $userInfo
5428
     *
5429
     * @return string
5430
     */
5431
    public static function getUserProfileLinkWithPicture($userInfo)
5432
    {
5433
        return Display::url(Display::img($userInfo['avatar']), $userInfo['profile_url']);
5434
    }
5435
5436
    /**
5437
     * Get users whose name matches $firstname and $lastname
5438
     * @param string $firstname Firstname to search
5439
     * @param string $lastname Lastname to search
5440
     * @return array The user list
5441
     */
5442
    public static function getUserByName($firstname, $lastname)
5443
    {
5444
        $firstname = Database::escape_string($firstname);
5445
        $lastname = Database::escape_string($lastname);
5446
5447
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
5448
5449
        $sql = <<<SQL
5450
            SELECT id, username, lastname, firstname
5451
            FROM $userTable
5452
            WHERE 
5453
                firstname LIKE '$firstname%' AND
5454
                lastname LIKE '$lastname%'
5455
SQL;
5456
5457
        $result = Database::query($sql);
5458
5459
        $users = [];
5460
        while ($resultData = Database::fetch_object($result)) {
5461
            $users[] = $resultData;
5462
        }
5463
5464
        return $users;
5465
    }
5466
5467
    /**
5468
     * @param int $optionSelected
5469
     * @return string
5470
     */
5471
    public static function getUserSubscriptionTab($optionSelected = 1)
5472
    {
5473
        $allowAdmin = api_get_setting('allow_user_course_subscription_by_course_admin');
5474
        if (($allowAdmin === 'true' && api_is_allowed_to_edit()) ||
5475
            api_is_platform_admin()
5476
        ) {
5477
            $userPath = api_get_path(WEB_CODE_PATH).'user/';
5478
5479
            $headers = [
5480
                [
5481
                    'url' => $userPath.'user.php?'.api_get_cidreq().'&type='.STUDENT,
5482
                    'content' => get_lang('Students'),
5483
                ],
5484
                [
5485
                    'url' => $userPath.'user.php?'.api_get_cidreq().'&type='.COURSEMANAGER,
5486
                    'content' => get_lang('Teachers'),
5487
                ],
5488
                /*[
5489
                    'url' => $userPath.'subscribe_user.php?'.api_get_cidreq(),
5490
                    'content' => get_lang('Students'),
5491
                ],
5492
                [
5493
                    'url' => $userPath.'subscribe_user.php?type=teacher&'.api_get_cidreq(),
5494
                    'content' => get_lang('Teachers'),
5495
                ],*/
5496
                [
5497
                    'url' => api_get_path(WEB_CODE_PATH).'group/group.php?'.api_get_cidreq(),
5498
                    'content' => get_lang('Groups'),
5499
                ],
5500
                [
5501
                    'url' => $userPath.'class.php?'.api_get_cidreq(),
5502
                    'content' => get_lang('Classes'),
5503
                ]
5504
            ];
5505
5506
            return Display::tabsOnlyLink($headers, $optionSelected);
5507
        }
5508
    }
5509
}
5510