Completed
Push — master ( 5f1c93...626f54 )
by Julito
31:28
created

UserManager::is_user_certified()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 15
Code Lines 11

Duplication

Lines 15
Ratio 100 %

Importance

Changes 0
Metric Value
cc 3
eloc 11
nc 2
nop 2
dl 15
loc 15
rs 9.4285
c 0
b 0
f 0
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 Chamilo\CoreBundle\Framework\Container;
7
use Chamilo\CoreBundle\Entity\AccessUrlRelUser;
8
use Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder;
9
use Symfony\Component\Security\Core\Encoder\EncoderFactory;
10
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
11
use Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder;
12
13
/**
14
 *
15
 * Class UserManager
16
 *
17
 * This library provides functions for user management.
18
 * Include/require it in your code to use its functionality.
19
 * @package chamilo.library
20
 * @author Julio Montoya <[email protected]> Social network groups added 2009/12
21
 *
22
 */
23
class UserManager
24
{
25
    // This constants are deprecated use the constants located in ExtraField
26
    const USER_FIELD_TYPE_TEXT = 1;
27
    const USER_FIELD_TYPE_TEXTAREA = 2;
28
    const USER_FIELD_TYPE_RADIO = 3;
29
    const USER_FIELD_TYPE_SELECT = 4;
30
    const USER_FIELD_TYPE_SELECT_MULTIPLE = 5;
31
    const USER_FIELD_TYPE_DATE = 6;
32
    const USER_FIELD_TYPE_DATETIME = 7;
33
    const USER_FIELD_TYPE_DOUBLE_SELECT = 8;
34
    const USER_FIELD_TYPE_DIVIDER = 9;
35
    const USER_FIELD_TYPE_TAG = 10;
36
    const USER_FIELD_TYPE_TIMEZONE = 11;
37
    const USER_FIELD_TYPE_SOCIAL_PROFILE = 12;
38
    const USER_FIELD_TYPE_FILE = 13;
39
    const USER_FIELD_TYPE_MOBILE_PHONE_NUMBER  = 14;
40
41
    private static $encryptionMethod;
42
43
    /**
44
     * Constructor
45
     * @assert () === null
46
     */
47
    public function __construct()
48
    {
49
    }
50
51
    /**
52
     * Repository is use to query the DB, selects, etc
53
     * @return Chamilo\UserBundle\Entity\Repository\UserRepository
54
     */
55
    public static function getRepository()
56
    {
57
        return Database::getManager()->getRepository('ChamiloUserBundle:User');
58
    }
59
60
    /**
61
     * Create/update/delete methods are available in the UserManager
62
     * (based in the Sonata\UserBundle\Entity\UserManager)
63
     *
64
     * @return Chamilo\UserBundle\Entity\Manager\UserManager
65
     */
66
    public static function getManager()
67
    {
68
        return Container::getUserManager();
69
    }
70
71
    /**
72
     * @param string $encryptionMethod
73
     */
74
    public static function setPasswordEncryption($encryptionMethod)
75
    {
76
        self::$encryptionMethod = $encryptionMethod;
77
    }
78
79
    /**
80
     * @return bool|mixed
81
     */
82
    public static function getPasswordEncryption()
83
    {
84
        $encryptionMethod = self::$encryptionMethod;
85
        if (empty($encryptionMethod)) {
86
            $encryptionMethod = api_get_configuration_value('password_encryption');
87
        }
88
89
        return $encryptionMethod;
90
    }
91
92
    /**
93
     * @return EncoderFactory
94
     */
95
    private static function getEncoderFactory()
96
    {
97
        $encryption = self::getPasswordEncryption();
98
        $encoders = array(
99
            'Chamilo\\UserBundle\\Entity\\User' => new \Chamilo\UserBundle\Security\Encoder($encryption)
100
        );
101
102
        $encoderFactory = new EncoderFactory($encoders);
103
104
        return $encoderFactory;
105
    }
106
107
    /**
108
     * @param User $user
109
     *
110
     * @return \Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface
111
     */
112
    private static function getEncoder(User $user)
113
    {
114
        $encoderFactory = self::getEncoderFactory();
115
116
        return $encoderFactory->getEncoder($user);
117
    }
118
119
    /**
120
     * Validates the password
121
     *
122
     * @param $encoded
123
     * @param $raw
124
     * @param $salt
125
     * @return bool
126
     */
127
    public static function isPasswordValid($encoded, $raw, $salt)
128
    {
129
        $encoder = new \Chamilo\UserBundle\Security\Encoder(self::getPasswordEncryption());
130
        $validPassword = $encoder->isPasswordValid($encoded, $raw, $salt);
131
132
        return $validPassword;
133
    }
134
135
    /**
136
     * @param string $raw
137
     * @param User   $user
138
     *
139
     * @return bool
140
     */
141
    public static function encryptPassword($raw, User $user)
142
    {
143
        $encoder = self::getEncoder($user);
144
145
        $encodedPassword = $encoder->encodePassword(
146
            $raw,
147
            $user->getSalt()
148
        );
149
150
        return $encodedPassword;
151
    }
152
153
    /**
154
     * @param int $userId
155
     * @param string $password
156
     *
157
     */
158
    public static function updatePassword($userId, $password)
159
    {
160
        $repository = self::getRepository();
161
        /** @var User $user */
162
        $user = $repository->find($userId);
163
        $userManager = self::getManager();
164
        $user->setPlainPassword($password);
165
        $userManager->updateUser($user, true);
166
    }
167
168
    /**
169
     * Creates a new user for the platform
170
     * @author Hugues Peeters <[email protected]>,
171
     * @author Roan Embrechts <[email protected]>
172
     * @param  string $firstName
173
     * @param  string $lastName
174
     * @param  int    $status (1 for course tutor, 5 for student, 6 for anonymous)
175
     * @param  string $email
176
     * @param  string $loginName
177
     * @param  string $password
178
     * @param  string $official_code Any official code (optional)
179
     * @param  string $language User language    (optional)
180
     * @param  string $phone Phone number    (optional)
181
     * @param  string $picture_uri Picture URI        (optional)
182
     * @param  string $authSource Authentication source    (optional, defaults to 'platform', dependind on constant)
183
     * @param  string $expirationDate Account expiration date (optional, defaults to null)
184
     * @param  int    $active Whether the account is enabled or disabled by default
185
     * @param  int    $hr_dept_id The department of HR in which the user is registered (optional, defaults to 0)
186
     * @param  array  $extra    Extra fields
187
     * @param  string $encrypt_method Encrypt method used if password is given encrypted. Set to an empty string by default
188
     * @param  bool $send_mail
189
     * @param  bool $isAdmin
190
     * @param  string $address
191
     * @param  bool $sendEmailToAllAdmins
192
     * @param FormValidator $form
193
     *
194
     * @return mixed   new user id - if the new user creation succeeds, false otherwise
195
     * @desc The function tries to retrieve user id from the session.
196
     * If it exists, the current user id is the creator id. If a problem arises,
197
     * @assert ('Sam','Gamegie',5,'[email protected]','jo','jo') > 1
198
     * @assert ('Pippin','Took',null,null,'jo','jo') === false
199
     */
200
    public static function create_user(
201
        $firstName,
202
        $lastName,
203
        $status,
204
        $email,
205
        $loginName,
206
        $password,
207
        $official_code = '',
208
        $language = '',
209
        $phone = '',
210
        $picture_uri = '',
211
        $authSource = PLATFORM_AUTH_SOURCE,
212
        $expirationDate = null,
213
        $active = 1,
214
        $hr_dept_id = 0,
215
        $extra = [],
216
        $encrypt_method = '',
217
        $send_mail = false,
218
        $isAdmin = false,
219
        $address = '',
220
        $sendEmailToAllAdmins = false,
221
        $form = null
222
    ) {
223
        $currentUserId = api_get_user_id();
224
        $hook = HookCreateUser::create();
225
        if (!empty($hook)) {
226
            $hook->notifyCreateUser(HOOK_EVENT_TYPE_PRE);
227
        }
228
229
        // First check wether the login already exists
230
        if (!self::is_username_available($loginName)) {
231
            Display::addFlash(
232
                Display::return_message(get_lang('LoginAlreadyTaken'))
233
            );
234
235
            return false;
236
        }
237
238
        global $_configuration;
239
        $original_password = $password;
240
241
        $access_url_id = 1;
242
        if (api_get_multiple_access_url()) {
243
            $access_url_id = api_get_current_access_url_id();
244
        }
245
246 View Code Duplication
        if (isset($_configuration[$access_url_id]) &&
247
            is_array($_configuration[$access_url_id]) &&
248
            isset($_configuration[$access_url_id]['hosting_limit_users']) &&
249
            $_configuration[$access_url_id]['hosting_limit_users'] > 0) {
250
            $num = self::get_number_of_users();
251
            if ($num >= $_configuration[$access_url_id]['hosting_limit_users']) {
252
                api_warn_hosting_contact('hosting_limit_users');
253
                Display::addFlash(Display::return_message(get_lang('PortalUsersLimitReached'), 'warning'));
254
255
                return false;
256
            }
257
        }
258
259 View Code Duplication
        if ($status === 1 &&
260
            isset($_configuration[$access_url_id]) &&
261
            is_array($_configuration[$access_url_id]) &&
262
            isset($_configuration[$access_url_id]['hosting_limit_teachers']) &&
263
            $_configuration[$access_url_id]['hosting_limit_teachers'] > 0
264
        ) {
265
            $num = self::get_number_of_users(1);
266
            if ($num >= $_configuration[$access_url_id]['hosting_limit_teachers']) {
267
                Display::addFlash(Display::return_message(get_lang('PortalTeachersLimitReached'), 'warning'));
268
                api_warn_hosting_contact('hosting_limit_teachers');
269
270
                return false;
271
            }
272
        }
273
274 View Code Duplication
        if (empty($password)) {
275
            if ($authSource === PLATFORM_AUTH_SOURCE) {
276
                Display::addFlash(
277
                    Display::return_message(
278
                        get_lang('ThisFieldIsRequired').': '.get_lang(
279
                            'Password'
280
                        ),
281
                        'warning'
282
                    )
283
                );
284
285
                return false;
286
            }
287
288
            // We use the authSource as password.
289
            // The real validation will be by processed by the auth
290
            // source not Chamilo
291
            //$password = $authSource;
292
        }
293
294
        // database table definition
295
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
296
297
        // Checking the user language
298
        $languages = api_get_languages();
299
        $language = strtolower($language);
300
301 View Code Duplication
        if (isset($languages['folder'])) {
302
            if (!in_array($language, $languages['folder'])) {
303
                $language = api_get_setting('platformLanguage');
304
            }
305
        }
306
307
        if (!empty($currentUserId)) {
308
            $creator_id = $currentUserId;
309
        } else {
310
            $creator_id = 0;
311
        }
312
313
        $currentDate = api_get_utc_datetime();
314
        $now = new DateTime();
315
316
        if (empty($expirationDate) || $expirationDate == '0000-00-00 00:00:00') {
317
            // Default expiration date
318
            // if there is a default duration of a valid account then
319
            // we have to change the expiration_date accordingly
320
            // Accept 0000-00-00 00:00:00 as a null value to avoid issues with
321
            // third party code using this method with the previous (pre-1.10)
322
            // value of 0000...
323
            if (api_get_setting('account_valid_duration') != '') {
324
                $expirationDate = new DateTime($currentDate);
325
                $days = intval(api_get_setting('account_valid_duration'));
326
                $expirationDate->modify('+'.$days.' day');
327
            }
328
        } else {
329
            $expirationDate = api_get_utc_datetime($expirationDate);
330
            $expirationDate = new \DateTime($expirationDate, new DateTimeZone('UTC'));
331
        }
332
333
        $em = Database::getManager();
334
        $userManager = self::getManager();
335
336
        /** @var User $user */
337
        $user = $userManager->createUser();
338
339
        $user
340
            ->setLastname($lastName)
341
            ->setFirstname($firstName)
342
            ->setUsername($loginName)
343
            ->setStatus($status)
344
            ->setPlainPassword($password)
345
            ->setEmail($email)
346
            ->setOfficialCode($official_code)
347
            ->setPictureUri($picture_uri)
348
            ->setCreatorId($creator_id)
349
            ->setAuthSource($authSource)
350
            ->setPhone($phone)
351
            ->setAddress($address)
352
            ->setLanguage($language)
353
            ->setRegistrationDate($now)
354
            ->setHrDeptId($hr_dept_id)
355
            ->setActive($active)
356
            ->setEnabled($active)
357
        ;
358
359
        if (!empty($expirationDate)) {
360
            $user->setExpirationDate($expirationDate);
0 ignored issues
show
Bug introduced by
It seems like $expirationDate defined by parameter $expirationDate on line 212 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...
361
        }
362
363
        $url = $em->getRepository('ChamiloCoreBundle:AccessUrl')->find(api_get_current_access_url_id());
364
365
        $accessRelUser = new AccessUrlRelUser();
366
        $accessRelUser->setUser($user);
367
        $accessRelUser->setPortal($url);
368
        $user->setPortal($accessRelUser);
369
370
        // Default group is student
371
        $group = 'student';
372
373
        switch ($status) {
374
            case STUDENT:
375
                $group = 'student';
376
                break;
377
            case COURSEMANAGER:
378
                $group = 'teacher';
379
                break;
380
            case DRH:
381
                $group = 'drh';
382
                break;
383
            case SESSIONADMIN:
384
                $group = 'session_manager';
385
                break;
386
            /*case QUESTION:
387
                $group = 'question_manager';
388
                break;*/
389
            case STUDENT_BOSS:
390
                $group = 'student_boss';
391
                break;
392
            case INVITEE:
393
                $group = 'invitee';
394
                break;
395
        }
396
397
        if ($isAdmin) {
398
            $group = 'admin';
399
        }
400
401
        $criteria = ['code' => $group];
402
        $group = $em->getRepository('ChamiloUserBundle:Group')->findOneBy($criteria);
403
        $user->setGroups(array($group));
404
405
        $userManager->updateUser($user, true);
406
        $userId = $user->getId();
407
408
        if (!empty($userId)) {
409
            $sql = "UPDATE $table_user SET user_id = $userId WHERE id = $userId";
410
            Database::query($sql);
411
412
            if ($isAdmin) {
413
                UserManager::add_user_as_admin($user);
414
            }
415
416
            if (is_array($extra) && count($extra) > 0) {
417
                foreach ($extra as $fname => $fvalue) {
418
                    self::update_extra_field_value($userId, $fname, $fvalue);
419
                }
420
            } else {
421
                // Create notify settings by default
422
                self::update_extra_field_value($userId, 'mail_notify_invitation', '1');
423
                self::update_extra_field_value($userId, 'mail_notify_message', '1');
424
                self::update_extra_field_value($userId, 'mail_notify_group_message', '1');
425
            }
426
427
            self::update_extra_field_value($userId, 'already_logged_in', 'false');
428
429
            if (!empty($email) && $send_mail) {
430
                $recipient_name = api_get_person_name(
431
                    $firstName,
432
                    $lastName,
433
                    null,
434
                    PERSON_NAME_EMAIL_ADDRESS
435
                );
436
                $tplSubject = new Template(null, false, false, false, false, false);
437
                $layoutSubject = $tplSubject->get_template(
438
                    'mail/subject_registration_platform.tpl'
439
                );
440
                $emailSubject = $tplSubject->fetch($layoutSubject);
441
                $sender_name = api_get_person_name(
442
                    api_get_setting('administratorName'),
443
                    api_get_setting('administratorSurname'),
444
                    null,
445
                    PERSON_NAME_EMAIL_ADDRESS
446
                );
447
                $email_admin = api_get_setting('emailAdministrator');
448
449
                if (api_is_multiple_url_enabled()) {
450
                    $access_url_id = api_get_current_access_url_id();
451
                    if ($access_url_id != -1) {
452
                        $url = api_get_access_url($access_url_id);
453
                    }
454
                } else {
455
                    $url = api_get_path(WEB_PATH);
456
                }
457
                $tplContent = new Template(null, false, false, false, false, false);
458
                // variables for the default template
459
                $tplContent->assign('complete_name', stripslashes(api_get_person_name($firstName, $lastName)));
460
                $tplContent->assign('login_name', $loginName);
461
                $tplContent->assign('original_password', stripslashes($original_password));
462
                $tplContent->assign('mailWebPath', $url);
463
                $tplContent->assign('new_user', $user);
464
465
                $layoutContent = $tplContent->get_template('mail/content_registration_platform.tpl');
466
                $emailBody = $tplContent->fetch($layoutContent);
467
                /* MANAGE EVENT WITH MAIL */
468
                if (EventsMail::check_if_using_class('user_registration')) {
469
                    $values["about_user"] = $userId;
470
                    $values["password"] = $original_password;
471
                    $values["send_to"] = array($userId);
472
                    $values["prior_lang"] = null;
473
                    EventsDispatcher::events('user_registration', $values);
474
                } else {
475
                    $phoneNumber = isset($extra['mobile_phone_number']) ? $extra['mobile_phone_number'] : null;
476
477
                    $additionalParameters = array(
478
                        'smsType' => SmsPlugin::WELCOME_LOGIN_PASSWORD,
479
                        'userId' => $userId,
480
                        'mobilePhoneNumber' => $phoneNumber,
481
                        'password' => $original_password
482
                    );
483
484
                    api_mail_html(
485
                        $recipient_name,
486
                        $email,
487
                        $emailSubject,
488
                        $emailBody,
489
                        $sender_name,
490
                        $email_admin,
491
                        null,
492
                        null,
493
                        null,
494
                        $additionalParameters
495
                    );
496
                }
497
498
                if ($sendEmailToAllAdmins) {
499
                    $adminList = UserManager::get_all_administrators();
500
501
                    $tplContent = new Template(null, false, false, false, false, false);
502
                    // variables for the default template
503
                    $tplContent->assign('complete_name', stripslashes(api_get_person_name($firstName, $lastName)));
504
                    $tplContent->assign('user_added', $user);
505
506
                    $renderer = FormValidator::getDefaultRenderer();
507
508
                    // Form template
509
                    $elementTemplate = ' {label}: {element} <br />';
510
                    $renderer->setElementTemplate($elementTemplate);
511
                    /** @var FormValidator $form */
512
                    $form->freeze(null, $elementTemplate);
513
                    $form->removeElement('submit');
514
                    $formData = $form->returnForm();
515
                    $url = api_get_path(WEB_CODE_PATH).'admin/user_information.php?user_id='.$user->getId();
516
                    $tplContent->assign('link', Display::url($url, $url));
517
                    $tplContent->assign('form', $formData);
518
519
                    $layoutContent = $tplContent->get_template('mail/content_registration_platform_to_admin.tpl');
520
                    $emailBody = $tplContent->fetch($layoutContent);
521
                    $subject = get_lang('UserAdded');
522
523
                    foreach ($adminList as $adminId => $data) {
524
                        MessageManager::send_message_simple($adminId, $subject, $emailBody);
525
                    }
526
527
                }
528
                /* ENDS MANAGE EVENT WITH MAIL */
529
            }
530
531
            if (!empty($hook)) {
532
                $hook->setEventData(array(
533
                    'return' => $userId,
534
                    'originalPassword' => $original_password
535
                ));
536
                $hook->notifyCreateUser(HOOK_EVENT_TYPE_POST);
537
            }
538
            Event::addEvent(LOG_USER_CREATE, LOG_USER_ID, $userId);
539
        } else {
540
            Display::addFlash(Display::return_message(get_lang('ErrorContactPlatformAdmin')));
541
542
            return false;
543
        }
544
545
        return $userId;
546
    }
547
548
    /**
549
     * Can user be deleted? This function checks whether there's a course
550
     * in which the given user is the
551
     * only course administrator. If that is the case, the user can't be
552
     * deleted because the course would remain without a course admin.
553
     * @param int $user_id The user id
554
     * @return boolean true if user can be deleted
555
     * @assert (null) === false
556
     * @assert (-1) === false
557
     * @assert ('abc') === false
558
     */
559
    public static function can_delete_user($user_id)
560
    {
561
        $deny = api_get_configuration_value('deny_delete_users');
562
563
        if ($deny) {
564
            return false;
565
        }
566
567
        $table_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
568
        if ($user_id != strval(intval($user_id))) {
569
            return false;
570
        }
571
        if ($user_id === false) {
572
            return false;
573
        }
574
        $sql = "SELECT * FROM $table_course_user
575
                WHERE status = 1 AND user_id = ".$user_id;
576
        $res = Database::query($sql);
577
        while ($course = Database::fetch_object($res)) {
578
            $sql = "SELECT id FROM $table_course_user
579
                    WHERE status=1 AND c_id = " . intval($course->c_id);
580
            $res2 = Database::query($sql);
581
            if (Database::num_rows($res2) == 1) {
582
583
                return false;
584
            }
585
        }
586
587
        return true;
588
    }
589
590
    /**
591
     * Delete a user from the platform, and all its belongings. This is a
592
     * very dangerous function that should only be accessible by
593
     * super-admins. Other roles should only be able to disable a user,
594
     * which removes access to the platform but doesn't delete anything.
595
     * @param int The ID of th user to be deleted
596
     * @return boolean true if user is successfully deleted, false otherwise
597
     * @assert (null) === false
598
     * @assert ('abc') === false
599
     */
600
    public static function delete_user($user_id)
601
    {
602
        if ($user_id != strval(intval($user_id))) {
603
            return false;
604
        }
605
606
        if ($user_id === false) {
607
            return false;
608
        }
609
610
        if (!self::can_delete_user($user_id)) {
611
            return false;
612
        }
613
614
        $user = self::getManager()->find($user_id);
615
616
        if (empty($user)) {
617
            return false;
618
        }
619
620
        $usergroup_rel_user = Database :: get_main_table(TABLE_USERGROUP_REL_USER);
621
        $table_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
622
        $table_course = Database :: get_main_table(TABLE_MAIN_COURSE);
623
        $table_session = Database :: get_main_table(TABLE_MAIN_SESSION);
624
        $table_admin = Database :: get_main_table(TABLE_MAIN_ADMIN);
625
        $table_session_user = Database :: get_main_table(TABLE_MAIN_SESSION_USER);
626
        $table_session_course_user = Database :: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
627
        $table_group = Database :: get_course_table(TABLE_GROUP_USER);
628
        $table_work = Database :: get_course_table(TABLE_STUDENT_PUBLICATION);
629
630
        // Unsubscribe the user from all groups in all his courses
631
        $sql = "SELECT c.id FROM $table_course c, $table_course_user cu
632
                WHERE
633
                    cu.user_id = '".$user_id."' AND
634
                    relation_type<>".COURSE_RELATION_TYPE_RRHH." AND
635
                    c.id = cu.c_id";
636
637
        $res = Database::query($sql);
638
        while ($course = Database::fetch_object($res)) {
639
            $sql = "DELETE FROM $table_group
640
                    WHERE c_id = {$course->id} AND user_id = $user_id";
641
            Database::query($sql);
642
        }
643
644
        // Unsubscribe user from usergroup_rel_user
645
        $sql = "DELETE FROM $usergroup_rel_user WHERE user_id = '".$user_id."'";
646
        Database::query($sql);
647
648
        // Unsubscribe user from all courses
649
        $sql = "DELETE FROM $table_course_user WHERE user_id = '".$user_id."'";
650
        Database::query($sql);
651
652
        // Unsubscribe user from all courses in sessions
653
        $sql = "DELETE FROM $table_session_course_user WHERE user_id = '".$user_id."'";
654
        Database::query($sql);
655
656
        // If the user was added as a id_coach then set the current admin as coach see BT#
657
        $currentUserId = api_get_user_id();
658
        $sql = "UPDATE $table_session SET id_coach = $currentUserId
659
                WHERE id_coach = '".$user_id."'";
660
        Database::query($sql);
661
662
        $sql = "UPDATE $table_session SET id_coach = $currentUserId
663
                WHERE session_admin_id = '".$user_id."'";
664
        Database::query($sql);
665
666
        // Unsubscribe user from all sessions
667
        $sql = "DELETE FROM $table_session_user
668
                WHERE user_id = '".$user_id."'";
669
        Database::query($sql);
670
671
        // Delete user picture
672
        /* TODO: Logic about api_get_setting('split_users_upload_directory') == 'true'
673
        a user has 4 different sized photos to be deleted. */
674
        $user_info = api_get_user_info($user_id);
675
676
        if (strlen($user_info['picture_uri']) > 0) {
677
            $path = self::getUserPathById($user_id, 'system');
678
            $img_path = $path.$user_info['picture_uri'];
679
            if (file_exists($img_path)) {
680
                unlink($img_path);
681
            }
682
        }
683
684
        // Delete the personal course categories
685
        $course_cat_table = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
686
        $sql = "DELETE FROM $course_cat_table WHERE user_id = '".$user_id."'";
687
        Database::query($sql);
688
689
        // Delete user from the admin table
690
        $sql = "DELETE FROM $table_admin WHERE user_id = '".$user_id."'";
691
        Database::query($sql);
692
693
        // Delete the personal agenda-items from this user
694
        $agenda_table = Database :: get_main_table(TABLE_PERSONAL_AGENDA);
695
        $sql = "DELETE FROM $agenda_table WHERE user = '".$user_id."'";
696
        Database::query($sql);
697
698
        $gradebook_results_table = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_RESULT);
699
        $sql = 'DELETE FROM '.$gradebook_results_table.' WHERE user_id = '.$user_id;
700
        Database::query($sql);
701
702
        $extraFieldValue = new ExtraFieldValue('user');
703
        $extraFieldValue->deleteValuesByItem($user_id);
704
705
        UrlManager::deleteUserFromAllUrls($user_id);
706
707
        if (api_get_setting('allow_social_tool') == 'true') {
708
            $userGroup = new UserGroup();
709
            //Delete user from portal groups
710
            $group_list = $userGroup->get_groups_by_user($user_id);
711
            if (!empty($group_list)) {
712
                foreach ($group_list as $group_id => $data) {
713
                    $userGroup->delete_user_rel_group($user_id, $group_id);
714
                }
715
            }
716
717
            // Delete user from friend lists
718
            SocialManager::remove_user_rel_user($user_id, true);
719
        }
720
721
        // Removing survey invitation
722
        SurveyManager::delete_all_survey_invitations_by_user($user_id);
723
724
        // Delete students works
725
        $sql = "DELETE FROM $table_work WHERE user_id = $user_id AND c_id <> 0";
726
        Database::query($sql);
727
728
        $sql = "UPDATE c_item_property SET to_user_id = NULL
729
                WHERE to_user_id = '".$user_id."'";
730
        Database::query($sql);
731
732
        $sql = "UPDATE c_item_property SET insert_user_id = NULL
733
                WHERE insert_user_id = '".$user_id."'";
734
        Database::query($sql);
735
736
        $sql = "UPDATE c_item_property SET lastedit_user_id = NULL
737
                WHERE lastedit_user_id = '".$user_id."'";
738
        Database::query($sql);
739
740
        // Skills
741
        $table = Database::get_main_table(TABLE_MAIN_SKILL_REL_USER);
742
        $sql = "DELETE FROM $table WHERE user_id = $user_id";
743
        Database::query($sql);
744
745
        // Delete user from database
746
        /*$sql = "DELETE FROM $table_user WHERE id = '".$user_id."'";
747
        Database::query($sql);*/
748
        self::getManager()->delete($user);
749
750
        // Add event to system log
751
        $user_id_manager = api_get_user_id();
752
753
        Event::addEvent(
754
            LOG_USER_DELETE,
755
            LOG_USER_ID,
756
            $user_id,
757
            api_get_utc_datetime(),
0 ignored issues
show
Bug introduced by
It seems like api_get_utc_datetime() can also be of type object<DateTime>; however, Event::addEvent() does only seem to accept string|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
758
            $user_id_manager
759
        );
760
761
        Event::addEvent(
762
            LOG_USER_DELETE,
763
            LOG_USER_OBJECT,
764
            $user_info,
765
            api_get_utc_datetime(),
0 ignored issues
show
Bug introduced by
It seems like api_get_utc_datetime() can also be of type object<DateTime>; however, Event::addEvent() does only seem to accept string|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
766
            $user_id_manager
767
        );
768
769
        return true;
770
    }
771
772
    /**
773
     * Deletes users completely. Can be called either as:
774
     * - UserManager :: delete_users(1, 2, 3); or
775
     * - UserManager :: delete_users(array(1, 2, 3));
776
     * @param array|int $ids
777
     * @return boolean  True if at least one user was successfuly deleted. False otherwise.
778
     * @author Laurent Opprecht
779
     * @uses UserManager::delete_user() to actually delete each user
780
     * @assert (null) === false
781
     * @assert (-1) === false
782
     * @assert (array(-1)) === false
783
     */
784
    public static function delete_users($ids = array())
785
    {
786
        $result = false;
787
        $ids = is_array($ids) ? $ids : func_get_args();
788
        if (!is_array($ids) || count($ids) == 0) {
789
            return false;
790
        }
791
        $ids = array_map('intval', $ids);
792
        foreach ($ids as $id) {
793
            if (empty($id) || $id < 1) {
794
                continue;
795
            }
796
            $deleted = self::delete_user($id);
797
            $result = $deleted || $result;
798
        }
799
800
        return $result;
801
    }
802
803
    /**
804
     * Disable users. Can be called either as:
805
     * - UserManager :: deactivate_users(1, 2, 3);
806
     * - UserManager :: deactivate_users(array(1, 2, 3));
807
     * @param array|int $ids
808
     * @return boolean
809
     * @author Laurent Opprecht
810
     * @assert (null) === false
811
     * @assert (array(-1)) === false
812
     */
813 View Code Duplication
    public static function deactivate_users($ids = array())
814
    {
815
        if (empty($ids)) {
816
817
            return false;
818
        }
819
820
        $table_user = Database :: get_main_table(TABLE_MAIN_USER);
821
822
        $ids = is_array($ids) ? $ids : func_get_args();
823
        $ids = array_map('intval', $ids);
824
        $ids = implode(',', $ids);
825
826
        $sql = "UPDATE $table_user SET active = 0 WHERE id IN ($ids)";
827
        $r = Database::query($sql);
828
        if ($r !== false) {
829
            Event::addEvent(LOG_USER_DISABLE, LOG_USER_ID, $ids);
830
        }
831
        return $r;
832
    }
833
834
    /**
835
     * Enable users. Can be called either as:
836
     * - UserManager :: activate_users(1, 2, 3);
837
     * - UserManager :: activate_users(array(1, 2, 3));
838
     * @param array|int IDs of the users to enable
839
     * @return boolean
840
     * @author Laurent Opprecht
841
     * @assert (null) === false
842
     * @assert (array(-1)) === false
843
     */
844 View Code Duplication
    public static function activate_users($ids = array())
845
    {
846
        if (empty($ids)) {
847
848
            return false;
849
        }
850
851
        $table_user = Database :: get_main_table(TABLE_MAIN_USER);
852
853
        $ids = is_array($ids) ? $ids : func_get_args();
854
        $ids = array_map('intval', $ids);
855
        $ids = implode(',', $ids);
856
857
        $sql = "UPDATE $table_user SET active = 1 WHERE id IN ($ids)";
858
        $r = Database::query($sql);
859
        if ($r !== false) {
860
            Event::addEvent(LOG_USER_ENABLE, LOG_USER_ID, $ids);
861
        }
862
        return $r;
863
    }
864
865
    /**
866
     * Update user information with new openid
867
     * @param int $user_id
868
     * @param string $openid
869
     * @return boolean true if the user information was updated
870
     * @assert (false,'') === false
871
     * @assert (-1,'') === false
872
     */
873
    public static function update_openid($user_id, $openid)
874
    {
875
        $table_user = Database:: get_main_table(TABLE_MAIN_USER);
876
        if ($user_id != strval(intval($user_id))) {
877
            return false;
878
        }
879
        if ($user_id === false) {
880
            return false;
881
        }
882
        $sql = "UPDATE $table_user SET
883
                openid='".Database::escape_string($openid)."'";
884
        $sql .= " WHERE id= $user_id";
885
886
        return Database::query($sql);
887
    }
888
889
    /**
890
     * Update user information with all the parameters passed to this function
891
     * @param int The ID of the user to be updated
892
     * @param string The user's firstname
893
     * @param string The user's lastname
894
     * @param string The user's username (login)
895
     * @param string The user's password
896
     * @param string The authentication source (default: "platform")
897
     * @param string The user's e-mail address
898
     * @param int The user's status
899
     * @param string The user's official code (usually just an internal institutional code)
900
     * @param string The user's phone number
901
     * @param string The user's picture URL (internal to the Chamilo directory)
902
     * @param int The user ID of the person who registered this user (optional, defaults to null)
903
     * @param int The department of HR in which the user is registered (optional, defaults to 0)
904
     * @param array A series of additional fields to add to this user as extra fields (optional, defaults to null)
905
     * @return boolean|integer False on error, or the user ID if the user information was updated
906
     * @assert (false, false, false, false, false, false, false, false, false, false, false, false, false) === false
907
     */
908
    public static function update_user(
909
        $user_id,
910
        $firstname,
911
        $lastname,
912
        $username,
913
        $password = null,
914
        $auth_source = null,
915
        $email,
916
        $status,
917
        $official_code,
918
        $phone,
919
        $picture_uri,
920
        $expiration_date,
921
        $active,
922
        $creator_id = null,
923
        $hr_dept_id = 0,
924
        $extra = null,
925
        $language = 'english',
926
        $encrypt_method = '',
927
        $send_email = false,
928
        $reset_password = 0,
929
        $address = null
930
    ) {
931
        $hook = HookUpdateUser::create();
932
        if (!empty($hook)) {
933
            $hook->notifyUpdateUser(HOOK_EVENT_TYPE_PRE);
934
        }
935
        $original_password = $password;
936
937
        if ($user_id != strval(intval($user_id))) {
938
            return false;
939
        }
940
941
        if (empty($user_id)) {
942
            return false;
943
        }
944
945
        $userManager = self::getManager();
946
        /** @var Chamilo\UserBundle\Entity\User $user */
947
        $user = self::getRepository()->find($user_id);
948
949
        if (empty($user)) {
950
            return false;
951
        }
952
953
        if ($reset_password == 0) {
954
            $password = null;
955
            $auth_source = $user->getAuthSource();
956
        } elseif ($reset_password == 1) {
957
            $original_password = $password = api_generate_password();
958
            $auth_source = PLATFORM_AUTH_SOURCE;
959
        } elseif ($reset_password == 2) {
960
            $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...
961
            $auth_source = PLATFORM_AUTH_SOURCE;
962
        } elseif ($reset_password == 3) {
963
            $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...
964
            $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...
965
        }
966
967
        // Checking the user language
968
        $languages = api_get_platform_isocodes();
969
        if (!in_array($language, $languages)) {
970
            $language = api_get_setting('platformLanguage');
971
        }
972
973
        $change_active = 0;
974
        $isUserActive = $user->getActive();
975
        if ($isUserActive != $active) {
976
            $change_active = 1;
977
        }
978
979
        $originalUsername = $user->getUsername();
980
981
        // If username is different from original then check if it exists.
982
        if ($originalUsername !== $username) {
983
            $available = self::is_username_available($username);
984
            if ($available === false) {
985
                return false;
986
            }
987
        }
988
989
        if (!empty($expiration_date)) {
990
            $expiration_date = api_get_utc_datetime($expiration_date);
991
            $expiration_date = new \DateTime(
992
                $expiration_date,
993
                new DateTimeZone('UTC')
994
            );
995
        }
996
997
        $user
998
            ->setLastname($lastname)
999
            ->setFirstname($firstname)
1000
            ->setUsername($username)
1001
            ->setStatus($status)
1002
            ->setAuthSource($auth_source)
1003
            ->setLanguage($language)
1004
            ->setEmail($email)
1005
            ->setOfficialCode($official_code)
1006
            ->setPhone($phone)
1007
            ->setAddress($address)
1008
            ->setPictureUri($picture_uri)
1009
            ->setExpirationDate($expiration_date)
1010
            ->setActive($active)
1011
            ->setEnabled($active)
1012
            ->setHrDeptId($hr_dept_id)
1013
        ;
1014
1015
        if (!is_null($password)) {
1016
            $user->setPlainPassword($password);
1017
        }
1018
1019
        $userManager->updateUser($user, true);
1020
1021
        if ($change_active == 1) {
1022
            if ($active == 1) {
1023
                $event_title = LOG_USER_ENABLE;
1024
            } else {
1025
                $event_title = LOG_USER_DISABLE;
1026
            }
1027
            Event::addEvent($event_title, LOG_USER_ID, $user_id);
1028
        }
1029
1030
        if (is_array($extra) && count($extra) > 0) {
1031
            $res = true;
1032
            foreach ($extra as $fname => $fvalue) {
1033
                $res = $res && self::update_extra_field_value(
1034
                    $user_id,
1035
                    $fname,
1036
                    $fvalue
1037
                );
1038
            }
1039
        }
1040
1041
        if (!empty($email) && $send_email) {
1042
            $recipient_name = api_get_person_name($firstname, $lastname, null, PERSON_NAME_EMAIL_ADDRESS);
1043
            $emailsubject = '['.api_get_setting('siteName').'] '.get_lang('YourReg').' '.api_get_setting('siteName');
1044
            $sender_name = api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'), null, PERSON_NAME_EMAIL_ADDRESS);
1045
            $email_admin = api_get_setting('emailAdministrator');
1046
1047
            if (api_is_multiple_url_enabled()) {
1048
                $access_url_id = api_get_current_access_url_id();
1049
                if ($access_url_id != -1) {
1050
                    $url = api_get_access_url($access_url_id);
1051
                    $emailbody = get_lang('Dear')." ".stripslashes(api_get_person_name($firstname, $lastname)).",\n\n".
1052
                        get_lang('YouAreReg')." ".api_get_setting('siteName')." ".get_lang('WithTheFollowingSettings')."\n\n".
1053
                        get_lang('Username')." : ".$username.(($reset_password > 0) ? "\n".
1054
                        get_lang('Pass')." : ".stripslashes($original_password) : "")."\n\n".
1055
                        get_lang('Address')." ".api_get_setting('siteName')." ".get_lang('Is')." : ".$url['url']."\n\n".
1056
                        get_lang('Problem')."\n\n".
1057
                        get_lang('SignatureFormula').",\n\n".
1058
                        api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'))."\n".
1059
                        get_lang('Manager')." ".api_get_setting('siteName')."\nT. ".api_get_setting('administratorTelephone')."\n".
1060
                        get_lang('Email')." : ".api_get_setting('emailAdministrator');
1061
                }
1062
            } else {
1063
                $emailbody = get_lang('Dear')." ".stripslashes(api_get_person_name($firstname, $lastname)).",\n\n".
1064
                    get_lang('YouAreReg')." ".api_get_setting('siteName')." ".get_lang('WithTheFollowingSettings')."\n\n".
1065
                    get_lang('Username')." : ".$username.(($reset_password > 0) ? "\n".
1066
                    get_lang('Pass')." : ".stripslashes($original_password) : "")."\n\n".
1067
                    get_lang('Address')." ".api_get_setting('siteName')." ".get_lang('Is')." : ".api_get_path(WEB_PATH)."\n\n".
1068
                    get_lang('Problem')."\n\n".
1069
                    get_lang('SignatureFormula').",\n\n".
1070
                    api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'))."\n".
1071
                    get_lang('Manager')." ".api_get_setting('siteName')."\nT. ".api_get_setting('administratorTelephone')."\n".
1072
                    get_lang('Email')." : ".api_get_setting('emailAdministrator');
1073
            }
1074
1075
            $emailbody = nl2br($emailbody);
1076
            api_mail_html(
1077
                $recipient_name,
1078
                $email,
1079
                $emailsubject,
1080
                $emailbody,
1081
                $sender_name,
1082
                $email_admin
1083
            );
1084
        }
1085
1086
        if (!empty($hook)) {
1087
            $hook->notifyUpdateUser(HOOK_EVENT_TYPE_POST);
1088
        }
1089
1090
        return $user->getId();
1091
    }
1092
1093
    /**
1094
     * Disables or enables a user
1095
     * @param int $user_id
1096
     * @param int $active Enable or disable
1097
     * @return void
1098
     * @assert (-1,0) === false
1099
     * @assert (1,1) === true
1100
     */
1101
    private static function change_active_state($user_id, $active)
1102
    {
1103
        if (strval(intval($user_id)) != $user_id) {
1104
            return false;
1105
        }
1106
        if ($user_id < 1) {
1107
            return false;
1108
        }
1109
        $user_id = intval($user_id);
1110
        $table_user = Database :: get_main_table(TABLE_MAIN_USER);
1111
        $sql = "UPDATE $table_user SET active = '$active' WHERE id = $user_id";
1112
        $r = Database::query($sql);
1113
        $ev = LOG_USER_DISABLE;
1114
        if ($active == 1) {
1115
            $ev = LOG_USER_ENABLE;
1116
        }
1117
        if ($r !== false) {
1118
            Event::addEvent($ev, LOG_USER_ID, $user_id);
1119
        }
1120
1121
        return $r;
1122
    }
1123
1124
    /**
1125
     * Disables a user
1126
     * @param int User id
1127
     * @return bool
1128
     * @uses UserManager::change_active_state() to actually disable the user
1129
     * @assert (0) === false
1130
     */
1131
    public static function disable($user_id)
1132
    {
1133
        if (empty($user_id)) {
1134
            return false;
1135
        }
1136
        self::change_active_state($user_id, 0);
1137
        return true;
1138
    }
1139
1140
    /**
1141
     * Enable a user
1142
     * @param int User id
1143
     * @return bool
1144
     * @uses UserManager::change_active_state() to actually disable the user
1145
     * @assert (0) === false
1146
     */
1147
    public static function enable($user_id)
1148
    {
1149
        if (empty($user_id)) {
1150
            return false;
1151
        }
1152
        self::change_active_state($user_id, 1);
1153
        return true;
1154
    }
1155
1156
    /**
1157
     * Returns the user's id based on the original id and field name in
1158
     * the extra fields. Returns 0 if no user was found. This function is
1159
     * mostly useful in the context of a web services-based sinchronization
1160
     * @param string Original user id
1161
     * @param string Original field name
1162
     * @return int User id
1163
     * @assert ('0','---') === 0
1164
     */
1165 View Code Duplication
    public static function get_user_id_from_original_id($original_user_id_value, $original_user_id_name)
1166
    {
1167
        $t_uf = Database::get_main_table(TABLE_EXTRA_FIELD);
1168
        $t_ufv = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
1169
        $extraFieldType = EntityExtraField::USER_FIELD_TYPE;
1170
        $sql = "SELECT item_id as user_id
1171
                FROM $t_uf uf
1172
                INNER JOIN $t_ufv ufv
1173
                ON ufv.field_id=uf.id
1174
                WHERE
1175
                    variable='$original_user_id_name' AND
1176
                    value='$original_user_id_value' AND
1177
                    extra_field_type = $extraFieldType
1178
                ";
1179
        $res = Database::query($sql);
1180
        $row = Database::fetch_object($res);
1181
        if ($row) {
1182
            return $row->user_id;
1183
        } else {
1184
            return 0;
1185
        }
1186
    }
1187
1188
    /**
1189
     * Check if a username is available
1190
     * @param string $username the wanted username
1191
     * @return boolean true if the wanted username is available
1192
     * @assert ('') === false
1193
     * @assert ('xyzxyzxyz') === true
1194
     */
1195 View Code Duplication
    public static function is_username_available($username)
1196
    {
1197
        if (empty($username)) {
1198
            return false;
1199
        }
1200
        $table_user = Database :: get_main_table(TABLE_MAIN_USER);
1201
        $sql = "SELECT username FROM $table_user
1202
                WHERE username = '".Database::escape_string($username)."'";
1203
        $res = Database::query($sql);
1204
1205
        return Database::num_rows($res) == 0;
1206
    }
1207
1208
    /**
1209
     * Creates a username using person's names, i.e. creates jmontoya from Julio Montoya.
1210
     * @param string $firstname The first name of the user.
1211
     * @param string $lastname The last name of the user.
1212
     * @return string Suggests a username that contains only ASCII-letters and digits,
1213
     * without check for uniqueness within the system.
1214
     * @author Julio Montoya Armas
1215
     * @author Ivan Tcholakov, 2009 - rework about internationalization.
1216
     * @assert ('','') === false
1217
     * @assert ('a','b') === 'ab'
1218
     */
1219
    public static function create_username($firstname, $lastname)
1220
    {
1221
        if (empty($firstname) && empty($lastname)) {
1222
1223
            return false;
1224
        }
1225
1226
        $firstname = api_substr(preg_replace(USERNAME_PURIFIER, '', $firstname), 0, 1); // The first letter only.
1227
        //Looking for a space in the lastname
1228
        $pos = api_strpos($lastname, ' ');
1229
        if ($pos !== false) {
1230
            $lastname = api_substr($lastname, 0, $pos);
1231
        }
1232
1233
        $lastname = preg_replace(USERNAME_PURIFIER, '', $lastname);
1234
        $username = $firstname.$lastname;
1235
        if (empty($username)) {
1236
            $username = 'user';
1237
        }
1238
1239
        $username = URLify::transliterate($username);
1240
1241
        return strtolower(substr($username, 0, USERNAME_MAX_LENGTH - 3));
1242
    }
1243
1244
    /**
1245
     * Creates a unique username, using:
1246
     * 1. the first name and the last name of a user;
1247
     * 2. an already created username but not checked for uniqueness yet.
1248
     * @param string $firstname                The first name of a given user. If the second parameter $lastname is NULL, then this
1249
     * parameter is treated as username which is to be checked for uniqueness and to be modified when it is necessary.
1250
     * @param string $lastname                The last name of the user.
1251
     * @return string                        Returns a username that contains only ASCII-letters and digits, and that is unique within the system.
1252
     * Note: When the method is called several times with same parameters, its results look like the following sequence: ivan, ivan2, ivan3, ivan4, ...
1253
     * @author Ivan Tcholakov, 2009
1254
     */
1255
    public static function create_unique_username($firstname, $lastname = null)
1256
    {
1257
        if (is_null($lastname)) {
1258
            // In this case the actual input parameter $firstname should contain ASCII-letters and digits only.
1259
            // For making this method tolerant of mistakes, let us transliterate and purify the suggested input username anyway.
1260
            // So, instead of the sentence $username = $firstname; we place the following:
1261
            $username = strtolower(preg_replace(USERNAME_PURIFIER, '', $firstname));
1262
        } else {
1263
            $username = self::create_username($firstname, $lastname);
1264
        }
1265
        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 1263 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...
1266
            $i = 2;
1267
            $temp_username = substr($username, 0, USERNAME_MAX_LENGTH - strlen((string) $i)).$i;
1268
            while (!self::is_username_available($temp_username)) {
1269
                $i++;
1270
                $temp_username = substr($username, 0, USERNAME_MAX_LENGTH - strlen((string) $i)).$i;
1271
            }
1272
            $username = $temp_username;
1273
        }
1274
1275
        $username = URLify::transliterate($username);
1276
1277
        return $username;
1278
    }
1279
1280
    /**
1281
     * Modifies a given username accordingly to the specification for valid characters and length.
1282
     * @param $username string          The input username.
1283
     * @param bool $strict (optional)   When this flag is TRUE, the result is guaranteed for full compliance,
1284
     * otherwise compliance may be partial. The default value is FALSE.
1285
     * @return string                   The resulting purified username.
1286
     */
1287
    public static function purify_username($username, $strict = false)
1288
    {
1289
        if ($strict) {
1290
            // 1. Conversion of unacceptable letters (latinian letters with accents for example)
1291
            // into ASCII letters in order they not to be totally removed.
1292
            // 2. Applying the strict purifier.
1293
            // 3. Length limitation.
1294
            $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);
1295
            $return = URLify::transliterate($return);
1296
1297
            return $return;
1298
        }
1299
1300
        // 1. Applying the shallow purifier.
1301
        // 2. Length limitation.
1302
        return substr(preg_replace(USERNAME_PURIFIER_SHALLOW, '', $username), 0, USERNAME_MAX_LENGTH);
1303
    }
1304
1305
    /**
1306
     * Checks whether the user id exists in the database
1307
     *
1308
     * @param int User id
1309
     * @return bool True if user id was found, false otherwise
1310
     */
1311 View Code Duplication
    public static function is_user_id_valid($userId)
1312
    {
1313
        $resultData = Database::select(
1314
            'COUNT(1) AS count',
1315
            Database::get_main_table(TABLE_MAIN_USER),
1316
            [
1317
                'where' => ['id = ?' => intval($userId)]
1318
            ],
1319
            'first'
1320
        );
1321
1322
        if ($resultData === false) {
1323
            return false;
1324
        }
1325
1326
        return $resultData['count'] > 0;
1327
    }
1328
1329
    /**
1330
     * Checks whether a given username matches to the specification strictly. The empty username is assumed here as invalid.
1331
     * Mostly this function is to be used in the user interface built-in validation routines for providing feedback while usernames are enterd manually.
1332
     * @param string $username The input username.
1333
     * @return bool Returns TRUE if the username is valid, FALSE otherwise.
1334
     */
1335
    public static function is_username_valid($username)
1336
    {
1337
        return !empty($username) && $username == self::purify_username($username, true);
1338
    }
1339
1340
    /**
1341
     * Checks whether a username is empty. If the username contains whitespace characters, such as spaces, tabulators, newlines, etc.,
1342
     * it is assumed as empty too. This function is safe for validation unpurified data (during importing).
1343
     * @param string $username The given username.
1344
     * @return bool  Returns TRUE if length of the username exceeds the limit, FALSE otherwise.
1345
     */
1346
    public static function is_username_empty($username)
1347
    {
1348
        return (strlen(self::purify_username($username, false)) == 0);
1349
    }
1350
1351
    /**
1352
     * Checks whether a username is too long or not.
1353
     * @param string $username The given username, it should contain only ASCII-letters and digits.
1354
     * @return bool Returns TRUE if length of the username exceeds the limit, FALSE otherwise.
1355
     */
1356
    public static function is_username_too_long($username)
1357
    {
1358
        return (strlen($username) > USERNAME_MAX_LENGTH);
1359
    }
1360
1361
    /**
1362
    * Get the users by ID
1363
    * @param array $ids student ids
1364
    * @param string $active
1365
    * @param string $order
1366
    * @param string $limit
1367
    * @return array $result student information
1368
    */
1369
    public static function get_user_list_by_ids($ids = array(), $active = null, $order = null, $limit = null)
1370
    {
1371
        if (empty($ids)) {
1372
1373
            return array();
1374
        }
1375
1376
        $ids = is_array($ids) ? $ids : array($ids);
1377
        $ids = array_map('intval', $ids);
1378
        $ids = implode(',', $ids);
1379
1380
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
1381
        $sql = "SELECT * FROM $tbl_user WHERE id IN ($ids)";
1382
        if (!is_null($active)) {
1383
            $sql .= ' AND active='.($active ? '1' : '0');
1384
        }
1385
1386
        if (!is_null($order)) {
1387
            $order = Database::escape_string($order);
1388
            $sql .= ' ORDER BY ' . $order;
1389
        }
1390
1391
        if (!is_null($limit)) {
1392
            $limit = Database::escape_string($limit);
1393
            $sql .= ' LIMIT ' . $limit;
1394
        }
1395
1396
        $rs = Database::query($sql);
1397
        $result = array();
1398
        while ($row = Database::fetch_array($rs)) {
1399
            $result[] = $row;
1400
        }
1401
1402
        return $result;
1403
    }
1404
1405
    /**
1406
     * Get a list of users of which the given conditions match with an = 'cond'
1407
     * @param array $conditions a list of condition (example : 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(
1414
        $conditions = array(),
1415
        $order_by = array(),
1416
        $limit_from = false,
1417
        $limit_to = false
1418
    ) {
1419
        $user_table = Database :: get_main_table(TABLE_MAIN_USER);
1420
        $return_array = array();
1421
        $sql_query = "SELECT * FROM $user_table";
1422
        if (count($conditions) > 0) {
1423
            $sql_query .= ' WHERE ';
1424
            foreach ($conditions as $field => $value) {
1425
                $field = Database::escape_string($field);
1426
                $value = Database::escape_string($value);
1427
                $sql_query .= "$field = '$value'";
1428
            }
1429
        }
1430 View Code Duplication
        if (count($order_by) > 0) {
1431
            $sql_query .= ' ORDER BY '.Database::escape_string(implode(',', $order_by), null, false);
1432
        }
1433
1434
        if (is_numeric($limit_from) && is_numeric($limit_from)) {
1435
            $limit_from = intval($limit_from);
1436
            $limit_to = intval($limit_to);
1437
            $sql_query .= " LIMIT $limit_from, $limit_to";
1438
        }
1439
        $sql_result = Database::query($sql_query);
1440 View Code Duplication
        while ($result = Database::fetch_array($sql_result)) {
1441
            $result['complete_name'] = api_get_person_name($result['firstname'], $result['lastname']);
1442
            $return_array[] = $result;
1443
        }
1444
        return $return_array;
1445
    }
1446
1447
    /**
1448
     * Get a list of users of which the given conditions match with a LIKE '%cond%'
1449
     * @param array $conditions a list of condition (exemple : status=>STUDENT)
1450
     * @param array $order_by a list of fields on which sort
1451
     * @return array An array with all users of the platform.
1452
     * @todo optional course code parameter, optional sorting parameters...
1453
     * @todo security filter order_by
1454
     */
1455
    public static function get_user_list_like(
1456
        $conditions = array(),
1457
        $order_by = array(),
1458
        $simple_like = false,
1459
        $condition = 'AND'
1460
    ) {
1461
        $user_table = Database :: get_main_table(TABLE_MAIN_USER);
1462
        $tblAccessUrlRelUser = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
1463
        $return_array = array();
1464
        $sql_query = "SELECT * FROM $user_table ";
1465
1466
        if (api_is_multiple_url_enabled()) {
1467
            $sql_query .= " INNER JOIN $tblAccessUrlRelUser auru ON auru.user_id = user.id ";
1468
        }
1469
1470
        if (count($conditions) > 0) {
1471
            $sql_query .= ' WHERE ';
1472
            $temp_conditions = array();
1473
            foreach ($conditions as $field => $value) {
1474
                $field = Database::escape_string($field);
1475
                $value = Database::escape_string($value);
1476 View Code Duplication
                if ($simple_like) {
1477
                    $temp_conditions[] = $field." LIKE '$value%'";
1478
                } else {
1479
                    $temp_conditions[] = $field.' LIKE \'%'.$value.'%\'';
1480
                }
1481
            }
1482
            if (!empty($temp_conditions)) {
1483
                $sql_query .= implode(' '.$condition.' ', $temp_conditions);
1484
            }
1485
1486
            if (api_is_multiple_url_enabled()) {
1487
                $sql_query .= ' AND auru.access_url_id = ' . api_get_current_access_url_id();
1488
            }
1489
        } else {
1490
            if (api_is_multiple_url_enabled()) {
1491
                $sql_query .= ' WHERE auru.access_url_id = ' . api_get_current_access_url_id();
1492
            }
1493
        }
1494 View Code Duplication
        if (count($order_by) > 0) {
1495
            $sql_query .= ' ORDER BY '.Database::escape_string(implode(',', $order_by), null, false);
1496
        }
1497
        $sql_result = Database::query($sql_query);
1498 View Code Duplication
        while ($result = Database::fetch_array($sql_result)) {
1499
1500
            $result['complete_name'] = api_get_person_name(
1501
                $result['firstname'],
1502
                $result['lastname']
1503
            );
1504
            $return_array[] = $result;
1505
        }
1506
1507
        return $return_array;
1508
    }
1509
1510
    /**
1511
     * Get user picture URL or path from user ID (returns an array).
1512
     * The return format is a complete path, enabling recovery of the directory
1513
     * with dirname() or the file with basename(). This also works for the
1514
     * functions dealing with the user's productions, as they are located in
1515
     * the same directory.
1516
     * @param   integer   $id User ID
1517
     * @param   string    $type Type of path to return (can be 'system', 'web')
1518
     * @param   array $userInfo user information to avoid query the DB
1519
     * returns the /main/img/unknown.jpg image set it at true
1520
     *
1521
     * @return    array     Array of 2 elements: 'dir' and 'file' which contain
1522
     * the dir and file as the name implies if image does not exist it will
1523
     * return the unknow image if anonymous parameter is true if not it returns an empty array
1524
     */
1525 View Code Duplication
    public static function get_user_picture_path_by_id($id, $type = 'web', $userInfo = [])
1526
    {
1527
        switch ($type) {
1528
            case 'system': // Base: absolute system path.
1529
                $base = api_get_path(SYS_CODE_PATH);
1530
                break;
1531
            case 'web': // Base: absolute web path.
1532
            default:
1533
                $base = api_get_path(WEB_CODE_PATH);
1534
                break;
1535
        }
1536
1537
        $anonymousPath = array(
1538
            'dir' => $base.'img/',
1539
            'file' => 'unknown.jpg',
1540
            'email' => ''
1541
        );
1542
1543
        if (empty($id) || empty($type)) {
1544
            return $anonymousPath;
1545
        }
1546
1547
        $id = intval($id);
1548
        if (empty($userInfo)) {
1549
            $user_table = Database:: get_main_table(TABLE_MAIN_USER);
1550
            $sql = "SELECT email, picture_uri FROM $user_table
1551
                    WHERE id=".$id;
1552
            $res = Database::query($sql);
1553
1554
            if (!Database::num_rows($res)) {
1555
                return $anonymousPath;
1556
            }
1557
            $user = Database::fetch_array($res);
1558
            if (empty($user['picture_uri'])) {
1559
                return $anonymousPath;
1560
            }
1561
        } else {
1562
            $user = $userInfo;
1563
        }
1564
1565
        $pictureFilename = trim($user['picture_uri']);
1566
1567
        $dir = self::getUserPathById($id, $type);
1568
1569
        return array(
1570
            'dir' => $dir,
1571
            'file' => $pictureFilename,
1572
            'email' => $user['email']
1573
        );
1574
    }
1575
1576
    /**
1577
     * *** READ BEFORE REVIEW THIS FUNCTION ***
1578
     * This function is a exact copy from get_user_picture_path_by_id() and it was create it to avoid
1579
     * a recursive calls for get_user_picture_path_by_id() in another functions when you update a user picture
1580
     * in same script, so you can find this function usage in update_user_picture() function.
1581
     *
1582
     * @param   integer   $id User ID
1583
     * @param   string    $type Type of path to return (can be 'system', 'web')
1584
     * @param   array $userInfo user information to avoid query the DB
1585
     * returns the /main/img/unknown.jpg image set it at true
1586
     *
1587
     * @return    array     Array of 2 elements: 'dir' and 'file' which contain
1588
     * the dir and file as the name implies if image does not exist it will
1589
     * return the unknow image if anonymous parameter is true if not it returns an empty array
1590
     */
1591 View Code Duplication
    public static function getUserPicturePathById($id, $type = 'web', $userInfo = [])
1592
    {
1593
        switch ($type) {
1594
            case 'system': // Base: absolute system path.
1595
                $base = api_get_path(SYS_CODE_PATH);
1596
                break;
1597
            case 'web': // Base: absolute web path.
1598
            default:
1599
                $base = api_get_path(WEB_CODE_PATH);
1600
                break;
1601
        }
1602
1603
        $anonymousPath = array(
1604
            'dir' => $base.'img/',
1605
            'file' => 'unknown.jpg',
1606
            'email' => ''
1607
        );
1608
1609
        if (empty($id) || empty($type)) {
1610
            return $anonymousPath;
1611
        }
1612
1613
        $id = intval($id);
1614
1615
        if (empty($userInfo)) {
1616
            $user_table = Database:: get_main_table(TABLE_MAIN_USER);
1617
            $sql = "SELECT email, picture_uri FROM $user_table WHERE id=$id";
1618
            $res = Database::query($sql);
1619
1620
            if (!Database::num_rows($res)) {
1621
                return $anonymousPath;
1622
            }
1623
            $user = Database::fetch_array($res);
1624
1625
            if (empty($user['picture_uri'])) {
1626
                return $anonymousPath;
1627
            }
1628
        } else {
1629
            $user = $userInfo;
1630
        }
1631
1632
        $pictureFilename = trim($user['picture_uri']);
1633
1634
        $dir = self::getUserPathById($id, $type);
1635
1636
        return array(
1637
            'dir' => $dir,
1638
            'file' => $pictureFilename,
1639
            'email' => $user['email']
1640
        );
1641
    }
1642
1643
    /**
1644
     * Get user path from user ID (returns an array).
1645
     * The return format is a complete path to a folder ending with "/"
1646
     * In case the first level of subdirectory of users/ does not exist, the
1647
     * function will attempt to create it. Probably not the right place to do it
1648
     * but at least it avoids headaches in many other places.
1649
     * @param   integer $id User ID
1650
     * @param   string  $type Type of path to return (can be 'system', 'web', 'last')
1651
     * @return  string  User folder path (i.e. /var/www/chamilo/app/upload/users/1/1/)
1652
     */
1653
    public static function getUserPathById($id, $type)
1654
    {
1655
        $id = intval($id);
1656
        if (!$id) {
1657
            return null;
1658
        }
1659
1660
        $userPath = "users/$id/";
1661
        if (api_get_setting('split_users_upload_directory') === 'true') {
1662
            $userPath = 'users/'.substr((string) $id, 0, 1).'/'.$id.'/';
1663
            // In exceptional cases, on some portals, the intermediate base user
1664
            // directory might not have been created. Make sure it is before
1665
            // going further.
1666
1667
            $rootPath = api_get_path(SYS_UPLOAD_PATH) . 'users/' . substr((string) $id, 0, 1);
1668
            if (!is_dir($rootPath)) {
1669
                $perm = api_get_permissions_for_new_directories();
1670
                try {
1671
                    mkdir($rootPath, $perm);
1672
                } catch (Exception $e) {
1673
                    error_log($e->getMessage());
1674
                }
1675
            }
1676
        }
1677
        switch ($type) {
1678
            case 'system': // Base: absolute system path.
1679
                $userPath = api_get_path(SYS_UPLOAD_PATH).$userPath;
1680
                break;
1681
            case 'web': // Base: absolute web path.
1682
                $userPath = api_get_path(WEB_UPLOAD_PATH).$userPath;
1683
                break;
1684
            case 'last': // Only the last part starting with users/
1685
                break;
1686
        }
1687
1688
        return $userPath;
1689
    }
1690
1691
    /**
1692
     * Gets the current user image
1693
     * @param string $user_id
1694
     * @param int $size it can be USER_IMAGE_SIZE_SMALL,
1695
     * USER_IMAGE_SIZE_MEDIUM, USER_IMAGE_SIZE_BIG or  USER_IMAGE_SIZE_ORIGINAL
1696
     * @param bool $addRandomId
1697
     * @param array $userInfo to avoid query the DB
1698
     *
1699
     * @return string
1700
     */
1701
    public static function getUserPicture(
1702
        $user_id,
1703
        $size = USER_IMAGE_SIZE_MEDIUM,
1704
        $addRandomId = true,
1705
        $userInfo = []
1706
    ) {
1707
        // Make sure userInfo is defined. Otherwise, define it!
1708
        if (empty($userInfo) || !is_array($userInfo) || count($userInfo) == 0) {
1709
            if (empty($user_id)) {
1710
                return '';
1711
            } else {
1712
                $userInfo = api_get_user_info($user_id);
1713
            }
1714
        }
1715
1716
        $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 1712 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...
1717
        $pictureWebFile = $imageWebPath['file'];
1718
        $pictureWebDir = $imageWebPath['dir'];
1719
1720
        $pictureAnonymousSize = '128';
1721
        $gravatarSize = 22;
1722
        $realSizeName = 'small_';
1723
1724
        switch ($size) {
1725
            case USER_IMAGE_SIZE_SMALL:
1726
                $pictureAnonymousSize = '32';
1727
                $realSizeName = 'small_';
1728
                $gravatarSize = 22;
1729
                break;
1730
            case USER_IMAGE_SIZE_MEDIUM:
1731
                $pictureAnonymousSize = '64';
1732
                $realSizeName = 'medium_';
1733
                $gravatarSize = 50;
1734
                break;
1735
            case USER_IMAGE_SIZE_ORIGINAL:
1736
                $pictureAnonymousSize = '128';
1737
                $realSizeName = '';
1738
                $gravatarSize = 200;
1739
                break;
1740
            case USER_IMAGE_SIZE_BIG:
1741
                $pictureAnonymousSize = '128';
1742
                $realSizeName = 'big_';
1743
                $gravatarSize = 200;
1744
                break;
1745
        }
1746
1747
        $gravatarEnabled = api_get_setting('gravatar_enabled');
1748
        $anonymousPath = Display::returnIconPath('unknown.png', $pictureAnonymousSize);
1749
        if ($pictureWebFile == 'unknown.jpg' || empty($pictureWebFile)) {
1750
            if ($gravatarEnabled === 'true') {
1751
                $file = self::getGravatar(
1752
                    $imageWebPath['email'],
1753
                    $gravatarSize,
1754
                    api_get_setting('gravatar_type')
1755
                );
1756
1757
                if ($addRandomId) {
1758
                    $file .= '&rand='.uniqid();
1759
                }
1760
1761
                return $file;
1762
            }
1763
1764
            return $anonymousPath;
1765
        }
1766
1767
        $pictureSysPath = self::get_user_picture_path_by_id($user_id, 'system');
1768
1769
        $file = $pictureSysPath['dir'].$realSizeName.$pictureWebFile;
1770
        $picture = '';
1771
        if (file_exists($file)) {
1772
            $picture = $pictureWebDir.$realSizeName.$pictureWebFile;
1773
        } else {
1774
            $file = $pictureSysPath['dir'].$pictureWebFile;
1775
            if (file_exists($file) && !is_dir($file)) {
1776
                $picture = $pictureWebFile['dir'].$pictureWebFile;
1777
            }
1778
        }
1779
1780
        if (empty($picture)) {
1781
            return $anonymousPath;
1782
        }
1783
1784
        if ($addRandomId) {
1785
            $picture .= '?rand='.uniqid();
1786
        }
1787
1788
        return $picture;
1789
    }
1790
1791
    /**
1792
     * Creates new user photos in various sizes of a user, or deletes user photos.
1793
     * Note: This method relies on configuration setting from main/inc/conf/profile.conf.php
1794
     * @param   int $user_id The user internal identification number.
1795
     * @param   string $file The common file name for the newly created photos.
1796
     *                       It will be checked and modified for compatibility with the file system.
1797
     *                       If full name is provided, path component is ignored.
1798
     *                       If an empty name is provided, then old user photos are deleted only,
1799
     * @see     UserManager::delete_user_picture() as the prefered way for deletion.
1800
     * @param   string $source_file The full system name of the image from which user photos will be created.
1801
     * @param   string $cropParameters Optional string that contents "x,y,width,height" of a cropped image format
1802
     * @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...
1803
     * When deletion is requested returns empty string. In case of internal error or negative validation returns FALSE.
1804
     */
1805
    public static function update_user_picture($user_id, $file = null, $source_file = null, $cropParameters = '')
1806
    {
1807
        if (empty($user_id)) {
1808
            return false;
1809
        }
1810
        $delete = empty($file);
1811
        if (empty($source_file)) {
1812
            $source_file = $file;
1813
        }
1814
1815
        // User-reserved directory where photos have to be placed.
1816
        $path_info = self::getUserPicturePathById($user_id, 'system');
1817
1818
        $path = $path_info['dir'];
1819
1820
        // If this directory does not exist - we create it.
1821
        if (!file_exists($path)) {
1822
            mkdir($path, api_get_permissions_for_new_directories(), true);
1823
        }
1824
1825
        // The old photos (if any).
1826
        $old_file = $path_info['file'];
1827
1828
        // Let us delete them.
1829 View Code Duplication
        if ($old_file != 'unknown.jpg') {
1830
            if (KEEP_THE_OLD_IMAGE_AFTER_CHANGE) {
1831
                $prefix = 'saved_'.date('Y_m_d_H_i_s').'_'.uniqid('').'_';
1832
                @rename($path.'small_'.$old_file, $path.$prefix.'small_'.$old_file);
1833
                @rename($path.'medium_'.$old_file, $path.$prefix.'medium_'.$old_file);
1834
                @rename($path.'big_'.$old_file, $path.$prefix.'big_'.$old_file);
1835
                @rename($path.$old_file, $path.$prefix.$old_file);
1836
            } else {
1837
                @unlink($path.'small_'.$old_file);
1838
                @unlink($path.'medium_'.$old_file);
1839
                @unlink($path.'big_'.$old_file);
1840
                @unlink($path.$old_file);
1841
            }
1842
        }
1843
1844
        // Exit if only deletion has been requested. Return an empty picture name.
1845
        if ($delete) {
1846
            return '';
1847
        }
1848
1849
        // Validation 2.
1850
        $allowed_types = api_get_supported_image_extensions();
1851
        $file = str_replace('\\', '/', $file);
1852
        $filename = (($pos = strrpos($file, '/')) !== false) ? substr($file, $pos + 1) : $file;
1853
        $extension = strtolower(substr(strrchr($filename, '.'), 1));
1854
        if (!in_array($extension, $allowed_types)) {
1855
            return false;
1856
        }
1857
1858
        // This is the common name for the new photos.
1859
        if (KEEP_THE_NAME_WHEN_CHANGE_IMAGE && $old_file != 'unknown.jpg') {
1860
            $old_extension = strtolower(substr(strrchr($old_file, '.'), 1));
1861
            $filename = in_array($old_extension, $allowed_types) ? substr($old_file, 0, -strlen($old_extension)) : $old_file;
1862
            $filename = (substr($filename, -1) == '.') ? $filename.$extension : $filename.'.'.$extension;
1863
        } else {
1864
            $filename = api_replace_dangerous_char($filename);
1865
            if (PREFIX_IMAGE_FILENAME_WITH_UID) {
1866
                $filename = uniqid('').'_'.$filename;
1867
            }
1868
            // We always prefix user photos with user ids, so on setting
1869
            // api_get_setting('split_users_upload_directory') === 'true'
1870
            // the correspondent directories to be found successfully.
1871
            $filename = $user_id.'_'.$filename;
1872
        }
1873
1874
        //Crop the image to adjust 1:1 ratio
1875
        $image = new Image($source_file);
1876
        $image->crop($cropParameters);
1877
1878
        // Storing the new photos in 4 versions with various sizes.
1879
        $userPath = self::getUserPathById($user_id, 'system');
1880
1881
        // If this path does not exist - we create it.
1882
        if (!file_exists($userPath)) {
1883
            mkdir($userPath, api_get_permissions_for_new_directories(), true);
1884
        }
1885
        $small = new Image($source_file);
1886
        $small->resize(32);
1887
        $small->send_image($userPath.'small_'.$filename);
1888
        $medium = new Image($source_file);
1889
        $medium->resize(85);
1890
        $medium->send_image($userPath.'medium_'.$filename);
1891
        $normal = new Image($source_file);
1892
        $normal->resize(200);
1893
        $normal->send_image($userPath.$filename);
1894
1895
        $big = new Image($source_file); // This is the original picture.
1896
        $big->send_image($userPath.'big_'.$filename);
1897
1898
        $result = $small && $medium && $normal && $big;
1899
1900
        return $result ? $filename : false;
1901
    }
1902
1903
    /**
1904
     * Update User extra field file type into {user_folder}/{$extra_field}
1905
     * @param int $user_id          The user internal identification number
1906
     * @param string $extra_field   The $extra_field The extra field name
1907
     * @param null $file            The filename
1908
     * @param null $source_file     The temporal filename
1909
     * @return bool|null            return filename if success, but false
1910
     */
1911
    public static function update_user_extra_file($user_id, $extra_field = '', $file = null, $source_file = null)
1912
    {
1913
        // Add Filter
1914
        $source_file = Security::filter_filename($source_file);
1915
        $file = Security::filter_filename($file);
1916
1917
        if (empty($user_id)) {
1918
            return false;
1919
        }
1920
1921
        if (empty($source_file)) {
1922
            $source_file = $file;
1923
        }
1924
1925
        // User-reserved directory where extra file have to be placed.
1926
        $path_info = self::get_user_picture_path_by_id($user_id, 'system');
1927
        $path = $path_info['dir'];
1928
        if (!empty($extra_field)) {
1929
            $path .= $extra_field . '/';
1930
        }
1931
        // If this directory does not exist - we create it.
1932
        if (!file_exists($path)) {
1933
            @mkdir($path, api_get_permissions_for_new_directories(), true);
1934
        }
1935
1936
        if (filter_extension($file)) {
1937
            if (@move_uploaded_file($source_file, $path.$file)) {
1938
                if ($extra_field) {
1939
                    return $extra_field.'/'.$file;
1940
                } else {
1941
                    return $file;
1942
                }
1943
            }
1944
        }
1945
        return false; // this should be returned if anything went wrong with the upload
1946
    }
1947
1948
1949
    /**
1950
     * Deletes user photos.
1951
     * Note: This method relies on configuration setting from main/inc/conf/profile.conf.php
1952
     * @param int $user_id            The user internal identitfication number.
1953
     * @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...
1954
     */
1955
    public static function delete_user_picture($user_id)
1956
    {
1957
        return self::update_user_picture($user_id);
1958
    }
1959
1960
    /**
1961
     * Returns an XHTML formatted list of productions for a user, or FALSE if he
1962
     * doesn't have any.
1963
     *
1964
     * If there has been a request to remove a production, the function will return
1965
     * without building the list unless forced to do so by the optional second
1966
     * parameter. This increases performance by avoiding to read through the
1967
     * productions on the filesystem before the removal request has been carried
1968
     * out because they'll have to be re-read afterwards anyway.
1969
     *
1970
     * @param   int $user_id    User id
1971
     * @param   bool $force    Optional parameter to force building after a removal request
1972
     * @param   bool $showDelete
1973
     *
1974
     * @return  string A string containing the XHTML code to display the production list, or FALSE
1975
     */
1976
    public static function build_production_list($user_id, $force = false, $showDelete = false)
1977
    {
1978
        if (!$force && !empty($_POST['remove_production'])) {
1979
1980
            return true; // postpone reading from the filesystem
1981
        }
1982
1983
        $productions = self::get_user_productions($user_id);
1984
1985
        if (empty($productions)) {
1986
1987
            return false;
1988
        }
1989
1990
        $production_dir = self::getUserPathById($user_id, 'web');
1991
        $del_image = Display::returnIconPath('delete.png');
1992
        $add_image = Display::returnIconPath('archive.png');
1993
        $del_text = get_lang('Delete');
1994
        $production_list = '';
1995
        if (count($productions) > 0) {
1996
            $production_list = '<div class="files-production"><ul id="productions">';
1997
            foreach ($productions as $file) {
1998
                $production_list .= '<li><img src="'.$add_image.'" /><a href="'.$production_dir.urlencode($file).'" target="_blank">'.htmlentities($file).'</a>';
1999 View Code Duplication
                if ($showDelete) {
2000
                    $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>';
2001
                }
2002
            }
2003
            $production_list .= '</ul></div>';
2004
        }
2005
2006
        return $production_list;
2007
    }
2008
2009
    /**
2010
     * Returns an array with the user's productions.
2011
     *
2012
     * @param    $user_id    User id
2013
     * @return   array  An array containing the user's productions
2014
     */
2015
    public static function get_user_productions($user_id)
2016
    {
2017
        $production_repository = self::getUserPathById($user_id, 'system');
2018
        $productions = array();
2019
2020
        if (is_dir($production_repository)) {
2021
            $handle = opendir($production_repository);
2022
            while ($file = readdir($handle)) {
2023
                if ($file == '.' ||
2024
                    $file == '..' ||
2025
                    $file == '.htaccess' ||
2026
                    is_dir($production_repository.$file)
2027
                ) {
2028
                    // skip current/parent directory and .htaccess
2029
                    continue;
2030
                }
2031
2032
                if (preg_match('/('.$user_id.'|[0-9a-f]{13}|saved)_.+\.(png|jpg|jpeg|gif)$/i', $file)) {
2033
                    // User's photos should not be listed as productions.
2034
                    continue;
2035
                }
2036
                $productions[] = $file;
2037
            }
2038
        }
2039
2040
        return $productions;
2041
    }
2042
2043
    /**
2044
     * Remove a user production.
2045
     *
2046
     * @param int $user_id        User id
2047
     * @param string $production    The production to remove
2048
     */
2049
    public static function remove_user_production($user_id, $production)
2050
    {
2051
        $production_path = self::get_user_picture_path_by_id($user_id, 'system');
2052
        $production_file = $production_path['dir'].$production;
2053
        if (is_file($production_file)) {
2054
            unlink($production_file);
2055
            return true;
2056
        }
2057
        return false;
2058
    }
2059
2060
    /**
2061
     * Update an extra field value for a given user
2062
     * @param    integer   $userId User ID
2063
     * @param    string    $variable Field variable name
2064
     * @param    string    $value Field value
2065
     *
2066
     * @return    boolean    true if field updated, false otherwise
2067
     */
2068 View Code Duplication
    public static function update_extra_field_value($userId, $variable, $value = '')
2069
    {
2070
        $extraFieldValue = new ExtraFieldValue('user');
2071
        $params = [
2072
            'item_id' => $userId,
2073
            'variable' => $variable,
2074
            'value' => $value
2075
        ];
2076
2077
        return $extraFieldValue->save($params);
2078
    }
2079
2080
    /**
2081
     * Get an array of extra fields with field details (type, default value and options)
2082
     * @param    integer    Offset (from which row)
2083
     * @param    integer    Number of items
2084
     * @param    integer    Column on which sorting is made
2085
     * @param    string    Sorting direction
2086
     * @param    boolean    Optional. Whether we get all the fields or just the visible ones
2087
     * @param    int        Optional. Whether we get all the fields with field_filter 1 or 0 or everything
2088
     * @return    array    Extra fields details (e.g. $list[2]['type'], $list[4]['options'][2]['title']
2089
     */
2090
    public static function get_extra_fields(
2091
        $from = 0,
2092
        $number_of_items = 0,
2093
        $column = 5,
2094
        $direction = 'ASC',
2095
        $all_visibility = true,
2096
        $field_filter = null
2097
    ) {
2098
        $fields = array();
2099
        $t_uf = Database :: get_main_table(TABLE_EXTRA_FIELD);
2100
        $t_ufo = Database :: get_main_table(TABLE_EXTRA_FIELD_OPTIONS);
2101
        $columns = array(
2102
            'id',
2103
            'variable',
2104
            'field_type',
2105
            'display_text',
2106
            'default_value',
2107
            'field_order',
2108
            'filter'
2109
        );
2110
        $column = intval($column);
2111
        $sort_direction = '';
2112
        if (in_array(strtoupper($direction), array('ASC', 'DESC'))) {
2113
            $sort_direction = strtoupper($direction);
2114
        }
2115
        $extraFieldType = EntityExtraField::USER_FIELD_TYPE;
2116
        $sqlf = "SELECT * FROM $t_uf WHERE extra_field_type = $extraFieldType ";
2117
        if (!$all_visibility) {
2118
            $sqlf .= " AND visible_to_self = 1 ";
2119
        }
2120
        if (!is_null($field_filter)) {
2121
            $field_filter = intval($field_filter);
2122
            $sqlf .= " AND filter = $field_filter ";
2123
        }
2124
        $sqlf .= " ORDER BY ".$columns[$column]." $sort_direction ";
2125
        if ($number_of_items != 0) {
2126
            $sqlf .= " LIMIT ".intval($from).','.intval($number_of_items);
2127
        }
2128
        $resf = Database::query($sqlf);
2129
        if (Database::num_rows($resf) > 0) {
2130
            while ($rowf = Database::fetch_array($resf)) {
2131
                $fields[$rowf['id']] = array(
2132
                    0 => $rowf['id'],
2133
                    1 => $rowf['variable'],
2134
                    2 => $rowf['field_type'],
2135
                    3 => empty($rowf['display_text']) ? '' : $rowf['display_text'],
2136
                    4 => $rowf['default_value'],
2137
                    5 => $rowf['field_order'],
2138
                    6 => $rowf['visible_to_self'],
2139
                    7 => $rowf['changeable'],
2140
                    8 => $rowf['filter'],
2141
                    9 => array(),
2142
                    10 => '<a name="'.$rowf['id'].'"></a>',
2143
                );
2144
2145
                $sqlo = "SELECT * FROM $t_ufo
2146
                         WHERE field_id = ".$rowf['id']."
2147
                         ORDER BY option_order ASC";
2148
                $reso = Database::query($sqlo);
2149
                if (Database::num_rows($reso) > 0) {
2150
                    while ($rowo = Database::fetch_array($reso)) {
2151
                        $fields[$rowf['id']][9][$rowo['id']] = array(
2152
                            0 => $rowo['id'],
2153
                            1 => $rowo['option_value'],
2154
                            2 => empty($rowo['display_text']) ? '' : $rowo['display_text'],
2155
                            3 => $rowo['option_order']
2156
                        );
2157
                    }
2158
                }
2159
            }
2160
        }
2161
2162
        return $fields;
2163
    }
2164
2165
    /**
2166
     * Build a list of extra file already uploaded in $user_folder/{$extra_field}/
2167
     * @param $user_id
2168
     * @param $extra_field
2169
     * @param bool $force
2170
     * @param bool $showDelete
2171
     * @return bool|string
2172
     */
2173
    public static function build_user_extra_file_list($user_id, $extra_field, $force = false, $showDelete = false)
2174
    {
2175
        if (!$force && !empty($_POST['remove_'.$extra_field])) {
2176
            return true; // postpone reading from the filesystem
2177
        }
2178
2179
        $extra_files = self::get_user_extra_files($user_id, $extra_field);
2180
        if (empty($extra_files)) {
2181
            return false;
2182
        }
2183
2184
        $path_info = self::get_user_picture_path_by_id($user_id, 'web');
2185
        $path = $path_info['dir'];
2186
        $del_image = Display::returnIconPath('delete.png');
2187
2188
        $del_text = get_lang('Delete');
2189
        $extra_file_list = '';
2190
        if (count($extra_files) > 0) {
2191
            $extra_file_list = '<div class="files-production"><ul id="productions">';
2192
            foreach ($extra_files as $file) {
2193
                $filename = substr($file,strlen($extra_field)+1);
2194
                $extra_file_list .= '<li>'.Display::return_icon('archive.png').'<a href="'.$path.$extra_field.'/'.urlencode($filename).'" target="_blank">'.htmlentities($filename).'</a> ';
2195 View Code Duplication
                if ($showDelete) {
2196
                    $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>';
2197
                }
2198
            }
2199
            $extra_file_list .= '</ul></div>';
2200
        }
2201
2202
        return $extra_file_list;
2203
    }
2204
2205
    /**
2206
     * Get valid filenames in $user_folder/{$extra_field}/
2207
     * @param $user_id
2208
     * @param $extra_field
2209
     * @param bool $full_path
2210
     * @return array
2211
     */
2212
    public static function get_user_extra_files($user_id, $extra_field, $full_path = false)
2213
    {
2214
        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...
2215
            // Nothing to do
2216
        } else {
2217
            $path_info = self::get_user_picture_path_by_id($user_id, 'system');
2218
            $path = $path_info['dir'];
2219
        }
2220
        $extra_data = self::get_extra_user_data_by_field($user_id, $extra_field);
2221
        $extra_files = $extra_data[$extra_field];
2222
        if (is_array($extra_files)) {
2223
            foreach ($extra_files as $key => $value) {
2224
                if (!$full_path) {
2225
                    // Relative path from user folder
2226
                    $files[] = $value;
2227
                } else {
2228
                    $files[] = $path.$value;
2229
                }
2230
            }
2231
        } elseif (!empty($extra_files)) {
2232
            if (!$full_path) {
2233
                // Relative path from user folder
2234
                $files[] = $extra_files;
2235
            } else {
2236
                $files[] = $path.$extra_files;
2237
            }
2238
        }
2239
2240
        return $files; // can be an empty array
2241
    }
2242
2243
    /**
2244
     * Remove an {$extra_file} from the user folder $user_folder/{$extra_field}/
2245
     * @param $user_id
2246
     * @param $extra_field
2247
     * @param $extra_file
2248
     * @return bool
2249
     */
2250
    public static function remove_user_extra_file($user_id, $extra_field, $extra_file)
2251
    {
2252
        $extra_file = Security::filter_filename($extra_file);
2253
        $path_info = self::get_user_picture_path_by_id($user_id, 'system');
2254
        if (strpos($extra_file, $extra_field) !== false) {
2255
            $path_extra_file = $path_info['dir'].$extra_file;
2256
        } else {
2257
            $path_extra_file = $path_info['dir'].$extra_field.'/'.$extra_file;
2258
        }
2259
        if (is_file($path_extra_file)) {
2260
            unlink($path_extra_file);
2261
            return true;
2262
        }
2263
        return false;
2264
    }
2265
2266
    /**
2267
     * Creates a new extra field
2268
     * @param    string    $variable Field's internal variable name
2269
     * @param    int       $fieldType  Field's type
2270
     * @param    string    $displayText Field's language var name
2271
     * @param    string    $default Field's default value
2272
     * @return int
2273
     */
2274 View Code Duplication
    public static function create_extra_field($variable, $fieldType, $displayText, $default)
2275
    {
2276
        $extraField = new ExtraField('user');
2277
        $params = [
2278
            'variable' => $variable,
2279
            'field_type' => $fieldType,
2280
            'display_text' => $displayText,
2281
            'default_value' => $default
2282
        ];
2283
2284
        return $extraField->save($params);
2285
    }
2286
2287
    /**
2288
     * Check if a field is available
2289
     * @param    string    $variable
2290
     * @return    boolean
2291
     */
2292
    public static function is_extra_field_available($variable)
2293
    {
2294
        $extraField = new ExtraField('user');
2295
        $data = $extraField->get_handler_field_info_by_field_variable($variable);
2296
2297
        return !empty($data) ? true : false;
2298
    }
2299
2300
    /**
2301
     * Gets user extra fields data
2302
     * @param    integer    User ID
2303
     * @param    boolean    Whether to prefix the fields indexes with "extra_" (might be used by formvalidator)
2304
     * @param    boolean    Whether to return invisible fields as well
2305
     * @param    boolean    Whether to split multiple-selection fields or not
2306
     * @return    array    Array of fields => value for the given user
2307
     */
2308
    public static function get_extra_user_data(
2309
        $user_id,
2310
        $prefix = false,
2311
        $all_visibility = true,
2312
        $splitmultiple = false,
2313
        $field_filter = null
2314
    ) {
2315
        // A sanity check.
2316 View Code Duplication
        if (empty($user_id)) {
2317
            $user_id = 0;
2318
        } else {
2319
            if ($user_id != strval(intval($user_id)))
2320
                return array();
2321
        }
2322
        $extra_data = array();
2323
        $t_uf = Database::get_main_table(TABLE_EXTRA_FIELD);
2324
        $t_ufv = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
2325
        $user_id = intval($user_id);
2326
        $sql = "SELECT f.id as id, f.variable as fvar, f.field_type as type
2327
                FROM $t_uf f
2328
                WHERE
2329
                    extra_field_type = ".EntityExtraField::USER_FIELD_TYPE."
2330
                ";
2331
        $filter_cond = '';
2332
2333
        if (!$all_visibility) {
2334
            if (isset($field_filter)) {
2335
                $field_filter = intval($field_filter);
2336
                $filter_cond .= " AND filter = $field_filter ";
2337
            }
2338
            $sql .= " AND f.visible_to_self = 1 $filter_cond ";
2339
        } else {
2340
            if (isset($field_filter)) {
2341
                $field_filter = intval($field_filter);
2342
                $sql .= " AND filter = $field_filter ";
2343
            }
2344
        }
2345
2346
        $sql .= " ORDER BY f.field_order";
2347
2348
        $res = Database::query($sql);
2349
        if (Database::num_rows($res) > 0) {
2350
            while ($row = Database::fetch_array($res)) {
2351
                if ($row['type'] == self::USER_FIELD_TYPE_TAG) {
2352
                    $tags = self::get_user_tags_to_string($user_id, $row['id'], false);
2353
                    $extra_data['extra_'.$row['fvar']] = $tags;
2354
                } else {
2355
                    $sqlu = "SELECT value as fval
2356
                            FROM $t_ufv
2357
                            WHERE field_id=".$row['id']." AND item_id = ".$user_id;
2358
                    $resu = Database::query($sqlu);
2359
                    // get default value
2360
                    $sql_df = "SELECT default_value as fval_df FROM $t_uf
2361
                               WHERE id=".$row['id'];
2362
                    $res_df = Database::query($sql_df);
2363
2364
                    if (Database::num_rows($resu) > 0) {
2365
                        $rowu = Database::fetch_array($resu);
2366
                        $fval = $rowu['fval'];
2367
                        if ($row['type'] == self::USER_FIELD_TYPE_SELECT_MULTIPLE) {
2368
                            $fval = explode(';', $rowu['fval']);
2369
                        }
2370
                    } else {
2371
                        $row_df = Database::fetch_array($res_df);
2372
                        $fval = $row_df['fval_df'];
2373
                    }
2374
                    // We get here (and fill the $extra_data array) even if there
2375
                    // is no user with data (we fill it with default values)
2376
                    if ($prefix) {
2377 View Code Duplication
                        if ($row['type'] == self::USER_FIELD_TYPE_RADIO) {
2378
                            $extra_data['extra_'.$row['fvar']]['extra_'.$row['fvar']] = $fval;
2379
                        } else {
2380
                            $extra_data['extra_'.$row['fvar']] = $fval;
2381
                        }
2382 View Code Duplication
                    } else {
2383
                        if ($row['type'] == self::USER_FIELD_TYPE_RADIO) {
2384
                            $extra_data['extra_'.$row['fvar']]['extra_'.$row['fvar']] = $fval;
2385
                        } else {
2386
                            $extra_data[$row['fvar']] = $fval;
2387
                        }
2388
                    }
2389
                }
2390
            }
2391
        }
2392
2393
        return $extra_data;
2394
    }
2395
2396
    /** Get extra user data by field
2397
     * @param int    user ID
2398
     * @param string the internal variable name of the field
2399
     * @return array with extra data info of a user i.e array('field_variable'=>'value');
2400
     */
2401
    public static function get_extra_user_data_by_field(
2402
        $user_id,
2403
        $field_variable,
2404
        $prefix = false,
2405
        $all_visibility = true,
2406
        $splitmultiple = false
2407
    ) {
2408
        // A sanity check.
2409 View Code Duplication
        if (empty($user_id)) {
2410
            $user_id = 0;
2411
        } else {
2412
            if ($user_id != strval(intval($user_id)))
2413
                return array();
2414
        }
2415
        $extra_data = array();
2416
        $t_uf = Database::get_main_table(TABLE_EXTRA_FIELD);
2417
        $t_ufv = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
2418
        $user_id = intval($user_id);
2419
2420
        $sql = "SELECT f.id as id, f.variable as fvar, f.field_type as type
2421
                FROM $t_uf f
2422
                WHERE f.variable = '$field_variable' ";
2423
2424
        if (!$all_visibility) {
2425
            $sql .= " AND f.visible_to_self = 1 ";
2426
        }
2427
2428
        $sql .= " AND extra_field_type = ".EntityExtraField::USER_FIELD_TYPE;
2429
2430
        $sql .= " ORDER BY f.field_order";
2431
2432
        $res = Database::query($sql);
2433
        if (Database::num_rows($res) > 0) {
2434
            while ($row = Database::fetch_array($res)) {
2435
                $sqlu = "SELECT value as fval FROM $t_ufv v INNER JOIN $t_uf f
2436
                         ON (v.field_id = f.id)
2437
                         WHERE
2438
                            extra_field_type = ".EntityExtraField::USER_FIELD_TYPE." AND
2439
                            field_id = ".$row['id']." AND
2440
                            item_id = ".$user_id;
2441
                $resu = Database::query($sqlu);
2442
                $fval = '';
2443 View Code Duplication
                if (Database::num_rows($resu) > 0) {
2444
                    $rowu = Database::fetch_array($resu);
2445
                    $fval = $rowu['fval'];
2446
                    if ($row['type'] == self::USER_FIELD_TYPE_SELECT_MULTIPLE) {
2447
                        $fval = explode(';', $rowu['fval']);
2448
                    }
2449
                }
2450
                if ($prefix) {
2451
                    $extra_data['extra_'.$row['fvar']] = $fval;
2452
                } else {
2453
                    $extra_data[$row['fvar']] = $fval;
2454
                }
2455
            }
2456
        }
2457
2458
        return $extra_data;
2459
    }
2460
2461
    /**
2462
     * Get the extra field information for a certain field (the options as well)
2463
     * @param  int     $variable The name of the field we want to know everything about
2464
     * @return array   Array containing all the information about the extra profile field
2465
     * (first level of array contains field details, then 'options' sub-array contains options details,
2466
     * as returned by the database)
2467
     * @author Julio Montoya
2468
     * @since v1.8.6
2469
     */
2470
    public static function get_extra_field_information_by_name($variable)
2471
    {
2472
        $extraField = new ExtraField('user');
2473
2474
        return $extraField->get_handler_field_info_by_field_variable($variable);
2475
    }
2476
2477
    /**
2478
     * Get the extra field information for user tag (the options as well)
2479
     * @param  int     $variable The name of the field we want to know everything about
2480
     * @return array   Array containing all the information about the extra profile field
2481
     * (first level of array contains field details, then 'options' sub-array contains options details,
2482
     * as returned by the database)
2483
     * @author José Loguercio
2484
     * @since v1.11.0
2485
     */
2486
    public static function get_extra_field_tags_information_by_name($variable)
2487
    {
2488
        $extraField = new ExtraField('user');
2489
2490
        return $extraField->get_handler_field_info_by_tags($variable);
2491
    }
2492
2493
    /**
2494
     * @param string $type
2495
     *
2496
     * @return array
2497
     */
2498
    public static function get_all_extra_field_by_type($type)
2499
    {
2500
        $extraField = new ExtraField('user');
2501
2502
        return $extraField->get_all_extra_field_by_type($type);
2503
    }
2504
2505
    /**
2506
     * Get all the extra field information of a certain field (also the options)
2507
     *
2508
     * @param int $fieldId the ID of the field we want to know everything of
2509
     * @return array $return containing all th information about the extra profile field
2510
     * @author Julio Montoya
2511
     * @deprecated
2512
     * @since v1.8.6
2513
     */
2514
    public static function get_extra_field_information($fieldId)
2515
    {
2516
        $extraField = new ExtraField('user');
2517
2518
        return $extraField->getFieldInfoByFieldId($fieldId);
2519
    }
2520
2521
    /**
2522
     * Get extra user data by value
2523
     * @param string $variable the internal variable name of the field
2524
     * @param string $value the internal value of the field
2525
     * @param bool $all_visibility
2526
     *
2527
     * @return array with extra data info of a user i.e array('field_variable'=>'value');
2528
     */
2529
     public static function get_extra_user_data_by_value($variable, $value, $all_visibility = true)
2530
    {
2531
        $extraFieldValue = new ExtraFieldValue('user');
2532
        $extraField = new ExtraField('user');
2533
2534
        $info = $extraField->get_handler_field_info_by_field_variable($variable);
2535
2536
        if (false === $info) {
2537
            return [];
2538
        }
2539
2540
        $data = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
2541
            $variable,
2542
            $value,
2543
            false,
2544
            false,
2545
            true
2546
        );
2547
2548
        $result = [];
2549
        if (!empty($data)) {
2550
            foreach ($data as $item) {
2551
                $result[] = $item['item_id'];
2552
            }
2553
        }
2554
2555
        return $result;
2556
    }
2557
2558
    /**
2559
     * Get extra user data by tags value
2560
     *
2561
     * @param int $fieldId the ID of the field we want to know everything of
2562
     * @param string $tag the tag name for search
2563
     * @return array with extra data info of a user
2564
     * @author José Loguercio
2565
     * @since v1.11.0
2566
     */
2567
    public static function get_extra_user_data_by_tags($fieldId, $tag)
2568
    {
2569
        $extraField = new ExtraField('user');
2570
        $result = $extraField->getAllUserPerTag($fieldId, $tag);
2571
        $array = [];
2572
        foreach ($result as $index => $user) {
2573
            $array[] = $user['user_id'];
2574
        }
2575
        return $array;
2576
    }
2577
2578
    /**
2579
     * Get extra user data by field variable
2580
     * @param string    $variable field variable
2581
     * @return array    data
2582
     */
2583
    public static function get_extra_user_data_by_field_variable($variable)
2584
    {
2585
        $extra_information_by_variable = self::get_extra_field_information_by_name($variable);
2586
        $field_id = intval($extra_information_by_variable['id']);
2587
2588
        $extraField = new ExtraFieldValue('user');
2589
        $data = $extraField->getValuesByFieldId($field_id);
2590
2591
        if (!empty($data) > 0) {
2592
            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...
2593
                $user_id = $row['item_id'];
2594
                $data[$user_id] = $row;
2595
            }
2596
        }
2597
2598
        return $data;
2599
    }
2600
2601
    /**
2602
     * Get extra user data tags by field variable
2603
     *
2604
     * @param string $variable field variable
2605
     * @return array
2606
     */
2607
    public static function get_extra_user_data_for_tags($variable)
2608
    {
2609
        $data = self::get_extra_field_tags_information_by_name($variable);
2610
2611
        return $data;
2612
    }
2613
2614
    /**
2615
     * Gives a list of [session_category][session_id] for the current user.
2616
     * @param integer $user_id
2617
     * @param boolean whether to fill the first element or not (to give space for courses out of categories)
2618
     * @param boolean  optional true if limit time from session is over, false otherwise
2619
     * @param boolean $ignoreTimeLimit ignore time start/end
2620
     * @return array  list of statuses [session_category][session_id]
2621
     *
2622
     * @todo ensure multiple access urls are managed correctly
2623
     */
2624
    public static function get_sessions_by_category(
2625
        $user_id,
2626
        $is_time_over = true,
2627
        $ignore_visibility_for_admins = false,
2628
        $ignoreTimeLimit = false
2629
    ) {
2630
        if ($user_id != strval(intval($user_id))) {
2631
            return array();
2632
        }
2633
2634
        // Get the list of sessions per user
2635
        $now = new DateTime('now', new DateTimeZone('UTC'));
2636
2637
        $dql = "SELECT DISTINCT
2638
                    s.id,
2639
                    s.name,
2640
                    s.accessStartDate AS access_start_date,
2641
                    s.accessEndDate AS access_end_date,
2642
                    sc.id AS session_category_id,
2643
                    sc.name AS session_category_name,
2644
                    sc.dateStart AS session_category_date_start,
2645
                    sc.dateEnd AS session_category_date_end,
2646
                    s.coachAccessStartDate AS coach_access_start_date,
2647
                    s.coachAccessEndDate AS coach_access_end_date
2648
                FROM ChamiloCoreBundle:Session AS s                                
2649
                INNER JOIN ChamiloCoreBundle:SessionRelCourseRelUser AS scu WITH scu.session = s
2650
                LEFT JOIN ChamiloCoreBundle:SessionCategory AS sc WITH s.category = sc
2651
                WHERE scu.user = :user OR s.generalCoach = :user
2652
                ORDER BY sc.name, s.name";
2653
2654
        $dql = Database::getManager()
2655
            ->createQuery($dql)
2656
            ->setParameters(['user' => $user_id])
2657
        ;
2658
2659
        $sessionData = $dql->getResult();
2660
        $categories = [];
2661
2662
        foreach ($sessionData as $row) {
2663
            $session_id = $row['id'];
2664
            $coachList = SessionManager::getCoachesBySession($session_id);
2665
2666
            $categoryStart = $row['session_category_date_start'] ? $row['session_category_date_start']->format('Y-m-d') : '';
2667
            $categoryEnd = $row['session_category_date_end'] ? $row['session_category_date_end']->format('Y-m-d') : '';
2668
2669
            $courseList = UserManager::get_courses_list_by_session(
2670
                $user_id,
2671
                $session_id
2672
            );
2673
2674
            // User portal filters:
2675
            if ($ignoreTimeLimit === false) {
2676
                if ($is_time_over) {
2677
                    // History
2678
                    if (empty($row['access_end_date'])) {
2679
                        continue;
2680
                    } else {
2681
                        if ($row['access_end_date'] > $now) {
2682
                            continue;
2683
                        }
2684
                    }
2685
                } else {
2686
                    // Current user portal
2687
                    $isGeneralCoach = SessionManager::user_is_general_coach($user_id, $row['id']);
2688
                    $isCoachOfCourse = in_array($user_id, $coachList);
2689
2690
                    if (api_is_platform_admin() || $isGeneralCoach || $isCoachOfCourse) {
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...
2691
                        // Teachers can access the session depending in the access_coach date
2692
                    } else {
2693
                        if (isset($row['access_end_date']) &&
2694
                            !empty($row['access_end_date'])
2695
                        ) {
2696
                            if ($row['access_end_date'] <= $now) {
2697
                                continue;
2698
                            }
2699
                        }
2700
                    }
2701
                }
2702
            }
2703
2704
            $categories[$row['session_category_id']]['session_category'] = array(
2705
                'id' => $row['session_category_id'],
2706
                'name' => $row['session_category_name'],
2707
                'date_start' => $categoryStart,
2708
                'date_end' => $categoryEnd
2709
            );
2710
2711
            $visibility = api_get_session_visibility(
2712
                $session_id,
2713
                null,
2714
                $ignore_visibility_for_admins
2715
            );
2716
2717 View Code Duplication
            if ($visibility != SESSION_VISIBLE) {
2718
                // Course Coach session visibility.
2719
                $blockedCourseCount = 0;
2720
                $closedVisibilityList = array(
2721
                    COURSE_VISIBILITY_CLOSED,
2722
                    COURSE_VISIBILITY_HIDDEN
2723
                );
2724
2725
                foreach ($courseList as $course) {
2726
                    // Checking session visibility
2727
                    $sessionCourseVisibility = api_get_session_visibility(
2728
                        $session_id,
2729
                        $course['real_id'],
2730
                        $ignore_visibility_for_admins
2731
                    );
2732
2733
                    $courseIsVisible = !in_array(
2734
                        $course['visibility'],
2735
                        $closedVisibilityList
2736
                    );
2737
                    if ($courseIsVisible === false || $sessionCourseVisibility == SESSION_INVISIBLE) {
2738
                        $blockedCourseCount++;
2739
                    }
2740
                }
2741
2742
                // If all courses are blocked then no show in the list.
2743
                if ($blockedCourseCount === count($courseList)) {
2744
                    $visibility = SESSION_INVISIBLE;
2745
                } else {
2746
                    $visibility = SESSION_VISIBLE;
2747
                }
2748
            }
2749
2750
            switch ($visibility) {
2751
                case SESSION_VISIBLE_READ_ONLY:
2752
                case SESSION_VISIBLE:
2753
                case SESSION_AVAILABLE:
2754
                    break;
2755
                case SESSION_INVISIBLE:
2756
                    if ($ignore_visibility_for_admins === false) {
2757
                        continue 2;
2758
                    }
2759
            }
2760
2761
            $categories[$row['session_category_id']]['sessions'][$row['id']] = array(
2762
                'session_name' => $row['name'],
2763
                'session_id' => $row['id'],
2764
                'access_start_date' => $row['access_start_date'] ? $row['access_start_date']->format('Y-m-d H:i:s') : null,
2765
                'access_end_date' => $row['access_end_date'] ? $row['access_end_date']->format('Y-m-d H:i:s') : null,
2766
                'coach_access_start_date' => $row['coach_access_start_date'] ? $row['coach_access_start_date']->format('Y-m-d H:i:s') : null,
2767
                'coach_access_end_date' => $row['coach_access_end_date'] ? $row['coach_access_end_date']->format('Y-m-d H:i:s') : null,
2768
                'courses' => $courseList
2769
            );
2770
        }
2771
2772
        return $categories;
2773
    }
2774
2775
    /**
2776
     * Gives a list of [session_id-course_code] => [status] for the current user.
2777
     * @param integer $user_id
2778
     * @param int $sessionLimit
2779
     * @return array  list of statuses (session_id-course_code => status)
2780
     */
2781
    public static function get_personal_session_course_list($user_id, $sessionLimit = null)
2782
    {
2783
        // Database Table Definitions
2784
        $tbl_course = Database :: get_main_table(TABLE_MAIN_COURSE);
2785
        $tbl_user = Database :: get_main_table(TABLE_MAIN_USER);
2786
        $tbl_session = Database :: get_main_table(TABLE_MAIN_SESSION);
2787
        $tbl_session_user = Database :: get_main_table(TABLE_MAIN_SESSION_USER);
2788
        $tbl_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
2789
        $tbl_session_course_user = Database :: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2790
2791
        if ($user_id != strval(intval($user_id))) {
2792
            return array();
2793
        }
2794
2795
        // We filter the courses from the URL
2796
        $join_access_url = $where_access_url = '';
2797
2798 View Code Duplication
        if (api_get_multiple_access_url()) {
2799
            $access_url_id = api_get_current_access_url_id();
2800
            if ($access_url_id != -1) {
2801
                $tbl_url_course = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2802
                $join_access_url = "LEFT JOIN $tbl_url_course url_rel_course ON url_rel_course.c_id = course.id";
2803
                $where_access_url = " AND access_url_id = $access_url_id ";
2804
            }
2805
        }
2806
2807
        // Courses in which we subscribed out of any session
2808
        $tbl_user_course_category = Database :: get_main_table(TABLE_USER_COURSE_CATEGORY);
2809
2810
        $sql = "SELECT
2811
                    course.code,
2812
                    course_rel_user.status course_rel_status,
2813
                    course_rel_user.sort sort,
2814
                    course_rel_user.user_course_cat user_course_cat
2815
                 FROM $tbl_course_user course_rel_user
2816
                 LEFT JOIN $tbl_course course
2817
                 ON course.id = course_rel_user.c_id
2818
                 LEFT JOIN $tbl_user_course_category user_course_category
2819
                 ON course_rel_user.user_course_cat = user_course_category.id
2820
                 $join_access_url
2821
                 WHERE
2822
                    course_rel_user.user_id = '".$user_id."' AND
2823
                    course_rel_user.relation_type <> ".COURSE_RELATION_TYPE_RRHH."
2824
                    $where_access_url
2825
                 ORDER BY user_course_category.sort, course_rel_user.sort, course.title ASC";
2826
2827
        $course_list_sql_result = Database::query($sql);
2828
2829
        $personal_course_list = array();
2830
        if (Database::num_rows($course_list_sql_result) > 0) {
2831
            while ($result_row = Database::fetch_array($course_list_sql_result, 'ASSOC')) {
2832
                $course_info = api_get_course_info($result_row['code']);
2833
                $result_row['course_info'] = $course_info;
2834
                $personal_course_list[] = $result_row;
2835
            }
2836
        }
2837
2838
        $coachCourseConditions = null;
2839
2840
        // Getting sessions that are related to a coach in the session_rel_course_rel_user table
2841
2842
        if (api_is_allowed_to_create_course()) {
2843
            $sessionListFromCourseCoach = array();
2844
            $sql =" SELECT DISTINCT session_id
2845
                    FROM $tbl_session_course_user
2846
                    WHERE user_id = $user_id AND status = 2 ";
2847
2848
            $result = Database::query($sql);
2849
            if (Database::num_rows($result)) {
2850
                $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...
2851
                foreach ($result as $session) {
2852
                    $sessionListFromCourseCoach[]= $session['session_id'];
2853
                }
2854
            }
2855
            if (!empty($sessionListFromCourseCoach)) {
2856
                $condition = implode("','", $sessionListFromCourseCoach);
2857
                $coachCourseConditions = " OR ( s.id IN ('$condition'))";
2858
            }
2859
        }
2860
2861
        // Get the list of sessions where the user is subscribed
2862
        // This is divided into two different queries
2863
        $sessions = array();
2864
2865
        $sessionLimitRestriction = '';
2866
        if (!empty($sessionLimit)) {
2867
            $sessionLimit = (int) $sessionLimit;
2868
            $sessionLimitRestriction = "LIMIT $sessionLimit";
2869
        }
2870
2871
        $sql = "SELECT DISTINCT s.id, name, access_start_date, access_end_date
2872
                FROM $tbl_session_user su INNER JOIN $tbl_session s
2873
                ON (s.id = su.session_id)
2874
                WHERE (
2875
                    su.user_id = $user_id AND
2876
                    su.relation_type <> ".SESSION_RELATION_TYPE_RRHH."
2877
                )
2878
                $coachCourseConditions
2879
                ORDER BY access_start_date, access_end_date, name
2880
                $sessionLimitRestriction
2881
        ";
2882
2883
        $result = Database::query($sql);
2884
        if (Database::num_rows($result)>0) {
2885
            while ($row = Database::fetch_assoc($result)) {
2886
                $sessions[$row['id']] = $row;
2887
            }
2888
        }
2889
2890
        $sql = "SELECT DISTINCT
2891
                id, name, access_start_date, access_end_date
2892
                FROM $tbl_session s
2893
                WHERE (
2894
                    id_coach = $user_id
2895
                )
2896
                $coachCourseConditions
2897
                ORDER BY access_start_date, access_end_date, name";
2898
2899
        $result = Database::query($sql);
2900
        if (Database::num_rows($result)>0) {
2901
            while ($row = Database::fetch_assoc($result)) {
2902
                if (empty($sessions[$row['id']])) {
2903
                    $sessions[$row['id']] = $row;
2904
                }
2905
            }
2906
        }
2907
2908
        if (api_is_allowed_to_create_course()) {
2909
            foreach ($sessions as $enreg) {
2910
                $session_id = $enreg['id'];
2911
                $session_visibility = api_get_session_visibility($session_id);
2912
2913
                if ($session_visibility == SESSION_INVISIBLE) {
2914
                    continue;
2915
                }
2916
2917
                // This query is horribly slow when more than a few thousand
2918
                // users and just a few sessions to which they are subscribed
2919
                $sql = "SELECT DISTINCT
2920
                        course.code code,
2921
                        course.title i,
2922
                        ".(api_is_western_name_order() ? "CONCAT(user.firstname,' ',user.lastname)" : "CONCAT(user.lastname,' ',user.firstname)")." t,
2923
                        email, course.course_language l,
2924
                        1 sort,
2925
                        category_code user_course_cat,
2926
                        access_start_date,
2927
                        access_end_date,
2928
                        session.id as session_id,
2929
                        session.name as session_name
2930
                    FROM $tbl_session_course_user as session_course_user
2931
                        INNER JOIN $tbl_course AS course
2932
                            ON course.id = session_course_user.c_id
2933
                        INNER JOIN $tbl_session as session
2934
                            ON session.id = session_course_user.session_id
2935
                        LEFT JOIN $tbl_user as user
2936
                            ON user.id = session_course_user.user_id OR session.id_coach = user.id
2937
                    WHERE
2938
                        session_course_user.session_id = $session_id AND (
2939
                            (session_course_user.user_id = $user_id AND session_course_user.status = 2)
2940
                            OR session.id_coach = $user_id
2941
                        )
2942
                    ORDER BY i";
2943
                $course_list_sql_result = Database::query($sql);
2944 View Code Duplication
                while ($result_row = Database::fetch_array($course_list_sql_result, 'ASSOC')) {
2945
                    $result_row['course_info'] = api_get_course_info($result_row['code']);
2946
                    $key = $result_row['session_id'].' - '.$result_row['code'];
2947
                    $personal_course_list[$key] = $result_row;
2948
                }
2949
            }
2950
        }
2951
2952
        foreach ($sessions as $enreg) {
2953
            $session_id = $enreg['id'];
2954
            $session_visibility = api_get_session_visibility($session_id);
2955
            if ($session_visibility == SESSION_INVISIBLE) {
2956
                continue;
2957
            }
2958
2959
            /* This query is very similar to the above query,
2960
               but it will check the session_rel_course_user table if there are courses registered to our user or not */
2961
            $sql = "SELECT DISTINCT
2962
                course.code code,
2963
                course.title i, CONCAT(user.lastname,' ',user.firstname) t,
2964
                email,
2965
                course.course_language l,
2966
                1 sort,
2967
                category_code user_course_cat,
2968
                access_start_date,
2969
                access_end_date,
2970
                session.id as session_id,
2971
                session.name as session_name,
2972
                IF((session_course_user.user_id = 3 AND session_course_user.status=2),'2', '5')
2973
            FROM $tbl_session_course_user as session_course_user
2974
            INNER JOIN $tbl_course AS course
2975
            ON course.id = session_course_user.c_id AND session_course_user.session_id = $session_id
2976
            INNER JOIN $tbl_session as session 
2977
            ON session_course_user.session_id = session.id
2978
            LEFT JOIN $tbl_user as user ON user.id = session_course_user.user_id
2979
            WHERE session_course_user.user_id = $user_id
2980
            ORDER BY i";
2981
2982
            $course_list_sql_result = Database::query($sql);
2983 View Code Duplication
            while ($result_row = Database::fetch_array($course_list_sql_result, 'ASSOC')) {
2984
                $result_row['course_info'] = api_get_course_info($result_row['code']);
2985
                $key = $result_row['session_id'].' - '.$result_row['code'];
2986
                if (!isset($personal_course_list[$key])) {
2987
                    $personal_course_list[$key] = $result_row;
2988
                }
2989
            }
2990
        }
2991
2992
        return $personal_course_list;
2993
    }
2994
2995
    /**
2996
     * Gives a list of courses for the given user in the given session
2997
     * @param integer $user_id
2998
     * @param integer $session_id
2999
     * @return array  list of statuses (session_id-course_code => status)
3000
     */
3001
    public static function get_courses_list_by_session($user_id, $session_id)
3002
    {
3003
        // Database Table Definitions
3004
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
3005
        $tableCourse = Database::get_main_table(TABLE_MAIN_COURSE);
3006
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
3007
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
3008
3009
        $user_id = intval($user_id);
3010
        $session_id = intval($session_id);
3011
        //we filter the courses from the URL
3012
        $join_access_url = $where_access_url = '';
3013
3014 View Code Duplication
        if (api_get_multiple_access_url()) {
3015
            $urlId = api_get_current_access_url_id();
3016
            if ($urlId != -1) {
3017
                $tbl_url_session = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
3018
                $join_access_url = " ,  $tbl_url_session url_rel_session ";
3019
                $where_access_url = " AND access_url_id = $urlId AND url_rel_session.session_id = $session_id ";
3020
            }
3021
        }
3022
3023
        /* This query is very similar to the query below, but it will check the
3024
        session_rel_course_user table if there are courses registered
3025
        to our user or not */
3026
        $sql = "SELECT DISTINCT
3027
                    c.visibility,
3028
                    c.id as real_id,                    
3029
                    sc.position
3030
                FROM $tbl_session_course_user as scu
3031
                INNER JOIN $tbl_session_course sc
3032
                ON (scu.session_id = sc.session_id AND scu.c_id = sc.c_id)
3033
                INNER JOIN $tableCourse as c
3034
                ON (scu.c_id = c.id)
3035
                $join_access_url
3036
                WHERE
3037
                    scu.user_id = $user_id AND
3038
                    scu.session_id = $session_id
3039
                    $where_access_url
3040
                ORDER BY sc.position ASC, c.id";
3041
3042
        $personal_course_list = array();
3043
        $courses = array();
3044
3045
        $result = Database::query($sql);
3046 View Code Duplication
        if (Database::num_rows($result) > 0) {
3047
            while ($result_row = Database::fetch_array($result, 'ASSOC')) {
3048
                $result_row['status'] = 5;
3049
                if (!in_array($result_row['real_id'], $courses)) {
3050
                    $personal_course_list[] = $result_row;
3051
                    $courses[] = $result_row['real_id'];
3052
                }
3053
            }
3054
        }
3055
3056
        if (api_is_allowed_to_create_course()) {
3057
            $sql = "SELECT DISTINCT
3058
                        c.visibility, 
3059
                        c.id as real_id,
3060
                        sc.position
3061
                    FROM $tbl_session_course_user as scu
3062
                    INNER JOIN $tbl_session as s
3063
                    ON (scu.session_id = s.id)
3064
                    INNER JOIN $tbl_session_course sc
3065
                    ON (scu.session_id = sc.session_id AND scu.c_id = sc.c_id)
3066
                    INNER JOIN $tableCourse as c
3067
                    ON (scu.c_id = c.id)
3068
                    $join_access_url
3069
                    WHERE
3070
                      s.id = $session_id AND
3071
                      (
3072
                        (scu.user_id = $user_id AND scu.status = 2) OR
3073
                        s.id_coach = $user_id
3074
                      )
3075
                    $where_access_url
3076
                    ORDER BY sc.position ASC";
3077
            $result = Database::query($sql);
3078
3079 View Code Duplication
            if (Database::num_rows($result) > 0) {
3080
                while ($result_row = Database::fetch_array($result, 'ASSOC')) {
3081
                    $result_row['status'] = 2;
3082
                    if (!in_array($result_row['real_id'], $courses)) {
3083
                        $personal_course_list[] = $result_row;
3084
                        $courses[] = $result_row['real_id'];
3085
                    }
3086
                }
3087
            }
3088
        }
3089
3090
        if (api_is_drh()) {
3091
            $sessionList = SessionManager::get_sessions_followed_by_drh($user_id);
3092
            $sessionList = array_keys($sessionList);
3093
            if (in_array($session_id, $sessionList)) {
3094
                $courseList = SessionManager::get_course_list_by_session_id($session_id);
3095 View Code Duplication
                if (!empty($courseList)) {
3096
                    foreach ($courseList as $course) {
0 ignored issues
show
Bug introduced by
The expression $courseList 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...
3097
                        if (!in_array($course['id'], $courses)) {
3098
                            $personal_course_list[] = $course;
3099
                        }
3100
                    }
3101
                }
3102
            }
3103
        } else {
3104
            //check if user is general coach for this session
3105
            $sessionInfo = api_get_session_info($session_id);
3106
            if ($sessionInfo['id_coach'] == $user_id) {
3107
                $courseList = SessionManager::get_course_list_by_session_id($session_id);
3108 View Code Duplication
                if (!empty($courseList)) {
3109
                    foreach ($courseList as $course) {
0 ignored issues
show
Bug introduced by
The expression $courseList 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...
3110
                        if (!in_array($course['id'], $courses)) {
3111
                            $personal_course_list[] = $course;
3112
                        }
3113
                    }
3114
                }
3115
            }
3116
        }
3117
3118
        return $personal_course_list;
3119
    }
3120
3121
    /**
3122
     * Get user id from a username
3123
     * @param    string    $username
3124
     * @return    int        User ID (or false if not found)
3125
     */
3126
    public static function get_user_id_from_username($username)
3127
    {
3128
        if (empty($username)) {
3129
3130
            return false;
3131
        }
3132
        $username = trim($username);
3133
        $username = Database::escape_string($username);
3134
        $t_user = Database::get_main_table(TABLE_MAIN_USER);
3135
        $sql = "SELECT id FROM $t_user WHERE username = '$username'";
3136
        $res = Database::query($sql);
3137
3138
        if ($res === false) {
3139
            return false;
3140
        }
3141
        if (Database::num_rows($res) !== 1) {
3142
            return false;
3143
        }
3144
        $row = Database::fetch_array($res);
3145
3146
        return $row['id'];
3147
    }
3148
3149
    /**
3150
     * Get the users files upload from his share_folder
3151
     * @param    string  $user_id   User ID
3152
     * @param   string  $course course directory
3153
     * @param   string  $resourcetype resourcetype: images, all
3154
     * @return    int        User ID (or false if not found)
3155
     */
3156
    public static function get_user_upload_files_by_course($user_id, $course, $resourcetype = 'all')
3157
    {
3158
        $return = '';
3159
        if (!empty($user_id) && !empty($course)) {
3160
            $user_id = intval($user_id);
3161
            $path = api_get_path(SYS_COURSE_PATH).$course.'/document/shared_folder/sf_user_'.$user_id.'/';
3162
            $web_path = api_get_path(WEB_COURSE_PATH).$course.'/document/shared_folder/sf_user_'.$user_id.'/';
3163
            $file_list = array();
3164
3165
            if (is_dir($path)) {
3166
                $handle = opendir($path);
3167
                while ($file = readdir($handle)) {
3168
                    if ($file == '.' || $file == '..' || $file == '.htaccess' || is_dir($path.$file)) {
3169
                        continue; // skip current/parent directory and .htaccess
3170
                    }
3171
                    $file_list[] = $file;
3172
                }
3173
                if (count($file_list) > 0) {
3174
                    $return = "<h4>$course</h4>";
3175
                    $return .= '<ul class="thumbnails">';
3176
                }
3177
                $extensionList = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'tif'];
3178
                foreach ($file_list as $file) {
3179
                    if ($resourcetype == "all") {
3180
                        $return .= '<li><a href="'.$web_path.urlencode($file).'" target="_blank">'.htmlentities($file).'</a></li>';
3181
                    } elseif ($resourcetype == "images") {
3182
                        //get extension
3183
                        $ext = explode('.', $file);
3184
                        if (isset($ext[1]) && in_array($ext[1], $extensionList)) {
3185
                            $return .= '<li class="span2">
3186
                                            <a class="thumbnail" href="'.$web_path.urlencode($file).'" target="_blank">
3187
                                                <img src="'.$web_path.urlencode($file).'" >
3188
                                            </a>
3189
                                        </li>';
3190
                        }
3191
                    }
3192
                }
3193
                if (count($file_list) > 0) {
3194
                    $return .= '</ul>';
3195
                }
3196
            }
3197
        }
3198
3199
        return $return;
3200
    }
3201
3202
    /**
3203
     * Gets the API key (or keys) and return them into an array
3204
     * @param   int     Optional user id (defaults to the result of api_get_user_id())
3205
     * @return  array   Non-indexed array containing the list of API keys for this user, or FALSE on error
3206
     */
3207
    public static function get_api_keys($user_id = null, $api_service = 'dokeos')
3208
    {
3209
        if ($user_id != strval(intval($user_id)))
3210
            return false;
3211
        if (empty($user_id)) {
3212
            $user_id = api_get_user_id();
3213
        }
3214
        if ($user_id === false)
3215
            return false;
3216
        $service_name = Database::escape_string($api_service);
3217
        if (is_string($service_name) === false) {
3218
            return false;
3219
        }
3220
        $t_api = Database::get_main_table(TABLE_MAIN_USER_API_KEY);
3221
        $sql = "SELECT * FROM $t_api WHERE user_id = $user_id AND api_service='$api_service';";
3222
        $res = Database::query($sql);
3223
        if ($res === false)
3224
            return false; //error during query
3225
        $num = Database::num_rows($res);
3226
        if ($num == 0)
3227
            return false;
3228
        $list = array();
3229
        while ($row = Database::fetch_array($res)) {
3230
            $list[$row['id']] = $row['api_key'];
3231
        }
3232
        return $list;
3233
    }
3234
3235
    /**
3236
     * Adds a new API key to the users' account
3237
     * @param   int     Optional user ID (defaults to the results of api_get_user_id())
3238
     * @return  boolean True on success, false on failure
3239
     */
3240
    public static function add_api_key($user_id = null, $api_service = 'dokeos')
3241
    {
3242
        if ($user_id != strval(intval($user_id)))
3243
            return false;
3244
        if (empty($user_id)) {
3245
            $user_id = api_get_user_id();
3246
        }
3247
        if ($user_id === false)
3248
            return false;
3249
        $service_name = Database::escape_string($api_service);
3250
        if (is_string($service_name) === false) {
3251
            return false;
3252
        }
3253
        $t_api = Database::get_main_table(TABLE_MAIN_USER_API_KEY);
3254
        $md5 = md5((time() + ($user_id * 5)) - rand(10000, 10000)); //generate some kind of random key
3255
        $sql = "INSERT INTO $t_api (user_id, api_key,api_service) VALUES ($user_id,'$md5','$service_name')";
3256
        $res = Database::query($sql);
3257
        if ($res === false)
3258
            return false; //error during query
3259
        $num = Database::insert_id();
3260
        return ($num == 0) ? false : $num;
3261
    }
3262
3263
    /**
3264
     * Deletes an API key from the user's account
3265
     * @param   int     API key's internal ID
3266
     * @return  boolean True on success, false on failure
3267
     */
3268
    public static function delete_api_key($key_id)
3269
    {
3270
        if ($key_id != strval(intval($key_id)))
3271
            return false;
3272
        if ($key_id === false)
3273
            return false;
3274
        $t_api = Database::get_main_table(TABLE_MAIN_USER_API_KEY);
3275
        $sql = "SELECT * FROM $t_api WHERE id = ".$key_id;
3276
        $res = Database::query($sql);
3277
        if ($res === false)
3278
            return false; //error during query
3279
        $num = Database::num_rows($res);
3280
        if ($num !== 1)
3281
            return false;
3282
        $sql = "DELETE FROM $t_api WHERE id = ".$key_id;
3283
        $res = Database::query($sql);
3284
        if ($res === false)
3285
            return false; //error during query
3286
        return true;
3287
    }
3288
3289
    /**
3290
     * Regenerate an API key from the user's account
3291
     * @param   int     user ID (defaults to the results of api_get_user_id())
3292
     * @param   string  API key's internal ID
3293
     * @return  int        num
3294
     */
3295
    public static function update_api_key($user_id, $api_service)
3296
    {
3297
        if ($user_id != strval(intval($user_id)))
3298
            return false;
3299
        if ($user_id === false)
3300
            return false;
3301
        $service_name = Database::escape_string($api_service);
3302
        if (is_string($service_name) === false) {
3303
            return false;
3304
        }
3305
        $t_api = Database::get_main_table(TABLE_MAIN_USER_API_KEY);
3306
        $sql = "SELECT id FROM $t_api WHERE user_id=".$user_id." AND api_service='".$api_service."'";
3307
        $res = Database::query($sql);
3308
        $num = Database::num_rows($res);
3309
        if ($num == 1) {
3310
            $id_key = Database::fetch_array($res, 'ASSOC');
3311
            self::delete_api_key($id_key['id']);
3312
            $num = self::add_api_key($user_id, $api_service);
3313
        } elseif ($num == 0) {
3314
            $num = self::add_api_key($user_id, $api_service);
3315
        }
3316
        return $num;
3317
    }
3318
3319
    /**
3320
     * @param   int     user ID (defaults to the results of api_get_user_id())
3321
     * @param   string    API key's internal ID
3322
     * @return  int    row ID, or return false if not found
3323
     */
3324
    public static function get_api_key_id($user_id, $api_service)
3325
    {
3326
        if ($user_id != strval(intval($user_id)))
3327
            return false;
3328
        if ($user_id === false)
3329
            return false;
3330
        if (empty($api_service))
3331
            return false;
3332
        $t_api = Database::get_main_table(TABLE_MAIN_USER_API_KEY);
3333
        $api_service = Database::escape_string($api_service);
3334
        $sql = "SELECT id FROM $t_api WHERE user_id=".$user_id." AND api_service='".$api_service."'";
3335
        $res = Database::query($sql);
3336
        if (Database::num_rows($res) < 1) {
3337
            return false;
3338
        }
3339
        $row = Database::fetch_array($res, 'ASSOC');
3340
        return $row['id'];
3341
    }
3342
3343
    /**
3344
     * Checks if a user_id is platform admin
3345
     * @param   int user ID
3346
     * @return  boolean True if is admin, false otherwise
3347
     * @see main_api.lib.php::api_is_platform_admin() for a context-based check
3348
     */
3349
    public static function is_admin($user_id)
3350
    {
3351
        if (empty($user_id) or $user_id != strval(intval($user_id))) {
3352
            return false;
3353
        }
3354
        $admin_table = Database::get_main_table(TABLE_MAIN_ADMIN);
3355
        $sql = "SELECT * FROM $admin_table WHERE user_id = $user_id";
3356
        $res = Database::query($sql);
3357
3358
        return Database::num_rows($res) === 1;
3359
    }
3360
3361
    /**
3362
     * Get the total count of users
3363
     * @param   int     Status of users to be counted
3364
     * @param   int     Access URL ID (optional)
3365
     * @return    mixed    Number of users or false on error
3366
     */
3367
    public static function get_number_of_users($status = 0, $access_url_id = null)
3368
    {
3369
        $t_u = Database::get_main_table(TABLE_MAIN_USER);
3370
        $t_a = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
3371
        $sql = "SELECT count(*) FROM $t_u u";
3372
        $sql2 = '';
3373
        if (is_int($status) && $status > 0) {
3374
            $sql2 .= " WHERE u.status = $status ";
3375
        }
3376
        if (!empty($access_url_id) && $access_url_id == intval($access_url_id)) {
3377
            $sql .= ", $t_a a ";
3378
            $sql2 .= " AND a.access_url_id = $access_url_id AND u.id = a.user_id ";
3379
        }
3380
        $sql = $sql.$sql2;
3381
        $res = Database::query($sql);
3382
        if (Database::num_rows($res) === 1) {
3383
            return (int) Database::result($res, 0, 0);
3384
        }
3385
        return false;
3386
    }
3387
3388
    /**
3389
     * @author Isaac flores <[email protected]>
3390
     * @param string The email administrator
3391
     * @param integer The user id
3392
     * @param string The message title
3393
     * @param string The content message
3394
     */
3395
    public static function send_message_in_outbox($email_administrator, $user_id, $title, $content)
3396
    {
3397
        $table_message = Database::get_main_table(TABLE_MESSAGE);
3398
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
3399
        $title = api_utf8_decode($title);
3400
        $content = api_utf8_decode($content);
3401
        $email_administrator = Database::escape_string($email_administrator);
3402
        //message in inbox
3403
        $sql_message_outbox = 'SELECT id from '.$table_user.' WHERE email="'.$email_administrator.'" ';
3404
        //$num_row_query = Database::num_rows($sql_message_outbox);
3405
        $res_message_outbox = Database::query($sql_message_outbox);
3406
        $array_users_administrator = array();
3407
        while ($row_message_outbox = Database::fetch_array($res_message_outbox, 'ASSOC')) {
3408
            $array_users_administrator[] = $row_message_outbox['id'];
3409
        }
3410
        //allow to insert messages in outbox
3411
        for ($i = 0; $i < count($array_users_administrator); $i++) {
3412
            $sql_insert_outbox = "INSERT INTO $table_message(user_sender_id, user_receiver_id, msg_status, send_date, title, content ) ".
3413
                " VALUES (".
3414
                "'".(int) $user_id."', '".(int) ($array_users_administrator[$i])."', '4', '".api_get_utc_datetime()."','".Database::escape_string($title)."','".Database::escape_string($content)."'".
3415
                ")";
3416
            Database::query($sql_insert_outbox);
3417
        }
3418
    }
3419
3420
    /**
3421
     *
3422
     * Gets the tags of a specific field_id
3423
     * USER TAGS
3424
     *
3425
     * Instructions to create a new user tag by Julio Montoya <[email protected]>
3426
     *
3427
     * 1. Create a new extra field in main/admin/user_fields.php with the "TAG" field type make it available and visible.
3428
     *    Called it "books" for example.
3429
     * 2. Go to profile main/auth/profile.php There you will see a special input (facebook style) that will show suggestions of tags.
3430
     * 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
3431
     * 4. Tags are independent this means that tags can't be shared between tags + book + hobbies.
3432
     * 5. Test and enjoy.
3433
     *
3434
     * @param string $tag
3435
     * @param int $field_id field_id
3436
     * @param string $return_format how we are going to result value in array or in a string (json)
3437
     * @param $limit
3438
     *
3439
     * @return mixed
3440
     *
3441
     */
3442
    public static function get_tags($tag, $field_id, $return_format = 'json', $limit = 10)
3443
    {
3444
        // database table definition
3445
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3446
        $field_id = intval($field_id);
3447
        $limit = intval($limit);
3448
        $tag = trim(Database::escape_string($tag));
3449
3450
        // all the information of the field
3451
        $sql = "SELECT DISTINCT id, tag from $table_user_tag
3452
                WHERE field_id = $field_id AND tag LIKE '$tag%' ORDER BY tag LIMIT $limit";
3453
        $result = Database::query($sql);
3454
        $return = array();
3455 View Code Duplication
        if (Database::num_rows($result) > 0) {
3456
            while ($row = Database::fetch_array($result, 'ASSOC')) {
3457
                $return[] = array('key' => $row['tag'], 'value' => $row['tag']);
3458
            }
3459
        }
3460
        if ($return_format === 'json') {
3461
            $return = json_encode($return);
3462
        }
3463
3464
        return $return;
3465
    }
3466
3467
    /**
3468
     * @param int $field_id
3469
     * @param int $limit
3470
     *
3471
     * @return array
3472
     */
3473
    public static function get_top_tags($field_id, $limit = 100)
3474
    {
3475
        // database table definition
3476
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3477
        $table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
3478
        $field_id = intval($field_id);
3479
        $limit = intval($limit);
3480
        // all the information of the field
3481
        $sql = "SELECT count(*) count, tag FROM $table_user_tag_values  uv
3482
                INNER JOIN $table_user_tag ut
3483
                ON(ut.id = uv.tag_id)
3484
                WHERE field_id = $field_id
3485
                GROUP BY tag_id
3486
                ORDER BY count DESC
3487
                LIMIT $limit";
3488
        $result = Database::query($sql);
3489
        $return = array();
3490
        if (Database::num_rows($result) > 0) {
3491
            while ($row = Database::fetch_array($result, 'ASSOC')) {
3492
                $return[] = $row;
3493
            }
3494
        }
3495
        return $return;
3496
    }
3497
3498
    /**
3499
     * Get user's tags
3500
     * @param int $user_id
3501
     * @param int $field_id
3502
     *
3503
     * @return array
3504
     */
3505
    public static function get_user_tags($user_id, $field_id)
3506
    {
3507
        // database table definition
3508
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3509
        $table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
3510
        $field_id = intval($field_id);
3511
        $user_id = intval($user_id);
3512
3513
        // all the information of the field
3514
        $sql = "SELECT ut.id, tag, count
3515
                FROM $table_user_tag ut
3516
                INNER JOIN $table_user_tag_values uv
3517
                ON (uv.tag_id=ut.ID)
3518
                WHERE field_id = $field_id AND user_id = $user_id
3519
                ORDER BY tag";
3520
        $result = Database::query($sql);
3521
        $return = array();
3522 View Code Duplication
        if (Database::num_rows($result) > 0) {
3523
            while ($row = Database::fetch_array($result, 'ASSOC')) {
3524
                $return[$row['id']] = array('tag' => $row['tag'], 'count' => $row['count']);
3525
            }
3526
        }
3527
3528
        return $return;
3529
    }
3530
3531
    /**
3532
     * Get user's tags
3533
     * @param int $user_id
3534
     * @param int $field_id
3535
     * @param bool $show_links show links or not
3536
     *
3537
     * @return array
3538
     */
3539
    public static function get_user_tags_to_string($user_id, $field_id, $show_links = true)
3540
    {
3541
        // database table definition
3542
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3543
        $table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
3544
        $field_id = intval($field_id);
3545
        $user_id = intval($user_id);
3546
3547
        // all the information of the field
3548
        $sql = "SELECT ut.id, tag,count FROM $table_user_tag ut
3549
                INNER JOIN $table_user_tag_values uv
3550
                ON (uv.tag_id = ut.id)
3551
                WHERE field_id = $field_id AND user_id = $user_id
3552
                ORDER BY tag";
3553
3554
        $result = Database::query($sql);
3555
        $return = array();
3556 View Code Duplication
        if (Database::num_rows($result) > 0) {
3557
            while ($row = Database::fetch_array($result, 'ASSOC')) {
3558
                $return[$row['id']] = array('tag' => $row['tag'], 'count' => $row['count']);
3559
            }
3560
        }
3561
        $user_tags = $return;
3562
        $tag_tmp = array();
3563
        foreach ($user_tags as $tag) {
3564
            if ($show_links) {
3565
                $tag_tmp[] = '<a href="'.api_get_path(WEB_PATH).'main/search/index.php?q='.$tag['tag'].'">'.$tag['tag'].'</a>';
3566
            } else {
3567
                $tag_tmp[] = $tag['tag'];
3568
            }
3569
        }
3570
3571
        if (is_array($user_tags) && count($user_tags) > 0) {
3572
            $return = implode(', ', $tag_tmp);
3573
        } else {
3574
3575
            return '';
3576
        }
3577
3578
        return $return;
3579
    }
3580
3581
    /**
3582
     * Get the tag id
3583
     * @param int $tag
3584
     * @param int $field_id
3585
     * @return int returns 0 if fails otherwise the tag id
3586
     */
3587
    public static function get_tag_id($tag, $field_id)
3588
    {
3589
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3590
        $tag = Database::escape_string($tag);
3591
        $field_id = intval($field_id);
3592
        //with COLLATE latin1_bin to select query in a case sensitive mode
3593
        $sql = "SELECT id FROM $table_user_tag
3594
                WHERE tag LIKE '$tag' AND field_id = $field_id";
3595
        $result = Database::query($sql);
3596
        if (Database::num_rows($result) > 0) {
3597
            $row = Database::fetch_array($result, 'ASSOC');
3598
3599
            return $row['id'];
3600
        } else {
3601
3602
            return 0;
3603
        }
3604
    }
3605
3606
    /**
3607
     * Get the tag id
3608
     * @param int $tag_id
3609
     * @param int $field_id
3610
     *
3611
     * @return int 0 if fails otherwise the tag id
3612
     */
3613 View Code Duplication
    public static function get_tag_id_from_id($tag_id, $field_id)
3614
    {
3615
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3616
        $tag_id = intval($tag_id);
3617
        $field_id = intval($field_id);
3618
        $sql = "SELECT id FROM $table_user_tag
3619
                WHERE id = '$tag_id' AND field_id = $field_id";
3620
        $result = Database::query($sql);
3621
        if (Database::num_rows($result) > 0) {
3622
            $row = Database::fetch_array($result, 'ASSOC');
3623
            return $row['id'];
3624
        } else {
3625
            return false;
3626
        }
3627
    }
3628
3629
    /**
3630
     * Adds a user-tag value
3631
     * @param mixed $tag
3632
     * @param int $user_id
3633
     * @param int $field_id field id of the tag
3634
     * @return bool
3635
     */
3636
    public static function add_tag($tag, $user_id, $field_id)
3637
    {
3638
        // database table definition
3639
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3640
        $table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
3641
        $tag = trim(Database::escape_string($tag));
3642
        $user_id = intval($user_id);
3643
        $field_id = intval($field_id);
3644
3645
        $tag_id = UserManager::get_tag_id($tag, $field_id);
3646
3647
        /* IMPORTANT
3648
         *  @todo we don't create tags with numbers
3649
         *
3650
         */
3651
        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...
3652
            //the form is sending an id this means that the user select it from the list so it MUST exists
3653
            /* $new_tag_id = UserManager::get_tag_id_from_id($tag,$field_id);
3654
              if ($new_tag_id !== false) {
3655
              $sql = "UPDATE $table_user_tag SET count = count + 1 WHERE id  = $new_tag_id";
3656
              $result = Database::query($sql);
3657
              $last_insert_id = $new_tag_id;
3658
              } else {
3659
              $sql = "INSERT INTO $table_user_tag (tag, field_id,count) VALUES ('$tag','$field_id', count + 1)";
3660
              $result = Database::query($sql);
3661
              $last_insert_id = Database::insert_id();
3662
              } */
3663
        }
3664
3665
        //this is a new tag
3666
        if ($tag_id == 0) {
3667
            //the tag doesn't exist
3668
            $sql = "INSERT INTO $table_user_tag (tag, field_id,count) VALUES ('$tag','$field_id', count + 1)";
3669
             Database::query($sql);
3670
            $last_insert_id = Database::insert_id();
3671
        } else {
3672
            //the tag exists we update it
3673
            $sql = "UPDATE $table_user_tag SET count = count + 1 WHERE id  = $tag_id";
3674
             Database::query($sql);
3675
            $last_insert_id = $tag_id;
3676
        }
3677
3678
        if (!empty($last_insert_id) && ($last_insert_id != 0)) {
3679
            //we insert the relationship user-tag
3680
            $sql = "SELECT tag_id FROM $table_user_tag_values
3681
                    WHERE user_id = $user_id AND tag_id = $last_insert_id ";
3682
            $result = Database::query($sql);
3683
            //if the relationship does not exist we create it
3684
            if (Database::num_rows($result) == 0) {
3685
                $sql = "INSERT INTO $table_user_tag_values SET user_id = $user_id, tag_id = $last_insert_id";
3686
                Database::query($sql);
3687
            }
3688
        }
3689
    }
3690
3691
    /**
3692
     * Deletes an user tag
3693
     * @param int $user_id
3694
     * @param int $field_id
3695
     *
3696
     */
3697
    public static function delete_user_tags($user_id, $field_id)
3698
    {
3699
        // database table definition
3700
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3701
        $table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
3702
        $tags = UserManager::get_user_tags($user_id, $field_id);
3703
        if (is_array($tags) && count($tags) > 0) {
3704
            foreach ($tags as $key => $tag) {
3705
                if ($tag['count'] > '0') {
3706
                    $sql = "UPDATE $table_user_tag SET count = count - 1  WHERE id = $key ";
3707
                    Database::query($sql);
3708
                }
3709
                $sql = "DELETE FROM $table_user_tag_values
3710
                        WHERE user_id = $user_id AND tag_id = $key";
3711
                Database::query($sql);
3712
            }
3713
        }
3714
    }
3715
3716
    /**
3717
     * Process the tag list comes from the UserManager::update_extra_field_value() function
3718
     * @param array $tags the tag list that will be added
3719
     * @param int $user_id
3720
     * @param int $field_id
3721
     *
3722
     * @return bool
3723
     */
3724
    public static function process_tags($tags, $user_id, $field_id)
3725
    {
3726
        // We loop the tags and add it to the DB
3727
        if (is_array($tags)) {
3728
            foreach ($tags as $tag) {
3729
                UserManager::add_tag($tag, $user_id, $field_id);
3730
            }
3731
        } else {
3732
            UserManager::add_tag($tags, $user_id, $field_id);
3733
        }
3734
3735
        return true;
3736
    }
3737
3738
    /**
3739
     * Returns a list of all administrators
3740
     *
3741
     * @return array
3742
     */
3743
    public static function get_all_administrators()
3744
    {
3745
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
3746
        $table_admin = Database::get_main_table(TABLE_MAIN_ADMIN);
3747
        $tbl_url_rel_user = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
3748
        $access_url_id = api_get_current_access_url_id();
3749
        if (api_get_multiple_access_url()) {
3750
            $sql = "SELECT admin.user_id, username, firstname, lastname, email, active
3751
                    FROM $tbl_url_rel_user as url
3752
                    INNER JOIN $table_admin as admin
3753
                    ON (admin.user_id=url.user_id)
3754
                    INNER JOIN $table_user u
3755
                    ON (u.id=admin.user_id)
3756
                    WHERE access_url_id ='".$access_url_id."'";
3757
        } else {
3758
            $sql = "SELECT admin.user_id, username, firstname, lastname, email, active
3759
                    FROM $table_admin as admin
3760
                    INNER JOIN $table_user u
3761
                    ON (u.id=admin.user_id)";
3762
        }
3763
        $result = Database::query($sql);
3764
        $return = array();
3765
        if (Database::num_rows($result) > 0) {
3766
            while ($row = Database::fetch_array($result, 'ASSOC')) {
3767
                $return[$row['user_id']] = $row;
3768
            }
3769
        }
3770
3771
        return $return;
3772
    }
3773
3774
    /**
3775
     * Search an user (tags, first name, last name and email )
3776
     * @param string $tag
3777
     * @param int $field_id field id of the tag
3778
     * @param int $from where to start in the query
3779
     * @param int $number_of_items
3780
     * @param bool $getCount get count or not
3781
     * @return array
3782
     */
3783
    public static function get_all_user_tags(
3784
        $tag,
3785
        $field_id = 0,
3786
        $from = 0,
3787
        $number_of_items = 10,
3788
        $getCount = false
3789
    ) {
3790
        $user_table = Database::get_main_table(TABLE_MAIN_USER);
3791
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3792
        $table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
3793
        $access_url_rel_user_table = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
3794
3795
        $field_id = intval($field_id);
3796
        $from = intval($from);
3797
        $number_of_items = intval($number_of_items);
3798
3799
        $where_field = "";
3800
        $where_extra_fields = UserManager::get_search_form_where_extra_fields();
3801
        if ($field_id != 0) {
3802
            $where_field = " field_id = $field_id AND ";
3803
        }
3804
3805
        // all the information of the field
3806
3807
        if ($getCount) {
3808
            $select = "SELECT count(DISTINCT u.id) count";
3809
        } else {
3810
            $select = "SELECT DISTINCT u.id, u.username, firstname, lastname, email, tag, picture_uri";
3811
        }
3812
3813
        $sql = " $select
3814
                FROM $user_table u
3815
                INNER JOIN $access_url_rel_user_table url_rel_user
3816
                ON (u.id = url_rel_user.user_id)
3817
                LEFT JOIN $table_user_tag_values uv
3818
                ON (u.id AND uv.user_id AND uv.user_id = url_rel_user.user_id)
3819
                LEFT JOIN $table_user_tag ut ON (uv.tag_id = ut.id)
3820
                WHERE
3821
                    ($where_field tag LIKE '".Database::escape_string($tag."%")."') OR
3822
                    (
3823
                        u.firstname LIKE '".Database::escape_string("%".$tag."%")."' OR
3824
                        u.lastname LIKE '".Database::escape_string("%".$tag."%")."' OR
3825
                        u.username LIKE '".Database::escape_string("%".$tag."%")."' OR
3826
                        concat(u.firstname, ' ', u.lastname) LIKE '".Database::escape_string("%".$tag."%")."' OR
3827
                        concat(u.lastname, ' ', u.firstname) LIKE '".Database::escape_string("%".$tag."%")."'
3828
                     )
3829
                     ".(!empty($where_extra_fields) ? $where_extra_fields : '')."
3830
                     AND url_rel_user.access_url_id=".api_get_current_access_url_id();
3831
3832
        $keyword_active = true;
3833
        // only active users
3834
        if ($keyword_active) {
3835
            $sql .= " AND u.active='1'";
3836
        }
3837
        // avoid anonymous
3838
        $sql .= " AND u.status <> 6 ";
3839
        $sql .= " ORDER BY username";
3840
        $sql .= " LIMIT $from , $number_of_items";
3841
3842
        $result = Database::query($sql);
3843
        $return = array();
3844
3845
        if (Database::num_rows($result) > 0) {
3846
            if ($getCount) {
3847
                $row = Database::fetch_array($result, 'ASSOC');
3848
                return $row['count'];
3849
            }
3850
            while ($row = Database::fetch_array($result, 'ASSOC')) {
3851
                if (isset($return[$row['id']]) &&
3852
                    !empty($return[$row['id']]['tag'])
3853
                ) {
3854
                    $url = Display::url(
3855
                        $row['tag'],
3856
                        api_get_path(WEB_PATH).'main/social/search.php?q='.$row['tag'],
3857
                        array('class' => 'tag')
3858
                    );
3859
                    $row['tag'] = $url;
3860
                }
3861
                $return[$row['id']] = $row;
3862
            }
3863
        }
3864
3865
        return $return;
3866
    }
3867
3868
    /**
3869
      * Get extra filtrable user fields (only type select)
3870
      * @return array
3871
      */
3872
    public static function get_extra_filtrable_fields()
3873
    {
3874
        $extraFieldList = UserManager::get_extra_fields();
3875
3876
        $extraFiltrableFields = array();
3877 View Code Duplication
        if (is_array($extraFieldList)) {
3878
            foreach ($extraFieldList as $extraField) {
3879
                // If is enabled to filter and is a "<select>" field type
3880
                if ($extraField[8] == 1 && $extraField[2] == 4) {
3881
                    $extraFiltrableFields[] = array(
3882
                        'name' => $extraField[3],
3883
                        'variable' => $extraField[1],
3884
                        'data' => $extraField[9]
3885
                    );
3886
                }
3887
            }
3888
        }
3889
3890
        if (is_array($extraFiltrableFields) && count($extraFiltrableFields) > 0) {
3891
            return $extraFiltrableFields;
3892
        }
3893
    }
3894
3895
    /**
3896
      * Get extra where clauses for finding users based on extra filtrable user fields (type select)
3897
      * @return string With AND clauses based on user's ID which have the values to search in extra user fields
3898
      */
3899
    public static function get_search_form_where_extra_fields()
3900
    {
3901
        $useExtraFields = false;
3902
        $extraFields = UserManager::get_extra_filtrable_fields();
3903
        $extraFieldResult = array();
3904 View Code Duplication
        if (is_array($extraFields) && count($extraFields)>0 ) {
3905
            foreach ($extraFields as $extraField) {
3906
                $varName = 'field_'.$extraField['variable'];
3907
                if (UserManager::is_extra_field_available($extraField['variable'])) {
3908
                    if (isset($_GET[$varName]) && $_GET[$varName]!='0') {
3909
                        $useExtraFields = true;
3910
                        $extraFieldResult[]= UserManager::get_extra_user_data_by_value(
3911
                            $extraField['variable'],
3912
                            $_GET[$varName]
3913
                        );
3914
                    }
3915
                }
3916
            }
3917
        }
3918
3919
        if ($useExtraFields) {
3920
            $finalResult = array();
3921
            if (count($extraFieldResult)>1) {
3922
                for ($i=0; $i < count($extraFieldResult) -1; $i++) {
3923
                if (is_array($extraFieldResult[$i]) && is_array($extraFieldResult[$i+1])) {
3924
                        $finalResult  = array_intersect($extraFieldResult[$i], $extraFieldResult[$i+1]);
3925
                    }
3926
                }
3927
            } else {
3928
                $finalResult = $extraFieldResult[0];
3929
            }
3930
3931
            if (is_array($finalResult) && count($finalResult)>0) {
3932
                $whereFilter = " AND u.id IN  ('".implode("','", $finalResult)."') ";
3933
            } else {
3934
                //no results
3935
                $whereFilter = " AND u.id  = -1 ";
3936
            }
3937
3938
            return $whereFilter;
3939
        }
3940
    }
3941
3942
    /**
3943
     * Show the search form
3944
     * @param string $query the value of the search box
3945
     * @return string HTML form
3946
     */
3947
    public static function get_search_form($query, $defaultParams = [])
3948
    {
3949
        $searchType = isset($_GET['search_type']) ? $_GET['search_type'] : null;
3950
        $form = new FormValidator(
3951
            'search_user',
3952
            'get',
3953
            api_get_path(WEB_PATH).'main/social/search.php',
3954
            '',
3955
            array(),
3956
            FormValidator::LAYOUT_HORIZONTAL
3957
        );
3958
3959
        $form->addText('q', get_lang('UsersGroups'), false);
3960
        $options = array(
3961
            0 => get_lang('Select'),
3962
            1 => get_lang('User'),
3963
            2 => get_lang('Group'),
3964
        );
3965
        $form->addSelect(
3966
            'search_type',
3967
            get_lang('Type'),
3968
            $options,
3969
            array('onchange' => 'javascript: extra_field_toogle();')
3970
        );
3971
3972
        // Extra fields
3973
3974
        $extraFields = UserManager::get_extra_filtrable_fields();
3975
        $defaults = [];
3976
        if (is_array($extraFields) && count($extraFields) > 0) {
3977
            foreach ($extraFields as $extraField) {
3978
                $varName = 'field_'.$extraField['variable'];
3979
3980
                $options = [
3981
                    0 => get_lang('Select')
3982
                ];
3983
                foreach ($extraField['data'] as $option) {
3984
                    $checked = '';
3985
                    if (isset($_GET[$varName])) {
3986
                        if ($_GET[$varName] == $option[1]) {
3987
                            $defaults[$option[1]] = true;
3988
                        }
3989
                    }
3990
3991
                    $options[$option[1]] = $option[1];
3992
                }
3993
                $form->addSelect($varName, $extraField['name'], $options);
3994
            }
3995
        }
3996
3997
        $defaults['search_type'] = intval($searchType);
3998
        $defaults['q'] = api_htmlentities(Security::remove_XSS($query));
3999
4000
        if (!empty($defaultParams)) {
4001
            $defaults = array_merge($defaults, $defaultParams);
4002
        }
4003
        $form->setDefaults($defaults);
4004
4005
        $form->addButtonSearch(get_lang('Search'));
4006
4007
        $js = '<script>
4008
        extra_field_toogle();
4009
        function extra_field_toogle() {
4010
            if (jQuery("select[name=search_type]").val() != "1") { jQuery(".extra_field").hide(); } else { jQuery(".extra_field").show(); }
4011
        }
4012
        </script>';
4013
4014
        return $js.$form->returnForm();
4015
    }
4016
4017
    /**
4018
     * Shows the user menu
4019
     */
4020
    public static function show_menu()
4021
    {
4022
        echo '<div class="actions">';
4023
        echo '<a href="/main/auth/profile.php">'.Display::return_icon('profile.png').' '.get_lang('PersonalData').'</a>';
4024
        echo '<a href="/main/messages/inbox.php">'.Display::return_icon('inbox.png').' '.get_lang('Inbox').'</a>';
4025
        echo '<a href="/main/messages/outbox.php">'.Display::return_icon('outbox.png').' '.get_lang('Outbox').'</a>';
4026
        echo '<span style="float:right; padding-top:7px;">'.
4027
        '<a href="/main/auth/profile.php?show=1">'.Display::return_icon('edit.gif').' '.get_lang('Configuration').'</a>';
4028
        '</span>';
4029
        echo '</div>';
4030
    }
4031
4032
    /**
4033
     * Allow to register contact to social network
4034
     * @param int $friend_id user friend id
4035
     * @param int $my_user_id user id
4036
     * @param int $relation_type relation between users see constants definition
4037
     */
4038
    public static function relate_users($friend_id, $my_user_id, $relation_type)
4039
    {
4040
        $tbl_my_friend = Database :: get_main_table(TABLE_MAIN_USER_REL_USER);
4041
4042
        $friend_id = intval($friend_id);
4043
        $my_user_id = intval($my_user_id);
4044
        $relation_type = intval($relation_type);
4045
4046
        $sql = 'SELECT COUNT(*) as count FROM '.$tbl_my_friend.'
4047
                WHERE
4048
                    friend_user_id='.$friend_id.' AND
4049
                    user_id='.$my_user_id.' AND
4050
                    relation_type <> '.USER_RELATION_TYPE_RRHH.' ';
4051
        $result = Database::query($sql);
4052
        $row = Database :: fetch_array($result, 'ASSOC');
4053
        $current_date = api_get_utc_datetime();
4054
4055
        if ($row['count'] == 0) {
4056
            $sql = 'INSERT INTO '.$tbl_my_friend.'(friend_user_id,user_id,relation_type,last_edit)
4057
                    VALUES ('.$friend_id.','.$my_user_id.','.$relation_type.',"'.$current_date.'")';
4058
            Database::query($sql);
4059
            return true;
4060
        }
4061
4062
        $sql = 'SELECT COUNT(*) as count, relation_type  FROM '.$tbl_my_friend.'
4063
                WHERE
4064
                    friend_user_id='.$friend_id.' AND
4065
                    user_id='.$my_user_id.' AND
4066
                    relation_type <> '.USER_RELATION_TYPE_RRHH.' ';
4067
        $result = Database::query($sql);
4068
        $row = Database :: fetch_array($result, 'ASSOC');
4069
4070
        if ($row['count'] == 1) {
4071
            //only for the case of a RRHH
4072
            if ($row['relation_type'] != $relation_type && $relation_type == USER_RELATION_TYPE_RRHH) {
4073
                $sql = 'INSERT INTO '.$tbl_my_friend.'(friend_user_id,user_id,relation_type,last_edit)
4074
                        VALUES ('.$friend_id.','.$my_user_id.','.$relation_type.',"'.$current_date.'")';
4075
            } else {
4076
                $sql = 'UPDATE '.$tbl_my_friend.' SET relation_type='.$relation_type.'
4077
                        WHERE friend_user_id='.$friend_id.' AND user_id='.$my_user_id;
4078
            }
4079
            Database::query($sql);
4080
4081
            return true;
4082
        }
4083
4084
        return false;
4085
    }
4086
4087
    /**
4088
     * Deletes a contact
4089
     * @param int user friend id
4090
     * @param bool true will delete ALL friends relationship from $friend_id
4091
     * @author isaac flores paz <[email protected]>
4092
     * @author Julio Montoya <[email protected]> Cleaning code
4093
     */
4094
    public static function remove_user_rel_user($friend_id, $real_removed = false, $with_status_condition = '')
4095
    {
4096
        $tbl_my_friend = Database :: get_main_table(TABLE_MAIN_USER_REL_USER);
4097
        $tbl_my_message = Database :: get_main_table(TABLE_MESSAGE);
4098
        $friend_id = intval($friend_id);
4099
4100
        if ($real_removed) {
4101
            $extra_condition = '';
4102
            if ($with_status_condition != '') {
4103
                $extra_condition = ' AND relation_type = '.intval($with_status_condition);
4104
            }
4105
            $sql = 'DELETE FROM '.$tbl_my_friend.'
4106
                    WHERE relation_type <> '.USER_RELATION_TYPE_RRHH.' AND friend_user_id='.$friend_id.' '.$extra_condition;
4107
            Database::query($sql);
4108
            $sql= 'DELETE FROM '.$tbl_my_friend.'
4109
                   WHERE relation_type <> '.USER_RELATION_TYPE_RRHH.' AND user_id='.$friend_id.' '.$extra_condition;
4110
            Database::query($sql);
4111
        } else {
4112
            $user_id = api_get_user_id();
4113
            $sql = 'SELECT COUNT(*) as count FROM '.$tbl_my_friend.'
4114
                    WHERE
4115
                        user_id='.$user_id.' AND
4116
                        relation_type NOT IN('.USER_RELATION_TYPE_DELETED.', '.USER_RELATION_TYPE_RRHH.') AND
4117
                        friend_user_id='.$friend_id;
4118
            $result = Database::query($sql);
4119
            $row = Database :: fetch_array($result, 'ASSOC');
4120
            if ($row['count'] == 1) {
4121
                //Delete user rel user
4122
                $sql_i = 'UPDATE '.$tbl_my_friend.' SET relation_type='.USER_RELATION_TYPE_DELETED.'
4123
                          WHERE user_id='.$user_id.' AND friend_user_id='.$friend_id;
4124
                $sql_j = 'UPDATE '.$tbl_my_message.' SET msg_status='.MESSAGE_STATUS_INVITATION_DENIED.'
4125
                          WHERE user_receiver_id='.$user_id.' AND user_sender_id='.$friend_id.' AND update_date="0000-00-00 00:00:00" ';
4126
                //Delete user
4127
                $sql_ij = 'UPDATE '.$tbl_my_friend.'  SET relation_type='.USER_RELATION_TYPE_DELETED.'
4128
                           WHERE user_id='.$friend_id.' AND friend_user_id='.$user_id;
4129
                $sql_ji = 'UPDATE '.$tbl_my_message.' SET msg_status='.MESSAGE_STATUS_INVITATION_DENIED.'
4130
                           WHERE user_receiver_id='.$friend_id.' AND user_sender_id='.$user_id.' AND update_date="0000-00-00 00:00:00" ';
4131
                Database::query($sql_i);
4132
                Database::query($sql_j);
4133
                Database::query($sql_ij);
4134
                Database::query($sql_ji);
4135
            }
4136
        }
4137
    }
4138
4139
    /**
4140
     * @param int $userId
4141
     * @return array
4142
     */
4143
    public static function getDrhListFromUser($userId)
4144
    {
4145
        $tblUser = Database::get_main_table(TABLE_MAIN_USER);
4146
        $tblUserRelUser = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
4147
        $tblUserRelAccessUrl = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
4148
        $userId = intval($userId);
4149
4150
        $orderBy = null;
4151
        if (api_is_western_name_order()) {
4152
            $orderBy .= " ORDER BY firstname, lastname ";
4153
        } else {
4154
            $orderBy .= " ORDER BY lastname, firstname ";
4155
        }
4156
4157
        $sql = "SELECT u.id, username, u.firstname, u.lastname
4158
                FROM $tblUser u
4159
                INNER JOIN $tblUserRelUser uru ON (uru.friend_user_id = u.id)
4160
                INNER JOIN $tblUserRelAccessUrl a ON (a.user_id = u.id)
4161
                WHERE
4162
                    access_url_id = ".api_get_current_access_url_id()." AND
4163
                    uru.user_id = '$userId' AND
4164
                    relation_type = '".USER_RELATION_TYPE_RRHH."'
4165
                $orderBy
4166
                ";
4167
        $result = Database::query($sql);
4168
4169
        return Database::store_result($result);
4170
    }
4171
4172
    /**
4173
     * get users followed by human resource manager
4174
     * @param int $userId
4175
     * @param int $userStatus (STUDENT, COURSEMANAGER, etc)
4176
     * @param bool $getOnlyUserId
4177
     * @param bool $getSql
4178
     * @param bool $getCount
4179
     * @param int $from
4180
     * @param int $numberItems
4181
     * @param int $column
4182
     * @param string $direction
4183
     * @param int $active
4184
     * @param string $lastConnectionDate
4185
     * @return array     users
4186
     */
4187 View Code Duplication
    public static function get_users_followed_by_drh(
4188
        $userId,
4189
        $userStatus = 0,
4190
        $getOnlyUserId = false,
4191
        $getSql = false,
4192
        $getCount = false,
4193
        $from = null,
4194
        $numberItems = null,
4195
        $column = null,
4196
        $direction = null,
4197
        $active = null,
4198
        $lastConnectionDate = null
4199
    ) {
4200
        return self::getUsersFollowedByUser(
4201
            $userId,
4202
            $userStatus,
4203
            $getOnlyUserId,
4204
            $getSql,
4205
            $getCount,
4206
            $from,
4207
            $numberItems,
4208
            $column,
4209
            $direction,
4210
            $active,
4211
            $lastConnectionDate,
4212
            DRH
4213
        );
4214
    }
4215
4216
    /**
4217
    * Get users followed by human resource manager
4218
    * @param int $userId
4219
    * @param int  $userStatus Filter users by status (STUDENT, COURSEMANAGER, etc)
4220
    * @param bool $getOnlyUserId
4221
    * @param bool $getSql
4222
    * @param bool $getCount
4223
    * @param int $from
4224
    * @param int $numberItems
4225
    * @param int $column
4226
    * @param string $direction
4227
    * @param int $active
4228
    * @param string $lastConnectionDate
4229
    * @param int $status the function is called by who? COURSEMANAGER, DRH?
4230
    * @param string $keyword
4231
     *
4232
    * @return array user list
4233
    */
4234
    public static function getUsersFollowedByUser(
4235
        $userId,
4236
        $userStatus = null,
4237
        $getOnlyUserId = false,
4238
        $getSql = false,
4239
        $getCount = false,
4240
        $from = null,
4241
        $numberItems = null,
4242
        $column = null,
4243
        $direction = null,
4244
        $active = null,
4245
        $lastConnectionDate = null,
4246
        $status = null,
4247
        $keyword = null
4248
    ) {
4249
        // Database Table Definitions
4250
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
4251
        $tbl_user_rel_user = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
4252
        $tbl_user_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
4253
4254
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
4255
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4256
4257
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4258
        $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
4259
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
4260
4261
        $userId = intval($userId);
4262
4263
        $limitCondition = '';
4264
4265 View Code Duplication
        if (isset($from) && isset($numberItems)) {
4266
            $from = intval($from);
4267
            $numberItems = intval($numberItems);
4268
            $limitCondition = "LIMIT $from, $numberItems";
4269
        }
4270
4271
        $column = Database::escape_string($column);
4272
        $direction = in_array(strtolower($direction), array('asc', 'desc')) ? $direction : null;
4273
4274
        $userConditions = '';
4275
        if (!empty($userStatus)) {
4276
            $userConditions .= ' AND u.status = '.intval($userStatus);
4277
        }
4278
4279
        $select = " SELECT DISTINCT u.id user_id, u.username, u.lastname, u.firstname, u.email ";
4280
        if ($getOnlyUserId) {
4281
            $select = " SELECT DISTINCT u.id user_id";
4282
        }
4283
4284
        $masterSelect = "SELECT DISTINCT * FROM ";
4285
4286
        if ($getCount) {
4287
            $masterSelect = "SELECT COUNT(DISTINCT(user_id)) as count FROM ";
4288
            $select = " SELECT DISTINCT(u.id) user_id";
4289
        }
4290
4291
        if (!is_null($active)) {
4292
            $active = intval($active);
4293
            $userConditions .= " AND u.active = $active ";
4294
        }
4295
4296 View Code Duplication
        if (!empty($keyword)) {
4297
            $keyword = Database::escape_string($keyword);
4298
            $userConditions .= " AND (
4299
                u.username LIKE '%$keyword%' OR
4300
                u.firstname LIKE '%$keyword%' OR
4301
                u.lastname LIKE '%$keyword%' OR
4302
                u.official_code LIKE '%$keyword%' OR
4303
                u.email LIKE '%$keyword%'
4304
            )";
4305
        }
4306
4307
        if (!empty($lastConnectionDate)) {
4308
            $lastConnectionDate = Database::escape_string($lastConnectionDate);
4309
            $userConditions .=  " AND u.last_login <= '$lastConnectionDate' ";
4310
        }
4311
4312
        $courseConditions = null;
4313
        $sessionConditionsCoach = null;
4314
        $sessionConditionsTeacher = null;
4315
        $drhConditions = null;
4316
        $teacherSelect = null;
4317
4318
        switch ($status) {
4319
            case DRH:
4320
                $drhConditions .= " AND
4321
                    friend_user_id = '$userId' AND
4322
                    relation_type = '".USER_RELATION_TYPE_RRHH."'
4323
                ";
4324
                break;
4325
            case COURSEMANAGER:
4326
                $drhConditions .= " AND
4327
                    friend_user_id = '$userId' AND
4328
                    relation_type = '".USER_RELATION_TYPE_RRHH."'
4329
                ";
4330
4331
                $sessionConditionsCoach .= " AND
4332
                    (s.id_coach = '$userId')
4333
                ";
4334
4335
                $sessionConditionsTeacher .= " AND
4336
                    (scu.status = 2 AND scu.user_id = '$userId')
4337
                ";
4338
4339
                $teacherSelect =
4340
                "UNION ALL (
4341
                        $select
4342
                        FROM $tbl_user u
4343
                        INNER JOIN $tbl_session_rel_user sru ON (sru.user_id = u.id)
4344
                        WHERE
4345
                            (
4346
                                sru.session_id IN (
4347
                                    SELECT DISTINCT(s.id) FROM $tbl_session s INNER JOIN
4348
                                    $tbl_session_rel_access_url session_rel_access_rel_user
4349
                                    ON session_rel_access_rel_user.session_id = s.id
4350
                                    WHERE access_url_id = ".api_get_current_access_url_id()."
4351
                                    $sessionConditionsCoach                                  
4352
                                ) OR sru.session_id IN (
4353
                                    SELECT DISTINCT(s.id) FROM $tbl_session s
4354
                                    INNER JOIN $tbl_session_rel_access_url url
4355
                                    ON (url.session_id = s.id)
4356
                                    INNER JOIN $tbl_session_rel_course_rel_user scu
4357
                                    ON (scu.session_id = s.id)
4358
                                    WHERE access_url_id = ".api_get_current_access_url_id()."
4359
                                    $sessionConditionsTeacher
4360
                                )
4361
                            )                            
4362
                            $userConditions
4363
                    )
4364
                    UNION ALL(
4365
                        $select
4366
                        FROM $tbl_user u
4367
                        INNER JOIN $tbl_course_user cu ON (cu.user_id = u.id)
4368
                        WHERE cu.c_id IN (
4369
                            SELECT DISTINCT(c_id) FROM $tbl_course_user
4370
                            WHERE user_id = $userId AND status = ".COURSEMANAGER."
4371
                        )
4372
                        $userConditions
4373
                    )"
4374
                ;
4375
                break;
4376
            case STUDENT_BOSS:
4377
                $drhConditions = " AND friend_user_id = $userId AND relation_type = " . USER_RELATION_TYPE_BOSS;
4378
                break;
4379
        }
4380
4381
        $join = null;
4382
        $sql = " $masterSelect
4383
                (
4384
                    (
4385
                        $select
4386
                        FROM $tbl_user u
4387
                        INNER JOIN $tbl_user_rel_user uru ON (uru.user_id = u.id)
4388
                        LEFT JOIN $tbl_user_rel_access_url a ON (a.user_id = u.id)
4389
                        $join
4390
                        WHERE
4391
                            access_url_id = ".api_get_current_access_url_id()."
4392
                            $drhConditions
4393
                            $userConditions
4394
                    )
4395
                    $teacherSelect
4396
4397
                ) as t1";
4398
4399
        if ($getSql) {
4400
            return $sql;
4401
        }
4402 View Code Duplication
        if ($getCount) {
4403
            $result = Database::query($sql);
4404
            $row = Database::fetch_array($result);
4405
            return $row['count'];
4406
        }
4407
4408
        $orderBy = null;
4409
        if ($getOnlyUserId == false) {
4410
            if (api_is_western_name_order()) {
4411
                $orderBy .= " ORDER BY firstname, lastname ";
4412
            } else {
4413
                $orderBy .= " ORDER BY lastname, firstname ";
4414
            }
4415
4416 View Code Duplication
            if (!empty($column) && !empty($direction)) {
4417
                // Fixing order due the UNIONs
4418
                $column = str_replace('u.', '', $column);
4419
                $orderBy = " ORDER BY $column $direction ";
4420
            }
4421
        }
4422
4423
        $sql .= $orderBy;
4424
        $sql .= $limitCondition;
4425
4426
        $result = Database::query($sql);
4427
        $users = array();
4428
        if (Database::num_rows($result) > 0) {
4429
4430
            while ($row = Database::fetch_array($result)) {
4431
                $users[$row['user_id']] = $row;
4432
            }
4433
        }
4434
4435
        return $users;
4436
    }
4437
4438
    /**
4439
     * Subscribes users to human resource manager (Dashboard feature)
4440
     * @param   int    $hr_dept_id
4441
     * @param   array   $users_id
4442
     * @param   int     affected rows
4443
     * */
4444
    public static function subscribeUsersToHRManager($hr_dept_id, $users_id)
4445
    {
4446
        return self::subscribeUsersToUser($hr_dept_id, $users_id, USER_RELATION_TYPE_RRHH);
4447
    }
4448
4449
    /**
4450
     * Add subscribed users to a user by relation type
4451
     * @param int $userId The user id
4452
     * @param array $subscribedUsersId The id of suscribed users
4453
     * @param string $relationType The relation type
4454
     * @param bool $deleteUsersBeforeInsert
4455
     */
4456
    public static function subscribeUsersToUser($userId, $subscribedUsersId, $relationType, $deleteUsersBeforeInsert = false)
4457
    {
4458
        $userRelUserTable = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
4459
        $userRelAccessUrlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
4460
4461
        $userId = intval($userId);
4462
        $relationType = intval($relationType);
4463
        $affectedRows = 0;
4464
4465
        if (api_get_multiple_access_url()) {
4466
            // Deleting assigned users to hrm_id
4467
            $sql = "SELECT s.user_id FROM $userRelUserTable s 
4468
                    INNER JOIN $userRelAccessUrlTable a ON (a.user_id = s.user_id) 
4469
                    WHERE 
4470
                        friend_user_id = $userId AND 
4471
                        relation_type = $relationType AND 
4472
                        access_url_id = " . api_get_current_access_url_id();
4473
        } else {
4474
            $sql = "SELECT user_id FROM $userRelUserTable 
4475
                    WHERE friend_user_id = $userId 
4476
                    AND relation_type = $relationType";
4477
        }
4478
        $result = Database::query($sql);
4479
4480 View Code Duplication
        if (Database::num_rows($result) > 0) {
4481
            while ($row = Database::fetch_array($result)) {
4482
                $sql = "DELETE FROM $userRelUserTable 
4483
                        WHERE 
4484
                          user_id = {$row['user_id']} AND 
4485
                          friend_user_id = $userId AND 
4486
                          relation_type = $relationType";
4487
                Database::query($sql);
4488
            }
4489
        }
4490
4491
        if ($deleteUsersBeforeInsert) {
4492
            $sql = "DELETE FROM $userRelUserTable 
4493
                    WHERE 
4494
                        user_id = $userId AND
4495
                        relation_type = $relationType";
4496
            Database::query($sql);
4497
        }
4498
4499
        // Inserting new user list
4500
        if (is_array($subscribedUsersId)) {
4501
            foreach ($subscribedUsersId as $subscribedUserId) {
4502
                $subscribedUserId = intval($subscribedUserId);
4503
4504
                $sql = "INSERT IGNORE INTO $userRelUserTable (user_id, friend_user_id, relation_type)
4505
                        VALUES ($subscribedUserId, $userId, $relationType)";
4506
4507
                $result = Database::query($sql);
4508
                $affectedRows = Database::affected_rows($result);
4509
            }
4510
        }
4511
4512
        return $affectedRows;
4513
    }
4514
4515
    /**
4516
     * This function check if an user is followed by human resources manager
4517
     * @param     int     $user_id
4518
     * @param    int      $hr_dept_id  Human resources manager
4519
     * @return    bool
4520
     */
4521
    public static function is_user_followed_by_drh($user_id, $hr_dept_id)
4522
    {
4523
        // Database table and variables Definitions
4524
        $tbl_user_rel_user = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
4525
        $user_id = intval($user_id);
4526
        $hr_dept_id = intval($hr_dept_id);
4527
        $result = false;
4528
4529
        $sql = "SELECT user_id FROM $tbl_user_rel_user
4530
                WHERE
4531
                    user_id = $user_id AND
4532
                    friend_user_id = $hr_dept_id AND
4533
                    relation_type = ".USER_RELATION_TYPE_RRHH;
4534
        $rs = Database::query($sql);
4535
        if (Database::num_rows($rs) > 0) {
4536
            $result = true;
4537
        }
4538
        return $result;
4539
    }
4540
4541
    /**
4542
     * get user id of teacher or session administrator
4543
     * @param array $courseInfo
4544
     *
4545
     * @return int The user id
4546
     */
4547
    public static function get_user_id_of_course_admin_or_session_admin($courseInfo)
4548
    {
4549
        $session = api_get_session_id();
4550
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
4551
        $table_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4552
        $table_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4553
        $courseId = $courseInfo['real_id'];
4554
4555
        if ($session == 0 || is_null($session)) {
4556
            $sql = 'SELECT u.id uid FROM '.$table_user.' u
4557
                    INNER JOIN '.$table_course_user.' ru
4558
                    ON ru.user_id = u.id
4559
                    WHERE
4560
                        ru.status = 1 AND
4561
                        ru.c_id = "'.$courseId.'" ';
4562
            $rs = Database::query($sql);
4563
            $num_rows = Database::num_rows($rs);
4564
            if ($num_rows == 1) {
4565
                $row = Database::fetch_array($rs);
4566
                return $row['uid'];
4567
            } else {
4568
                $my_num_rows = $num_rows;
4569
                $my_user_id = Database::result($rs, $my_num_rows - 1, 'uid');
4570
4571
                return $my_user_id;
4572
            }
4573
        } elseif ($session > 0) {
4574
            $sql = 'SELECT u.id uid FROM '.$table_user.' u
4575
                    INNER JOIN '.$table_session_course_user.' sru
4576
                    ON sru.user_id=u.id
4577
                    WHERE
4578
                        sru.c_id="'.$courseId.'" AND
4579
                        sru.status=2';
4580
            $rs = Database::query($sql);
4581
            $row = Database::fetch_array($rs);
4582
4583
            return $row['uid'];
4584
        }
4585
    }
4586
4587
    /**
4588
     * Determines if a user is a gradebook certified
4589
     * @param int $cat_id The category id of gradebook
4590
     * @param int $user_id The user id
4591
     * @return boolean
4592
     */
4593 View Code Duplication
    public static function is_user_certified($cat_id, $user_id)
4594
    {
4595
        $table_certificate = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
4596
        $sql = 'SELECT path_certificate FROM '.$table_certificate.'
4597
                WHERE
4598
                    cat_id="'.intval($cat_id).'" AND
4599
                    user_id="'.intval($user_id).'"';
4600
        $rs = Database::query($sql);
4601
        $row = Database::fetch_array($rs);
4602
        if ($row['path_certificate'] == '' || is_null($row['path_certificate'])) {
4603
            return false;
4604
        } else {
4605
            return true;
4606
        }
4607
    }
4608
4609
    /**
4610
     * Gets the info about a gradebook certificate for a user by course
4611
     * @param int $courseId course id
4612
     * @param int $user_id The user id
4613
     * @return array  if there is not information return false
4614
     */
4615
    public static function getInfoGradeBookCertificate($courseId, $user_id)
4616
    {
4617
        $tbl_grade_certificate = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
4618
        $tbl_grade_category = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
4619
        $session_id = api_get_session_id();
4620
4621
        if (empty($session_id)) {
4622
            $session_condition = ' AND (session_id = "" OR session_id = 0 OR session_id IS NULL )';
4623
        } else {
4624
            $session_condition = " AND session_id = $session_id";
4625
        }
4626
4627
        $sql = 'SELECT * FROM '.$tbl_grade_certificate.' 
4628
                WHERE cat_id = (
4629
                    SELECT id FROM '.$tbl_grade_category.'
4630
                    WHERE
4631
                        c_id = "'.Database::escape_string($courseId).'" '.$session_condition.' 
4632
                    LIMIT 1
4633
                 ) 
4634
                 AND user_id='.intval($user_id);
4635
4636
        $rs = Database::query($sql);
4637
        if (Database::num_rows($rs) > 0) {
4638
            $row = Database::fetch_array($rs, 'ASSOC');
4639
            $score = $row['score_certificate'];
4640
            $category_id = $row['cat_id'];
4641
            $cat = Category::load($category_id);
4642
            $displayscore = ScoreDisplay::instance();
4643
            if (isset($cat) && $displayscore->is_custom()) {
4644
                $grade = $displayscore->display_score(array($score, $cat[0]->get_weight()), SCORE_DIV_PERCENT_WITH_CUSTOM);
4645
            } else {
4646
                $grade = $displayscore->display_score(array($score, $cat[0]->get_weight()));
4647
            }
4648
            $row['grade'] = $grade;
4649
4650
            return $row;
4651
        }
4652
4653
        return false;
4654
    }
4655
4656
    /**
4657
     * Gets the user path of user certificated
4658
     * @param int The user id
4659
     * @return array  containing path_certificate and cat_id
4660
     */
4661
    public static function get_user_path_certificate($user_id)
4662
    {
4663
        $my_certificate = array();
4664
        $table_certificate = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
4665
        $table_gradebook_category = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
4666
4667
        $session_id = api_get_session_id();
4668
        $user_id = intval($user_id);
4669 View Code Duplication
        if ($session_id == 0 || is_null($session_id)) {
4670
            $sql_session = 'AND (session_id='.intval($session_id).' OR isnull(session_id)) ';
4671
        } elseif ($session_id > 0) {
4672
            $sql_session = 'AND session_id='.intval($session_id);
4673
        } else {
4674
            $sql_session = '';
4675
        }
4676
        $sql = "SELECT tc.path_certificate,tc.cat_id,tgc.course_code,tgc.name
4677
                FROM $table_certificate tc, $table_gradebook_category tgc
4678
                WHERE tgc.id = tc.cat_id AND tc.user_id = $user_id
4679
                ORDER BY tc.date_certificate DESC 
4680
                LIMIT 5";
4681
4682
        $rs = Database::query($sql);
4683
        while ($row = Database::fetch_array($rs)) {
4684
            $my_certificate[] = $row;
4685
        }
4686
        return $my_certificate;
4687
    }
4688
4689
    /**
4690
     * This function check if the user is a coach inside session course
4691
     * @param  int  $user_id    User id
4692
     * @param  int  $courseId
4693
     * @param  int  $session_id
4694
     * @return bool    True if the user is a coach
4695
     *
4696
     */
4697 View Code Duplication
    public static function is_session_course_coach($user_id, $courseId, $session_id)
4698
    {
4699
        $tbl_session_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4700
        // Protect data
4701
        $user_id = intval($user_id);
4702
        $courseId = intval($courseId);
4703
        $session_id = intval($session_id);
4704
        $result = false;
4705
4706
        $sql = "SELECT session_id FROM $tbl_session_course_rel_user
4707
                WHERE
4708
                  session_id = $session_id AND
4709
                  c_id = $courseId AND
4710
                  user_id = $user_id AND
4711
                  status = 2 ";
4712
        $res = Database::query($sql);
4713
4714
        if (Database::num_rows($res) > 0) {
4715
            $result = true;
4716
        }
4717
        return $result;
4718
    }
4719
4720
    /**
4721
     * This function returns an icon path that represents the favicon of the website of which the url given.
4722
     * Defaults to the current Chamilo favicon
4723
     * @param    string    $url1 URL of website where to look for favicon.ico
4724
     * @param    string    $url2 Optional second URL of website where to look for favicon.ico
4725
     * @return    string    Path of icon to load
4726
     */
4727
    public static function get_favicon_from_url($url1, $url2 = null)
4728
    {
4729
        $icon_link = '';
4730
        $url = $url1;
4731
        if (empty($url1)) {
4732
            $url = $url2;
4733
            if (empty($url)) {
4734
                $url = api_get_access_url(api_get_current_access_url_id());
4735
                $url = $url[0];
4736
            }
4737
        }
4738
        if (!empty($url)) {
4739
            $pieces = parse_url($url);
4740
            $icon_link = $pieces['scheme'].'://'.$pieces['host'].'/favicon.ico';
4741
        }
4742
        return $icon_link;
4743
    }
4744
4745
    /**
4746
     *
4747
     * @param int   student id
4748
     * @param int   years
4749
     * @param bool  show warning_message
4750
     * @param bool  return_timestamp
4751
     */
4752
    public static function delete_inactive_student($student_id, $years = 2, $warning_message = false, $return_timestamp = false)
4753
    {
4754
        $tbl_track_login = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
4755
        $sql = 'SELECT login_date FROM '.$tbl_track_login.'
4756
                WHERE login_user_id = '.intval($student_id).'
4757
                ORDER BY login_date DESC LIMIT 0,1';
4758
        if (empty($years)) {
4759
            $years = 1;
4760
        }
4761
        $inactive_time = $years * 31536000;  //1 year
4762
        $rs = Database::query($sql);
4763
        if (Database::num_rows($rs) > 0) {
4764
            if ($last_login_date = Database::result($rs, 0, 0)) {
4765
                $last_login_date = api_get_local_time($last_login_date, null, date_default_timezone_get());
4766
                if ($return_timestamp) {
4767
                    return api_strtotime($last_login_date);
4768
                } else {
4769
                    if (!$warning_message) {
4770
                        return api_format_date($last_login_date, DATE_FORMAT_SHORT);
4771
                    } else {
4772
                        $timestamp = api_strtotime($last_login_date);
4773
                        $currentTimestamp = time();
4774
4775
                        //If the last connection is > than 7 days, the text is red
4776
                        //345600 = 7 days in seconds 63072000= 2 ans
4777
                        // if ($currentTimestamp - $timestamp > 184590 )
4778
                        if ($currentTimestamp - $timestamp > $inactive_time && UserManager::delete_user($student_id)) {
4779
                            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...
4780
                            echo '<p>', 'id', $student_id, ':', $last_login_date, '</p>';
4781
                        }
4782
                    }
4783
                }
4784
            }
4785
        }
4786
        return false;
4787
    }
4788
4789
    /**
4790
     * @param FormValidator $form
4791
     * @param $extra_data
4792
     * @param $form_name
4793
     * @param bool $admin_permissions
4794
     * @param null $user_id
4795
     * @deprecated
4796
     * @return array
4797
     */
4798
    public static function set_extra_fields_in_form(
4799
        $form,
4800
        $extra_data,
4801
        $admin_permissions = false,
4802
        $user_id = null
4803
    ) {
4804
        $user_id = intval($user_id);
4805
4806
        // EXTRA FIELDS
4807
        $extra = UserManager::get_extra_fields(0, 50, 5, 'ASC');
4808
        $jquery_ready_content = null;
4809
        foreach ($extra as $field_details) {
4810
4811
            if (!$admin_permissions) {
4812
                if ($field_details[6] == 0) {
4813
                    continue;
4814
                }
4815
            }
4816
4817
            switch ($field_details[2]) {
4818 View Code Duplication
                case ExtraField::FIELD_TYPE_TEXT:
4819
                    $form->addElement('text', 'extra_'.$field_details[1], $field_details[3], array('size' => 40));
4820
                    $form->applyFilter('extra_'.$field_details[1], 'stripslashes');
4821
                    $form->applyFilter('extra_'.$field_details[1], 'trim');
4822
                    $form->applyFilter('extra_'.$field_details[1], 'html_filter');
4823
4824
                    if (!$admin_permissions) {
4825
                        if ($field_details[7] == 0) {
4826
                            $form->freeze('extra_'.$field_details[1]);
4827
                        }
4828
                    }
4829
                    break;
4830 View Code Duplication
                case ExtraField::FIELD_TYPE_TEXTAREA:
4831
                    $form->addHtmlEditor(
4832
                        'extra_'.$field_details[1],
4833
                        $field_details[3],
4834
                        false,
4835
                        false,
4836
                        array('ToolbarSet' => 'Profile', 'Width' => '100%', 'Height' => '130')
4837
                    );
4838
                    $form->applyFilter('extra_'.$field_details[1], 'stripslashes');
4839
                    $form->applyFilter('extra_'.$field_details[1], 'trim');
4840
                    if (!$admin_permissions) {
4841
                        if ($field_details[7] == 0)
4842
                            $form->freeze('extra_'.$field_details[1]);
4843
                    }
4844
                    break;
4845
                case ExtraField::FIELD_TYPE_RADIO:
4846
                    $group = array();
4847 View Code Duplication
                    foreach ($field_details[9] as $option_id => $option_details) {
4848
                        $options[$option_details[1]] = $option_details[2];
4849
                        $group[] = $form->createElement(
4850
                            'radio',
4851
                            'extra_'.$field_details[1],
4852
                            $option_details[1],
4853
                            $option_details[2].'<br />',
4854
                            $option_details[1]
4855
                        );
4856
                    }
4857
                    $form->addGroup($group, 'extra_'.$field_details[1], $field_details[3]);
4858
                    if (!$admin_permissions) {
4859
                        if ($field_details[7] == 0) {
4860
                            $form->freeze('extra_'.$field_details[1]);
4861
                        }
4862
                    }
4863
                    break;
4864
                case ExtraField::FIELD_TYPE_SELECT:
4865
                    $get_lang_variables = false;
4866 View Code Duplication
                    if (in_array(
4867
                        $field_details[1],
4868
                        array(
4869
                            'mail_notify_message',
4870
                            'mail_notify_invitation',
4871
                            'mail_notify_group_message',
4872
                        )
4873
                    )) {
4874
                        $get_lang_variables = true;
4875
                    }
4876
                    $options = array();
4877
4878
                    foreach ($field_details[9] as $option_id => $option_details) {
4879
                        if ($get_lang_variables) {
4880
                            $options[$option_details[1]] = get_lang($option_details[2]);
4881
                        } else {
4882
                            $options[$option_details[1]] = $option_details[2];
4883
                        }
4884
                    }
4885
4886
                    if ($get_lang_variables) {
4887
                        $field_details[3] = get_lang($field_details[3]);
4888
                    }
4889
4890
                    $form->addElement(
4891
                        'select',
4892
                        'extra_'.$field_details[1],
4893
                        $field_details[3],
4894
                        $options,
4895
                        array('id' => 'extra_' . $field_details[1])
4896
                    );
4897
4898
                    if (!$admin_permissions) {
4899
                        if ($field_details[7] == 0)
4900
                            $form->freeze('extra_'.$field_details[1]);
4901
                    }
4902
                    break;
4903
                case ExtraField::FIELD_TYPE_SELECT_MULTIPLE:
4904
                    $options = array();
4905
                    foreach ($field_details[9] as $option_id => $option_details) {
4906
                        $options[$option_details[1]] = $option_details[2];
4907
                    }
4908
                    $form->addElement(
4909
                        'select',
4910
                        'extra_'.$field_details[1],
4911
                        $field_details[3],
4912
                        $options,
4913
                        array('multiple' => 'multiple')
4914
                    );
4915
                    if (!$admin_permissions) {
4916
                        if ($field_details[7] == 0)
4917
                            $form->freeze('extra_'.$field_details[1]);
4918
                    }
4919
                    break;
4920 View Code Duplication
                case ExtraField::FIELD_TYPE_DATE:
4921
                    $form->addDatePicker('extra_'.$field_details[1], $field_details[3]);
4922
                    $defaults['extra_'.$field_details[1]] = date('Y-m-d 12:00:00');
4923
                    $form->setDefaults($defaults);
4924
                    if (!$admin_permissions) {
4925
                        if ($field_details[7] == 0)
4926
                            $form->freeze('extra_'.$field_details[1]);
4927
                    }
4928
                    $form->applyFilter('theme', 'trim');
4929
                    break;
4930 View Code Duplication
                case ExtraField::FIELD_TYPE_DATETIME:
4931
                    $form->addDateTimePicker('extra_'.$field_details[1], $field_details[3]);
4932
                    $defaults['extra_'.$field_details[1]] = date('Y-m-d 12:00:00');
4933
                    $form->setDefaults($defaults);
4934
                    if (!$admin_permissions) {
4935
                        if ($field_details[7] == 0)
4936
                            $form->freeze('extra_'.$field_details[1]);
4937
                    }
4938
                    $form->applyFilter('theme', 'trim');
4939
                    break;
4940
                case ExtraField::FIELD_TYPE_DOUBLE_SELECT:
4941
                    foreach ($field_details[9] as $key => $element) {
4942
                        if ($element[2][0] == '*') {
4943
                            $values['*'][$element[0]] = str_replace('*', '', $element[2]);
4944
                        } else {
4945
                            $values[0][$element[0]] = $element[2];
4946
                        }
4947
                    }
4948
4949
                    $group = '';
4950
                    $group[] = $form->createElement('select', 'extra_'.$field_details[1], '', $values[0], '');
4951
                    $group[] = $form->createElement('select', 'extra_'.$field_details[1].'*', '', $values['*'], '');
4952
                    $form->addGroup($group, 'extra_'.$field_details[1], $field_details[3]);
4953
4954
                    if (!$admin_permissions) {
4955
                        if ($field_details[7] == 0)
4956
                            $form->freeze('extra_'.$field_details[1]);
4957
                    }
4958
4959
                    /* Recoding the selected values for double : if the user has
4960
                    selected certain values, we have to assign them to the
4961
                    correct select form */
4962
                    if (array_key_exists('extra_'.$field_details[1], $extra_data)) {
4963
                        // exploding all the selected values (of both select forms)
4964
                        $selected_values = explode(';', $extra_data['extra_'.$field_details[1]]);
4965
                        $extra_data['extra_'.$field_details[1]] = array();
4966
4967
                        // looping through the selected values and assigning the selected values to either the first or second select form
4968
                        foreach ($selected_values as $key => $selected_value) {
4969
                            if (array_key_exists($selected_value, $values[0])) {
4970
                                $extra_data['extra_'.$field_details[1]]['extra_'.$field_details[1]] = $selected_value;
4971
                            } else {
4972
                                $extra_data['extra_'.$field_details[1]]['extra_'.$field_details[1].'*'] = $selected_value;
4973
                            }
4974
                        }
4975
                    }
4976
                    break;
4977
                case ExtraField::FIELD_TYPE_DIVIDER:
4978
                    $form->addElement('static', $field_details[1], '<br /><strong>'.$field_details[3].'</strong>');
4979
                    break;
4980
                case ExtraField::FIELD_TYPE_TAG:
4981
                    //the magic should be here
4982
                    $user_tags = UserManager::get_user_tags($user_id, $field_details[0]);
4983
4984
                    $tag_list = '';
4985
                    if (is_array($user_tags) && count($user_tags) > 0) {
4986
                        foreach ($user_tags as $tag) {
4987
                            $tag_list .= '<option value="'.$tag['tag'].'" class="selected">'.$tag['tag'].'</option>';
4988
                        }
4989
                    }
4990
4991
                    $multi_select = '<select id="extra_'.$field_details[1].'" name="extra_'.$field_details[1].'">
4992
                                    '.$tag_list.'
4993
                                    </select>';
4994
4995
                    $form->addElement('label', $field_details[3], $multi_select);
4996
                    $url = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php';
4997
                    $complete_text = get_lang('StartToType');
4998
                    //if cache is set to true the jquery will be called 1 time
4999
                    $jquery_ready_content = <<<EOF
5000
                    $("#extra_$field_details[1]").fcbkcomplete({
5001
                        json_url: "$url?a=search_tags&field_id=$field_details[0]",
5002
                        cache: false,
5003
                        filter_case: true,
5004
                        filter_hide: true,
5005
                        complete_text:"$complete_text",
5006
                        firstselected: true,
5007
                        //onremove: "testme",
5008
                        //onselect: "testme",
5009
                        filter_selected: true,
5010
                        newel: true
5011
                    });
5012
EOF;
5013
                    break;
5014
                case ExtraField::FIELD_TYPE_TIMEZONE:
5015
                    $form->addElement('select', 'extra_'.$field_details[1], $field_details[3], api_get_timezones(), '');
5016
                    if ($field_details[7] == 0)
5017
                        $form->freeze('extra_'.$field_details[1]);
5018
                    break;
5019
                case ExtraField::FIELD_TYPE_SOCIAL_PROFILE:
5020
                    // get the social network's favicon
5021
                    $icon_path = UserManager::get_favicon_from_url($extra_data['extra_'.$field_details[1]], $field_details[4]);
5022
                    // special hack for hi5
5023
                    $leftpad = '1.7';
5024
                    $top = '0.4';
5025
                    $domain = parse_url($icon_path, PHP_URL_HOST);
5026
                    if ($domain == 'www.hi5.com' or $domain == 'hi5.com') {
5027
                        $leftpad = '3';
5028
                        $top = '0';
5029
                    }
5030
                    // print the input field
5031
                    $form->addElement(
5032
                        'text',
5033
                        'extra_'.$field_details[1],
5034
                        $field_details[3],
5035
                        array(
5036
                            'size' => 60,
5037
                            'style' => 'background-image: url(\''.$icon_path.'\'); background-repeat: no-repeat; background-position: 0.4em '.$top.'em; padding-left: '.$leftpad.'em; '
5038
                        )
5039
                    );
5040
                    $form->applyFilter('extra_'.$field_details[1], 'stripslashes');
5041
                    $form->applyFilter('extra_'.$field_details[1], 'trim');
5042
                    if ($field_details[7] == 0)
5043
                        $form->freeze('extra_'.$field_details[1]);
5044
                    break;
5045
                case ExtraField::FIELD_TYPE_FILE:
5046
                    $extra_field = 'extra_'.$field_details[1];
5047
                    $form->addElement('file', $extra_field, $field_details[3], null, '');
5048
                    if ($extra_file_list = UserManager::build_user_extra_file_list($user_id, $field_details[1], '', true)) {
5049
                        $form->addElement('static', $extra_field . '_list', null, $extra_file_list);
5050
                    }
5051
                    if ($field_details[7] == 0) {
5052
                        $form->freeze($extra_field);
5053
                    }
5054
                    break;
5055 View Code Duplication
                case ExtraField::FIELD_TYPE_MOBILE_PHONE_NUMBER:
5056
                    $form->addElement(
5057
                        'text',
5058
                        'extra_'.$field_details[1],
5059
                        $field_details[3]." (".get_lang('CountryDialCode').")",
5060
                        array('size' => 40, 'placeholder'  => '(xx)xxxxxxxxx')
5061
                    );
5062
                    $form->applyFilter('extra_'.$field_details[1], 'stripslashes');
5063
                    $form->applyFilter('extra_'.$field_details[1], 'trim');
5064
                    $form->applyFilter('extra_'.$field_details[1], 'mobile_phone_number_filter');
5065
                    $form->addRule(
5066
                        'extra_'.$field_details[1],
5067
                        get_lang('MobilePhoneNumberWrong'),
5068
                        'mobile_phone_number'
5069
                    );
5070
                    if (!$admin_permissions) {
5071
                        if ($field_details[7] == 0) {
5072
                            $form->freeze('extra_'.$field_details[1]);
5073
                        }
5074
                    }
5075
                    break;
5076
            }
5077
        }
5078
        $return = array();
5079
        $return['jquery_ready_content'] = $jquery_ready_content;
5080
        return $return;
5081
    }
5082
5083
    /**
5084
     * @return array
5085
     */
5086
    public static function get_user_field_types()
5087
    {
5088
        $types = array();
5089
        $types[self::USER_FIELD_TYPE_TEXT] = get_lang('FieldTypeText');
5090
        $types[self::USER_FIELD_TYPE_TEXTAREA] = get_lang('FieldTypeTextarea');
5091
        $types[self::USER_FIELD_TYPE_RADIO] = get_lang('FieldTypeRadio');
5092
        $types[self::USER_FIELD_TYPE_SELECT] = get_lang('FieldTypeSelect');
5093
        $types[self::USER_FIELD_TYPE_SELECT_MULTIPLE] = get_lang('FieldTypeSelectMultiple');
5094
        $types[self::USER_FIELD_TYPE_DATE] = get_lang('FieldTypeDate');
5095
        $types[self::USER_FIELD_TYPE_DATETIME] = get_lang('FieldTypeDatetime');
5096
        $types[self::USER_FIELD_TYPE_DOUBLE_SELECT] = get_lang('FieldTypeDoubleSelect');
5097
        $types[self::USER_FIELD_TYPE_DIVIDER] = get_lang('FieldTypeDivider');
5098
        $types[self::USER_FIELD_TYPE_TAG] = get_lang('FieldTypeTag');
5099
        $types[self::USER_FIELD_TYPE_TIMEZONE] = get_lang('FieldTypeTimezone');
5100
        $types[self::USER_FIELD_TYPE_SOCIAL_PROFILE] = get_lang('FieldTypeSocialProfile');
5101
        $types[self::USER_FIELD_TYPE_FILE] = get_lang('FieldTypeFile');
5102
        $types[self::USER_FIELD_TYPE_MOBILE_PHONE_NUMBER] = get_lang('FieldTypeMobilePhoneNumber');
5103
5104
        return $types;
5105
    }
5106
5107
    /**
5108
     * @param User $user
5109
     */
5110
    public static function add_user_as_admin(User $user)
5111
    {
5112
        $table_admin = Database :: get_main_table(TABLE_MAIN_ADMIN);
5113
        if ($user) {
5114
            $userId = $user->getId();
5115
5116
            if (!self::is_admin($userId)) {
5117
                $sql = "INSERT INTO $table_admin SET user_id = $userId";
5118
                Database::query($sql);
5119
            }
5120
5121
            $user->addRole('ROLE_SUPER_ADMIN');
5122
            self::getManager()->updateUser($user, true);
5123
        }
5124
    }
5125
5126
    /**
5127
     * @param int $userId
5128
     */
5129 View Code Duplication
    public static function remove_user_admin($userId)
5130
    {
5131
        $table_admin = Database :: get_main_table(TABLE_MAIN_ADMIN);
5132
        $userId = intval($userId);
5133
        if (self::is_admin($userId)) {
5134
            $sql = "DELETE FROM $table_admin WHERE user_id = $userId";
5135
            Database::query($sql);
5136
        }
5137
    }
5138
5139
    /**
5140
     * @param string $from
5141
     * @param string $to
5142
     */
5143
    public static function update_all_user_languages($from, $to)
5144
    {
5145
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
5146
        $from = Database::escape_string($from);
5147
        $to = Database::escape_string($to);
5148
5149
        if (!empty($to) && !empty($from)) {
5150
            $sql = "UPDATE $table_user SET language = '$to'
5151
                    WHERE language = '$from'";
5152
            Database::query($sql);
5153
        }
5154
    }
5155
5156
    /**
5157
     * Subscribe boss to students
5158
     *
5159
     * @param int $bossId The boss id
5160
     * @param array $usersId The users array
5161
     * @return int Affected rows
5162
     */
5163
    public static function subscribeBossToUsers($bossId, $usersId)
5164
    {
5165
        return self::subscribeUsersToUser($bossId, $usersId, USER_RELATION_TYPE_BOSS);
5166
    }
5167
5168
    /**
5169
     * Subscribe boss to students
5170
     *
5171
     * @param int $studentId
5172
     * @param array $bossList
5173
     * @return int Affected rows
5174
     */
5175
    public static function subscribeUserToBossList($studentId, $bossList)
5176
    {
5177
        if ($bossList) {
5178
            $studentId = (int) $studentId;
5179
            $userRelUserTable = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
5180
            $sql = "DELETE FROM $userRelUserTable 
5181
                    WHERE user_id = $studentId AND relation_type = ".USER_RELATION_TYPE_BOSS;
5182
            Database::query($sql);
5183
5184
            foreach ($bossList as $bossId) {
5185
                $bossId = (int) $bossId;
5186
                $sql = "INSERT IGNORE INTO $userRelUserTable (user_id, friend_user_id, relation_type)
5187
                        VALUES ($studentId, $bossId, ".USER_RELATION_TYPE_BOSS.")";
5188
5189
                Database::query($sql);
5190
            }
5191
        }
5192
    }
5193
5194
    /**
5195
     * Get users followed by student boss
5196
     * @param int $userId
5197
     * @param int $userStatus (STUDENT, COURSEMANAGER, etc)
5198
     * @param bool $getOnlyUserId
5199
     * @param bool $getSql
5200
     * @param bool $getCount
5201
     * @param int $from
5202
     * @param int $numberItems
5203
     * @param int $column
5204
     * @param string $direction
5205
     * @param int $active
5206
     * @param string $lastConnectionDate
5207
     * @return array     users
5208
     */
5209 View Code Duplication
    public static function getUsersFollowedByStudentBoss(
5210
        $userId,
5211
        $userStatus = 0,
5212
        $getOnlyUserId = false,
5213
        $getSql = false,
5214
        $getCount = false,
5215
        $from = null,
5216
        $numberItems = null,
5217
        $column = null,
5218
        $direction = null,
5219
        $active = null,
5220
        $lastConnectionDate = null
5221
    ){
5222
        return self::getUsersFollowedByUser(
5223
            $userId,
5224
            $userStatus,
5225
            $getOnlyUserId,
5226
            $getSql,
5227
            $getCount,
5228
            $from,
5229
            $numberItems,
5230
            $column,
5231
            $direction,
5232
            $active,
5233
            $lastConnectionDate,
5234
            STUDENT_BOSS
5235
        );
5236
    }
5237
5238
    /**
5239
     * Get the teacher (users with COURSEMANGER status) list
5240
     * @return array The list
5241
     */
5242
    public static function getTeachersList()
5243
    {
5244
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
5245
5246
        $resultData = Database::select('user_id, lastname, firstname, username', $userTable, array(
5247
            'where' => array(
5248
                'status = ?' => COURSEMANAGER
5249
            )
5250
        ));
5251
5252
        foreach ($resultData as &$teacherData) {
5253
            $teacherData['completeName'] = api_get_person_name($teacherData['firstname'], $teacherData['lastname']);
5254
        }
5255
5256
        return $resultData;
5257
    }
5258
5259
    /**
5260
     * @return array
5261
     */
5262 View Code Duplication
    public static function getOfficialCodeGrouped()
5263
    {
5264
        $user = Database::get_main_table(TABLE_MAIN_USER);
5265
        $sql = "SELECT DISTINCT official_code
5266
                FROM $user
5267
                GROUP BY official_code";
5268
        $result = Database::query($sql);
5269
5270
        $values = Database::store_result($result, 'ASSOC');
5271
5272
        $result = array();
5273
        foreach ($values as $value) {
5274
            $result[$value['official_code']] = $value['official_code'];
5275
        }
5276
        return $result;
5277
    }
5278
5279
    /**
5280
     * @param string $officialCode
5281
     * @return array
5282
     */
5283
    public static function getUsersByOfficialCode($officialCode)
5284
    {
5285
        $user = Database::get_main_table(TABLE_MAIN_USER);
5286
        $officialCode = Database::escape_string($officialCode);
5287
5288
        $sql = "SELECT DISTINCT id
5289
                FROM $user
5290
                WHERE official_code = '$officialCode'
5291
                ";
5292
        $result = Database::query($sql);
5293
5294
        $users = array();
5295
        while ($row = Database::fetch_array($result)) {
5296
            $users[] = $row['id'];
5297
        }
5298
        return $users;
5299
    }
5300
5301
    /**
5302
     * Calc the expended time (in seconds) by a user in a course
5303
     * @param int $userId The user id
5304
     * @param int $courseId The course id
5305
     * @param int $sessionId Optional. The session id
5306
     * @param string $from Optional. From date
5307
     * @param string $until Optional. Until date
5308
     * @return int The time
5309
     */
5310
    public static function getTimeSpentInCourses($userId, $courseId, $sessionId = 0, $from = '', $until = '')
5311
    {
5312
        $userId = intval($userId);
5313
        $sessionId = intval($sessionId);
5314
5315
        $trackCourseAccessTable = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5316
5317
        $whereConditions = array(
5318
            'user_id = ? ' => $userId,
5319
            'AND c_id = ? ' => $courseId,
5320
            'AND session_id = ? ' => $sessionId
5321
        );
5322
5323 View Code Duplication
        if (!empty($from) && !empty($until)) {
5324
            $whereConditions["AND (login_course_date >= '?' "] = $from;
5325
            $whereConditions["AND logout_course_date <= DATE_ADD('?', INTERVAL 1 DAY)) "] = $until;
5326
        }
5327
5328
        $trackResult = Database::select(
5329
            'SUM(UNIX_TIMESTAMP(logout_course_date) - UNIX_TIMESTAMP(login_course_date)) as total_time',
5330
            $trackCourseAccessTable,
5331
            array(
5332
                'where' => $whereConditions
5333
            ), 'first'
5334
        );
5335
5336
        if ($trackResult != false) {
5337
            return $trackResult['total_time'] ? $trackResult['total_time'] : 0;
5338
        }
5339
5340
        return 0;
5341
    }
5342
5343
    /**
5344
     * Get the boss user ID from a followed user id
5345
     * @param $userId
5346
     * @return bool
5347
     */
5348 View Code Duplication
    public static function getFirstStudentBoss($userId)
5349
    {
5350
        $userId = intval($userId);
5351
        if ($userId > 0) {
5352
            $userRelTable = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
5353
            $row = Database::select(
5354
                'DISTINCT friend_user_id AS boss_id',
5355
                $userRelTable,
5356
                array(
5357
                    'where' => array(
5358
                        'user_id = ? AND relation_type = ? LIMIT 1' => array(
5359
                            $userId,
5360
                            USER_RELATION_TYPE_BOSS,
5361
                        )
5362
                    )
5363
                )
5364
            );
5365
            if (!empty($row)) {
5366
5367
                return $row[0]['boss_id'];
5368
            }
5369
        }
5370
5371
        return false;
5372
    }
5373
5374
    /**
5375
     * Get the boss user ID from a followed user id
5376
     * @param $userId
5377
     * @return bool
5378
     */
5379 View Code Duplication
    public static function getStudentBossList($userId)
5380
    {
5381
        $userId = intval($userId);
5382
        if ($userId > 0) {
5383
            $userRelTable = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
5384
            $result = Database::select(
5385
                'DISTINCT friend_user_id AS boss_id',
5386
                $userRelTable,
5387
                array(
5388
                    'where' => array(
5389
                        'user_id = ? AND relation_type = ? ' => array(
5390
                            $userId,
5391
                            USER_RELATION_TYPE_BOSS,
5392
                        )
5393
                    )
5394
                ),
5395
                'all'
5396
            );
5397
5398
            return $result;
5399
        }
5400
5401
        return false;
5402
    }
5403
5404
    /**
5405
     * @param int $bossId
5406
     * @param int $studentId
5407
     *
5408
     * @return bool
5409
     */
5410
    public static function userIsBossOfStudent($bossId, $studentId)
5411
    {
5412
        $result = false;
5413
        $bossList = UserManager::getStudentBossList($studentId);
5414
        if ($bossList) {
5415
            $bossList = array_column($bossList, 'boss_id');
5416
            if (in_array($bossId, $bossList)) {
5417
                $result = true;
5418
            }
5419
        }
5420
5421
        return $result;
5422
    }
5423
5424
    /**
5425
     * Get either a Gravatar URL or complete image tag for a specified email address.
5426
     *
5427
     * @param string $email The email address
5428
     * @param string $s Size in pixels, defaults to 80px [ 1 - 2048 ]
5429
     * @param string $d Default imageset to use [ 404 | mm | identicon | monsterid | wavatar ]
5430
     * @param string $r Maximum rating (inclusive) [ g | pg | r | x ]
5431
     * @param boole $img True to return a complete IMG tag False for just the URL
5432
     * @param array $atts Optional, additional key/value attributes to include in the IMG tag
5433
     * @return String containing either just a URL or a complete image tag
5434
     * @source http://gravatar.com/site/implement/images/php/
5435
     */
5436
    private static function getGravatar(
5437
        $email,
5438
        $s = 80,
5439
        $d = 'mm',
5440
        $r = 'g',
5441
        $img = false,
5442
        $atts = array()
5443
    ) {
5444
        $url = 'http://www.gravatar.com/avatar/';
5445
        if (!empty($_SERVER['HTTPS'])) {
5446
            $url = 'https://secure.gravatar.com/avatar/';
5447
        }
5448
        $url .= md5( strtolower( trim( $email ) ) );
5449
        $url .= "?s=$s&d=$d&r=$r";
5450
        if ( $img ) {
5451
            $url = '<img src="' . $url . '"';
5452
            foreach ( $atts as $key => $val )
5453
                $url .= ' ' . $key . '="' . $val . '"';
5454
            $url .= ' />';
5455
        }
5456
        return $url;
5457
    }
5458
5459
    /**
5460
     * Displays the name of the user and makes the link to the user profile
5461
     * @param array $userInfo
5462
     *
5463
     * @return string
5464
     */
5465
    public static function getUserProfileLink($userInfo)
5466
    {
5467
        if (isset($userInfo) && isset($userInfo['user_id'])) {
5468
            return Display::url(
5469
                $userInfo['complete_name_with_username'],
5470
                $userInfo['profile_url']
5471
            );
5472
        } else {
5473
            return get_lang('Anonymous');
5474
        }
5475
    }
5476
5477
    /**
5478
     * Displays the name of the user and makes the link to the user profile
5479
     *
5480
     * @param $userInfo
5481
     *
5482
     * @return string
5483
     */
5484
    public static function getUserProfileLinkWithPicture($userInfo)
5485
    {
5486
        return Display::url(Display::img($userInfo['avatar']), $userInfo['profile_url']);
5487
    }
5488
5489
    /**
5490
     * Get users whose name matches $firstname and $lastname
5491
     * @param string $firstname Firstname to search
5492
     * @param string $lastname Lastname to search
5493
     * @return array The user list
5494
     */
5495 View Code Duplication
    public static function getUserByName($firstname, $lastname)
5496
    {
5497
        $firstname = Database::escape_string($firstname);
5498
        $lastname = Database::escape_string($lastname);
5499
5500
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
5501
5502
        $sql = <<<SQL
5503
            SELECT id, username, lastname, firstname
5504
            FROM $userTable
5505
            WHERE 
5506
                firstname LIKE '$firstname%' AND
5507
                lastname LIKE '$lastname%'
5508
SQL;
5509
5510
        $result = Database::query($sql);
5511
5512
        $users = [];
5513
        while ($resultData = Database::fetch_object($result)) {
5514
            $users[] = $resultData;
5515
        }
5516
5517
        return $users;
5518
    }
5519
5520
    /**
5521
     * @param int $optionSelected
5522
     * @return string
5523
     */
5524
    public static function getUserSubscriptionTab($optionSelected = 1)
5525
    {
5526
        $allowAdmin = api_get_setting('allow_user_course_subscription_by_course_admin');
5527
        if (($allowAdmin === 'true' && api_is_allowed_to_edit()) ||
5528
            api_is_platform_admin()
5529
        ) {
5530
            $userPath = api_get_path(WEB_CODE_PATH).'user/';
5531
5532
            $headers = [
5533
                [
5534
                    'url' => $userPath.'user.php?'.api_get_cidreq().'&type='.STUDENT,
5535
                    'content' => get_lang('Students'),
5536
                ],
5537
                [
5538
                    'url' => $userPath.'user.php?'.api_get_cidreq().'&type='.COURSEMANAGER,
5539
                    'content' => get_lang('Teachers'),
5540
                ],
5541
                /*[
5542
                    'url' => $userPath.'subscribe_user.php?'.api_get_cidreq(),
5543
                    'content' => get_lang('Students'),
5544
                ],
5545
                [
5546
                    'url' => $userPath.'subscribe_user.php?type=teacher&'.api_get_cidreq(),
5547
                    'content' => get_lang('Teachers'),
5548
                ],*/
5549
                [
5550
                    'url' => api_get_path(WEB_CODE_PATH).'group/group.php?'.api_get_cidreq(),
5551
                    'content' => get_lang('Groups'),
5552
                ],
5553
                [
5554
                    'url' => $userPath.'class.php?'.api_get_cidreq(),
5555
                    'content' => get_lang('Classes'),
5556
                ]
5557
            ];
5558
5559
            return Display::tabsOnlyLink($headers, $optionSelected);
5560
        }
5561
    }
5562
5563
5564
    /**
5565
     * @param int $user_id
5566
     * @return bool
5567
     */
5568 View Code Duplication
    public static function user_is_online($user_id)
5569
    {
5570
        $track_online_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE);
5571
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
5572
5573
        $access_url_id = api_get_current_access_url_id();
5574
        $time_limit = api_get_setting('display.time_limit_whosonline');
5575
5576
        $online_time = time() - $time_limit*60;
5577
        $limit_date = api_get_utc_datetime($online_time);
5578
        $user_id = intval($user_id);
5579
5580
        $query = " SELECT login_user_id,login_date
5581
               FROM $track_online_table track
5582
               INNER JOIN $table_user u ON (u.id=track.login_user_id)
5583
               WHERE
5584
                    track.access_url_id =  $access_url_id AND
5585
                    login_date >= '".$limit_date."'  AND
5586
                    u.id =  $user_id
5587
               LIMIT 1 ";
5588
5589
        $result = Database::query($query);
5590
        if (Database::num_rows($result)) {
5591
5592
            return true;
5593
        }
5594
5595
        return false;
5596
    }
5597
5598
    /**
5599
     * @param int $time_limit seconds
5600
     * @param bool $friends show friends (true) or all users (false)
5601
     * @return bool
5602
     */
5603
    public static function whoIsOnlineCount(
5604
        $time_limit = 0,
5605
        $friends = false
5606
    ) {
5607
        if (empty($time_limit)) {
5608
            $time_limit = api_get_setting('display.time_limit_whosonline');
5609
        } else {
5610
            $time_limit = intval($time_limit);
5611
        }
5612
        $track_online_table = Database::get_main_table(
5613
            TABLE_STATISTIC_TRACK_E_ONLINE
5614
        );
5615
        $friend_user_table = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
5616
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
5617
        $online_time = time() - $time_limit * 60;
5618
        $current_date = api_get_utc_datetime($online_time);
5619
5620
        if ($friends) {
5621
            // 	who friends from social network is online
5622
            $query = "SELECT DISTINCT count(login_user_id) as count
5623
				  FROM $track_online_table INNER JOIN $friend_user_table
5624
                  ON (friend_user_id = login_user_id)
5625
				  WHERE
5626
				        login_date >= '$current_date' AND
5627
				        friend_user_id <> '".api_get_user_id()."' AND
5628
				        relation_type='".USER_RELATION_TYPE_FRIEND."' AND
5629
				        user_id = '".api_get_user_id()."' ";
5630
        } else {
5631
            // All users online
5632
            $query = "SELECT count(login_id) as count
5633
                  FROM $track_online_table track INNER JOIN $table_user u
5634
                  ON (u.id=track.login_user_id)
5635
                  WHERE u.status != ".ANONYMOUS." AND login_date >= '$current_date'  ";
5636
        }
5637
5638
        if (api_get_multiple_access_url()) {
5639
            $access_url_id = api_get_current_access_url_id();
5640
            if ($access_url_id != -1) {
5641
                if ($friends) {
5642
                    // 	friends from social network is online
5643
                    $query = "SELECT DISTINCT count(login_user_id) as count
5644
							FROM $track_online_table track
5645
							INNER JOIN $friend_user_table ON (friend_user_id = login_user_id)
5646
							WHERE
5647
							    track.access_url_id = $access_url_id AND
5648
							    login_date >= '".$current_date."' AND
5649
							    friend_user_id <> '".api_get_user_id()."' AND
5650
							    relation_type='".USER_RELATION_TYPE_FRIEND."'  ";
5651
                } else {
5652
                    // all users online
5653
                    $query = "SELECT count(login_id) as count FROM $track_online_table  track
5654
                          INNER JOIN $table_user u ON (u.id=track.login_user_id)
5655
						  WHERE
5656
						    u.status != ".ANONYMOUS." AND
5657
						    track.access_url_id =  $access_url_id AND
5658
						    login_date >= '$current_date' ";
5659
                }
5660
            }
5661
        }
5662
5663
        // Dev purposes show all users online
5664
        /*$table_user = Database::get_main_table(TABLE_MAIN_USER);
5665
        $query = "SELECT count(*)  as count FROM ".$table_user;*/
5666
5667
        $result = Database::query($query);
5668
        if (Database::num_rows($result) > 0) {
5669
            $row = Database::fetch_array($result);
5670
5671
            return $row['count'];
5672
        } else {
5673
            return false;
5674
        }
5675
    }
5676
5677
    /**
5678
     * Gives a list of people online now (and in the last $valid minutes)
5679
     *
5680
     * @param int $from
5681
     * @param int $number_of_items
5682
     * @param string $column
5683
     * @param string $direction
5684
     * @param int $time_limit in seconds
5685
     * @param bool $friends show friends (true) or all users (false)
5686
     * @return array|bool
5687
     */
5688
    public static function whoIsOnline(
5689
        $from,
5690
        $number_of_items,
5691
        $column = '',
5692
        $direction = '',
5693
        $time_limit = 0,
5694
        $friends = false
5695
    ) {
5696
        // Time limit in seconds?
5697
        if (empty($time_limit)) {
5698
            $time_limit = api_get_setting('display.time_limit_whosonline');
5699
        } else {
5700
            $time_limit = intval($time_limit);
5701
        }
5702
5703
        $from = intval($from);
5704
        $number_of_items = intval($number_of_items);
5705
5706
        if (empty($column)) {
5707
            $column = 'picture_uri';
5708
            if ($friends) {
5709
                $column = 'login_date';
5710
            }
5711
        }
5712
5713
        if (empty($direction)) {
5714
            $direction = 'DESC';
5715
        } else {
5716
            if (!in_array(strtolower($direction), array('asc', 'desc'))) {
5717
                $direction = 'DESC';
5718
            }
5719
        }
5720
5721
        $online_time = time() - $time_limit * 60;
5722
        $current_date = api_get_utc_datetime($online_time);
5723
        $track_online_table = Database::get_main_table(
5724
            TABLE_STATISTIC_TRACK_E_ONLINE
5725
        );
5726
        $friend_user_table = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
5727
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
5728
5729
        if ($friends) {
5730
            // 	who friends from social network is online
5731
            $query = "SELECT DISTINCT login_user_id, login_date
5732
				  FROM $track_online_table INNER JOIN $friend_user_table
5733
				  ON (friend_user_id = login_user_id)
5734
				  WHERE
5735
				    login_date >= '".$current_date."' AND
5736
                    friend_user_id <> '".api_get_user_id()."' AND
5737
                    relation_type='".USER_RELATION_TYPE_FRIEND."' AND
5738
                    user_id = '".api_get_user_id()."'
5739
                  ORDER BY $column $direction
5740
                  LIMIT $from, $number_of_items";
5741
        } else {
5742
            $query = "SELECT DISTINCT login_user_id, login_date
5743
                    FROM ".$track_online_table." e
5744
		            INNER JOIN ".$table_user." u ON (u.id = e.login_user_id)
5745
                  WHERE u.status != ".ANONYMOUS." AND login_date >= '".$current_date."'
5746
                  ORDER BY $column $direction
5747
                  LIMIT $from, $number_of_items";
5748
        }
5749
5750
        if (api_get_multiple_access_url()) {
5751
            $access_url_id = api_get_current_access_url_id();
5752
            if ($access_url_id != -1) {
5753
                if ($friends) {
5754
                    // 	friends from social network is online
5755
                    $query = "SELECT distinct login_user_id, login_date
5756
							FROM $track_online_table track INNER JOIN $friend_user_table
5757
							ON (friend_user_id = login_user_id)
5758
							WHERE   track.access_url_id =  $access_url_id AND
5759
                                    login_date >= '".$current_date."' AND
5760
                                    friend_user_id <> '".api_get_user_id()."' AND
5761
                                    relation_type='".USER_RELATION_TYPE_FRIEND."'
5762
                            ORDER BY $column $direction
5763
                            LIMIT $from, $number_of_items";
5764
                } else {
5765
                    // all users online
5766
                    $query = "SELECT login_user_id, login_date
5767
						  FROM ".$track_online_table." track
5768
                          INNER JOIN ".$table_user." u
5769
                          ON (u.id=track.login_user_id)
5770
						  WHERE u.status != ".ANONYMOUS." AND track.access_url_id =  $access_url_id AND
5771
                                login_date >= '".$current_date."'
5772
                          ORDER BY $column $direction
5773
                          LIMIT $from, $number_of_items";
5774
                }
5775
            }
5776
        }
5777
5778
        //This query will show all registered users. Only for dev purposes.
5779
        /*$query = "SELECT DISTINCT u.id as login_user_id, login_date FROM ".$track_online_table ."  e , $table_user u
5780
                GROUP by u.id
5781
                ORDER BY $column $direction
5782
                LIMIT $from, $number_of_items";*/
5783
5784
        $result = Database::query($query);
5785
        if ($result) {
5786
            $users_online = array();
5787
            while (list($login_user_id, $login_date) = Database::fetch_row($result)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $login_date is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
5788
                $users_online[] = $login_user_id;
5789
            }
5790
5791
            return $users_online;
5792
        } else {
5793
            return false;
5794
        }
5795
    }
5796
5797
    /**
5798
     * @param int $user_id
5799
     * @param bool $is_time_over
5800
     * @param bool $get_count
5801
     * @param bool $reverse_order
5802
     * @param int $start
5803
     * @param null $maxPerPage
5804
     * @param null $categoryFilter
5805
     * @return array
5806
     */
5807
    public static function getCategories(
5808
        $user_id,
5809
        $is_time_over = false,
5810
        $get_count = false,
5811
        $reverse_order = false,
5812
        $start = 0,
5813
        $maxPerPage = null,
5814
        $categoryFilter = null
5815
    ) {
5816
        $tableSessionCategory = Database:: get_main_table(
5817
            TABLE_MAIN_SESSION_CATEGORY
5818
        );
5819
        $tableSession = Database:: get_main_table(TABLE_MAIN_SESSION);
5820
        $tableSessionUser = Database:: get_main_table(TABLE_MAIN_SESSION_USER);
5821
        $tableSessionCourseUser = Database:: get_main_table(
5822
            TABLE_MAIN_SESSION_COURSE_USER
5823
        );
5824
5825
        $select = " DISTINCT sc.id, sc.name  ";
5826
        if ($get_count) {
5827
            $select = " COUNT(DISTINCT(sc.id)) as total";
5828
        }
5829
5830
        $sql = "SELECT $select
5831
                FROM $tableSessionCategory sc
5832
                INNER JOIN $tableSession s ON (sc.id = s.session_category_id)
5833
                INNER JOIN (
5834
                    (
5835
                        SELECT DISTINCT session_id as sessionID FROM $tableSessionUser
5836
                        WHERE user_id = $user_id AND relation_type <> ".SESSION_RELATION_TYPE_RRHH."
5837
                    )
5838
                    UNION
5839
                    (
5840
                        SELECT DISTINCT s.id
5841
                        FROM $tableSession s
5842
                        WHERE (id_coach = $user_id)
5843
                    )
5844
                    UNION
5845
                    (
5846
                        SELECT DISTINCT s.id
5847
                        FROM $tableSessionUser su INNER JOIN $tableSession s
5848
                        ON (su.session_id = s.id)
5849
                        INNER JOIN $tableSessionCourseUser scu
5850
                        ON (scu.session_id = s.id)
5851
                        WHERE (scu.user_id = $user_id)
5852
                    )
5853
                ) as t ON (t.sessionId = sc.id)
5854
        ";
5855
5856
        if ($get_count) {
5857
            $result = Database::query($sql);
5858
            $row = Database::fetch_array($result);
5859
5860
            return $row['total'];
5861
        }
5862
5863
        $order = ' ORDER BY sc.name';
5864
        if ($reverse_order) {
5865
            $order = ' ORDER BY sc.name DESC ';
5866
        }
5867
5868
        $sql .= $order;
5869
5870 View Code Duplication
        if (isset($start) && isset($maxPerPage)) {
5871
            $start = intval($start);
5872
            $maxPerPage = intval($maxPerPage);
5873
            $limitCondition = " LIMIT $start, $maxPerPage";
5874
            $sql .= $limitCondition;
5875
        }
5876
5877
        $result = Database::query($sql);
5878
        $sessionsCategories = array();
5879
        if (Database::num_rows($result)) {
5880
            while ($sessionCategory = Database::fetch_array($result, 'ASSOC')) {
5881
                $sessions = self::get_sessions_by_category(
5882
                    $user_id,
5883
                    $is_time_over,
5884
                    false,
5885
                    $reverse_order,
5886
                    null,
5887
                    null,
5888
                    $sessionCategory['id']
5889
                );
5890
                $sessionsCategories[$sessionCategory['id']] = $sessions[$sessionCategory['id']];
5891
            }
5892
        }
5893
5894
        return $sessionsCategories;
5895
    }
5896
5897
5898
}
5899