Completed
Push — master ( 81a867...33ec7a )
by Julito
33:04
created

UserManager::encryptPassword()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 2
dl 0
loc 11
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
        static $userManager;
69
70
        if (!isset($userManager)) {
71
            $encoderFactory = self::getEncoderFactory();
72
            $userManager = new Chamilo\UserBundle\Entity\Manager\UserManager(
73
                $encoderFactory,
74
                new \FOS\UserBundle\Util\Canonicalizer(),
75
                new \FOS\UserBundle\Util\Canonicalizer(),
76
                Database::getManager(),
77
                'Chamilo\\UserBundle\\Entity\\User'
78
            );
79
        }
80
81
        return $userManager;
82
    }
83
84
    /**
85
     * @param string $encryptionMethod
86
     */
87
    public static function setPasswordEncryption($encryptionMethod)
88
    {
89
        self::$encryptionMethod = $encryptionMethod;
90
    }
91
92
    /**
93
     * @return bool|mixed
94
     */
95
    public static function getPasswordEncryption()
96
    {
97
        $encryptionMethod = self::$encryptionMethod;
98
        if (empty($encryptionMethod)) {
99
            $encryptionMethod = api_get_configuration_value('password_encryption');
100
        }
101
102
        return $encryptionMethod;
103
    }
104
105
    /**
106
     * @return EncoderFactory
107
     */
108
    private static function getEncoderFactory()
109
    {
110
        $encryption = self::getPasswordEncryption();
111
        $encoders = array(
112
            'Chamilo\\UserBundle\\Entity\\User' => new \Chamilo\UserBundle\Security\Encoder($encryption)
113
        );
114
115
        $encoderFactory = new EncoderFactory($encoders);
116
117
        return $encoderFactory;
118
    }
119
120
    /**
121
     * @param User $user
122
     *
123
     * @return \Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface
124
     */
125
    private static function getEncoder(User $user)
126
    {
127
        $encoderFactory = self::getEncoderFactory();
128
129
        return $encoderFactory->getEncoder($user);
130
    }
131
132
    /**
133
     * Validates the password
134
     *
135
     * @param $encoded
136
     * @param $raw
137
     * @param $salt
138
     * @return bool
139
     */
140
    public static function isPasswordValid($encoded, $raw, $salt)
141
    {
142
        $encoder = new \Chamilo\UserBundle\Security\Encoder(self::getPasswordEncryption());
143
        $validPassword = $encoder->isPasswordValid($encoded, $raw, $salt);
144
145
        return $validPassword;
146
    }
147
148
    /**
149
     * @param string $raw
150
     * @param User   $user
151
     *
152
     * @return bool
153
     */
154
    public static function encryptPassword($raw, User $user)
155
    {
156
        $encoder = self::getEncoder($user);
157
158
        $encodedPassword = $encoder->encodePassword(
159
            $raw,
160
            $user->getSalt()
161
        );
162
163
        return $encodedPassword;
164
    }
165
166
    /**
167
     * @param int $userId
168
     * @param string $password
169
     *
170
     */
171
    public static function updatePassword($userId, $password)
172
    {
173
        $repository = self::getRepository();
174
        /** @var User $user */
175
        $user = $repository->find($userId);
176
        $userManager = self::getManager();
177
        $user->setPlainPassword($password);
178
        $userManager->updateUser($user, true);
179
    }
180
181
    /**
182
     * Creates a new user for the platform
183
     * @author Hugues Peeters <[email protected]>,
184
     * @author Roan Embrechts <[email protected]>
185
     * @param  string $firstName
186
     * @param  string $lastName
187
     * @param  int    $status (1 for course tutor, 5 for student, 6 for anonymous)
188
     * @param  string $email
189
     * @param  string $loginName
190
     * @param  string $password
191
     * @param  string $official_code Any official code (optional)
192
     * @param  string $language User language    (optional)
193
     * @param  string $phone Phone number    (optional)
194
     * @param  string $picture_uri Picture URI        (optional)
195
     * @param  string $authSource Authentication source    (optional, defaults to 'platform', dependind on constant)
196
     * @param  string $expirationDate Account expiration date (optional, defaults to null)
197
     * @param  int    $active Whether the account is enabled or disabled by default
198
     * @param  int    $hr_dept_id The department of HR in which the user is registered (optional, defaults to 0)
199
     * @param  array  $extra    Extra fields
200
     * @param  string $encrypt_method Encrypt method used if password is given encrypted. Set to an empty string by default
201
     * @param  bool $send_mail
202
     * @param  bool $isAdmin
203
     * @param  string $address
204
     * @param  bool $sendEmailToAllAdmins
205
     * @param FormValidator $form
206
     *
207
     * @return mixed   new user id - if the new user creation succeeds, false otherwise
208
     * @desc The function tries to retrieve user id from the session.
209
     * If it exists, the current user id is the creator id. If a problem arises,
210
     * @assert ('Sam','Gamegie',5,'[email protected]','jo','jo') > 1
211
     * @assert ('Pippin','Took',null,null,'jo','jo') === false
212
     */
213
    public static function create_user(
214
        $firstName,
215
        $lastName,
216
        $status,
217
        $email,
218
        $loginName,
219
        $password,
220
        $official_code = '',
221
        $language = '',
222
        $phone = '',
223
        $picture_uri = '',
224
        $authSource = PLATFORM_AUTH_SOURCE,
225
        $expirationDate = null,
226
        $active = 1,
227
        $hr_dept_id = 0,
228
        $extra = [],
229
        $encrypt_method = '',
230
        $send_mail = false,
231
        $isAdmin = false,
232
        $address = '',
233
        $sendEmailToAllAdmins = false,
234
        $form = null
235
    ) {
236
        $currentUserId = api_get_user_id();
237
        $hook = HookCreateUser::create();
238
        if (!empty($hook)) {
239
            $hook->notifyCreateUser(HOOK_EVENT_TYPE_PRE);
240
        }
241
242
        // First check wether the login already exists
243
        if (!self::is_username_available($loginName)) {
244
            Display::addFlash(
245
                Display::return_message(get_lang('LoginAlreadyTaken'))
246
            );
247
248
            return false;
249
        }
250
251
        global $_configuration;
252
        $original_password = $password;
253
254
        $access_url_id = 1;
255
        if (api_get_multiple_access_url()) {
256
            $access_url_id = api_get_current_access_url_id();
257
        }
258
259 View Code Duplication
        if (isset($_configuration[$access_url_id]) &&
260
            is_array($_configuration[$access_url_id]) &&
261
            isset($_configuration[$access_url_id]['hosting_limit_users']) &&
262
            $_configuration[$access_url_id]['hosting_limit_users'] > 0) {
263
            $num = self::get_number_of_users();
264
            if ($num >= $_configuration[$access_url_id]['hosting_limit_users']) {
265
                api_warn_hosting_contact('hosting_limit_users');
266
                Display::addFlash(Display::return_message(get_lang('PortalUsersLimitReached'), 'warning'));
267
268
                return false;
269
            }
270
        }
271
272 View Code Duplication
        if ($status === 1 &&
273
            isset($_configuration[$access_url_id]) &&
274
            is_array($_configuration[$access_url_id]) &&
275
            isset($_configuration[$access_url_id]['hosting_limit_teachers']) &&
276
            $_configuration[$access_url_id]['hosting_limit_teachers'] > 0
277
        ) {
278
            $num = self::get_number_of_users(1);
279
            if ($num >= $_configuration[$access_url_id]['hosting_limit_teachers']) {
280
                Display::addFlash(Display::return_message(get_lang('PortalTeachersLimitReached'), 'warning'));
281
                api_warn_hosting_contact('hosting_limit_teachers');
282
283
                return false;
284
            }
285
        }
286
287
        if (empty($password)) {
288
            if ($authSource === PLATFORM_AUTH_SOURCE) {
289
                Display::addFlash(
290
                    Display::return_message(
291
                        get_lang('ThisFieldIsRequired').': '.get_lang(
292
                            'Password'
293
                        ),
294
                        'warning'
295
                    )
296
                );
297
298
                return false;
299
            }
300
301
            // We use the authSource as password.
302
            // The real validation will be by processed by the auth
303
            // source not Chamilo
304
            $password = $authSource;
305
        }
306
307
        // database table definition
308
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
309
310
        // Checking the user language
311
        $languages = api_get_languages();
312
        $language = strtolower($language);
313
314 View Code Duplication
        if (isset($languages['folder'])) {
315
            if (!in_array($language, $languages['folder'])) {
316
                $language = api_get_setting('platformLanguage');
317
            }
318
        }
319
320
        if (!empty($currentUserId)) {
321
            $creator_id = $currentUserId;
322
        } else {
323
            $creator_id = 0;
324
        }
325
326
        $currentDate = api_get_utc_datetime();
327
        $now = new DateTime();
328
329
        if (empty($expirationDate) || $expirationDate == '0000-00-00 00:00:00') {
330
            // Default expiration date
331
            // if there is a default duration of a valid account then
332
            // we have to change the expiration_date accordingly
333
            // Accept 0000-00-00 00:00:00 as a null value to avoid issues with
334
            // third party code using this method with the previous (pre-1.10)
335
            // value of 0000...
336
            if (api_get_setting('account_valid_duration') != '') {
337
                $expirationDate = new DateTime($currentDate);
338
                $days = intval(api_get_setting('account_valid_duration'));
339
                $expirationDate->modify('+'.$days.' day');
340
            }
341
        } else {
342
            $expirationDate = api_get_utc_datetime($expirationDate);
343
            $expirationDate = new \DateTime($expirationDate, new DateTimeZone('UTC'));
344
        }
345
346
        $userManager = self::getManager();
347
348
        /** @var User $user */
349
        $user = $userManager->createUser();
350
351
        $user
352
            ->setLastname($lastName)
353
            ->setFirstname($firstName)
354
            ->setUsername($loginName)
355
            ->setStatus($status)
356
            ->setPlainPassword($password)
357
            ->setEmail($email)
358
            ->setOfficialCode($official_code)
359
            ->setPictureUri($picture_uri)
360
            ->setCreatorId($creator_id)
361
            ->setAuthSource($authSource)
362
            ->setPhone($phone)
363
            ->setAddress($address)
364
            ->setLanguage($language)
365
            ->setRegistrationDate($now)
366
            ->setHrDeptId($hr_dept_id)
367
            ->setActive($active)
368
            ->setEnabled($active)
369
        ;
370
371
        if (!empty($expirationDate)) {
372
            $user->setExpirationDate($expirationDate);
0 ignored issues
show
Bug introduced by
It seems like $expirationDate defined by parameter $expirationDate on line 225 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...
373
        }
374
375
        $userManager->updateUser($user);
376
        $userId = $user->getId();
377
378
        if (!empty($userId)) {
379
            $return = $userId;
380
            $sql = "UPDATE $table_user SET user_id = $return WHERE id = $return";
381
            Database::query($sql);
382
383
            if ($isAdmin) {
384
                UserManager::add_user_as_admin($user);
385
            }
386
387
            if (api_get_multiple_access_url()) {
388
                UrlManager::add_user_to_url($userId, api_get_current_access_url_id());
389
            } else {
390
                //we are adding by default the access_url_user table with access_url_id = 1
391
                UrlManager::add_user_to_url($userId, 1);
392
            }
393
394
            if (is_array($extra) && count($extra) > 0) {
395
                foreach ($extra as $fname => $fvalue) {
396
                    self::update_extra_field_value($userId, $fname, $fvalue);
397
                }
398
            } else {
399
                // Create notify settings by default
400
                self::update_extra_field_value($userId, 'mail_notify_invitation', '1');
401
                self::update_extra_field_value($userId, 'mail_notify_message', '1');
402
                self::update_extra_field_value($userId, 'mail_notify_group_message', '1');
403
            }
404
405
            self::update_extra_field_value($userId, 'already_logged_in', 'false');
406
407
            if (!empty($email) && $send_mail) {
408
                $recipient_name = api_get_person_name(
409
                    $firstName,
410
                    $lastName,
411
                    null,
412
                    PERSON_NAME_EMAIL_ADDRESS
413
                );
414
                $tplSubject = new Template(null, false, false, false, false, false);
415
                $layoutSubject = $tplSubject->get_template(
416
                    'mail/subject_registration_platform.tpl'
417
                );
418
                $emailSubject = $tplSubject->fetch($layoutSubject);
419
                $sender_name = api_get_person_name(
420
                    api_get_setting('administratorName'),
421
                    api_get_setting('administratorSurname'),
422
                    null,
423
                    PERSON_NAME_EMAIL_ADDRESS
424
                );
425
                $email_admin = api_get_setting('emailAdministrator');
426
427
                if (api_is_multiple_url_enabled()) {
428
                    $access_url_id = api_get_current_access_url_id();
429
                    if ($access_url_id != -1) {
430
                        $url = api_get_access_url($access_url_id);
431
                    }
432
                } else {
433
                    $url = api_get_path(WEB_PATH);
434
                }
435
                $tplContent = new Template(null, false, false, false, false, false);
436
                // variables for the default template
437
                $tplContent->assign('complete_name', stripslashes(api_get_person_name($firstName, $lastName)));
438
                $tplContent->assign('login_name', $loginName);
439
                $tplContent->assign('original_password', stripslashes($original_password));
440
                $tplContent->assign('mailWebPath', $url);
441
                $tplContent->assign('new_user', $user);
442
443
                $layoutContent = $tplContent->get_template('mail/content_registration_platform.tpl');
444
                $emailBody = $tplContent->fetch($layoutContent);
445
                /* MANAGE EVENT WITH MAIL */
446
                if (EventsMail::check_if_using_class('user_registration')) {
447
                    $values["about_user"] = $return;
448
                    $values["password"] = $original_password;
449
                    $values["send_to"] = array($return);
450
                    $values["prior_lang"] = null;
451
                    EventsDispatcher::events('user_registration', $values);
452
                } else {
453
                    $phoneNumber = isset($extra['mobile_phone_number']) ? $extra['mobile_phone_number'] : null;
454
455
                    $additionalParameters = array(
456
                        'smsType' => SmsPlugin::WELCOME_LOGIN_PASSWORD,
457
                        'userId' => $return,
458
                        'mobilePhoneNumber' => $phoneNumber,
459
                        'password' => $original_password
460
                    );
461
462
                    api_mail_html(
463
                        $recipient_name,
464
                        $email,
465
                        $emailSubject,
466
                        $emailBody,
467
                        $sender_name,
468
                        $email_admin,
469
                        null,
470
                        null,
471
                        null,
472
                        $additionalParameters
473
                    );
474
                }
475
476
                if ($sendEmailToAllAdmins) {
477
                    $adminList = UserManager::get_all_administrators();
478
479
                    $tplContent = new Template(null, false, false, false, false, false);
480
                    // variables for the default template
481
                    $tplContent->assign('complete_name', stripslashes(api_get_person_name($firstName, $lastName)));
482
                    $tplContent->assign('user_added', $user);
483
484
                    $renderer = FormValidator::getDefaultRenderer();
485
486
                    // Form template
487
                    $elementTemplate = ' {label}: {element} <br />';
488
                    $renderer->setElementTemplate($elementTemplate);
489
                    /** @var FormValidator $form */
490
                    $form->freeze(null, $elementTemplate);
491
                    $form->removeElement('submit');
492
                    $formData = $form->returnForm();
493
                    $url = api_get_path(WEB_CODE_PATH).'admin/user_information.php?user_id='.$user->getId();
494
                    $tplContent->assign('link', Display::url($url, $url));
495
                    $tplContent->assign('form', $formData);
496
497
                    $layoutContent = $tplContent->get_template('mail/content_registration_platform_to_admin.tpl');
498
                    $emailBody = $tplContent->fetch($layoutContent);
499
                    $subject = get_lang('UserAdded');
500
501
                    foreach ($adminList as $adminId => $data) {
502
                        MessageManager::send_message_simple($adminId, $subject, $emailBody);
503
                    }
504
505
                }
506
                /* ENDS MANAGE EVENT WITH MAIL */
507
            }
508
509
            if (!empty($hook)) {
510
                $hook->setEventData(array(
511
                    'return' => $userId,
512
                    'originalPassword' => $original_password
513
                ));
514
                $hook->notifyCreateUser(HOOK_EVENT_TYPE_POST);
515
            }
516
            Event::addEvent(LOG_USER_CREATE, LOG_USER_ID, $userId);
517
        } else {
518
            Display::addFlash(Display::return_message(get_lang('ErrorContactPlatformAdmin')));
519
520
            return false;
521
        }
522
523
        return $return;
524
    }
525
526
    /**
527
     * Can user be deleted? This function checks whether there's a course
528
     * in which the given user is the
529
     * only course administrator. If that is the case, the user can't be
530
     * deleted because the course would remain without a course admin.
531
     * @param int $user_id The user id
532
     * @return boolean true if user can be deleted
533
     * @assert (null) === false
534
     * @assert (-1) === false
535
     * @assert ('abc') === false
536
     */
537
    public static function can_delete_user($user_id)
538
    {
539
        $deny = api_get_configuration_value('deny_delete_users');
540
541
        if ($deny) {
542
            return false;
543
        }
544
545
        $table_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
546
        if ($user_id != strval(intval($user_id))) {
547
            return false;
548
        }
549
        if ($user_id === false) {
550
            return false;
551
        }
552
        $sql = "SELECT * FROM $table_course_user
553
                WHERE status = 1 AND user_id = ".$user_id;
554
        $res = Database::query($sql);
555
        while ($course = Database::fetch_object($res)) {
556
            $sql = "SELECT id FROM $table_course_user
557
                    WHERE status=1 AND c_id = " . intval($course->c_id);
558
            $res2 = Database::query($sql);
559
            if (Database::num_rows($res2) == 1) {
560
561
                return false;
562
            }
563
        }
564
565
        return true;
566
    }
567
568
    /**
569
     * Delete a user from the platform, and all its belongings. This is a
570
     * very dangerous function that should only be accessible by
571
     * super-admins. Other roles should only be able to disable a user,
572
     * which removes access to the platform but doesn't delete anything.
573
     * @param int The ID of th user to be deleted
574
     * @return boolean true if user is successfully deleted, false otherwise
575
     * @assert (null) === false
576
     * @assert ('abc') === false
577
     */
578
    public static function delete_user($user_id)
579
    {
580
        if ($user_id != strval(intval($user_id))) {
581
            return false;
582
        }
583
584
        if ($user_id === false) {
585
            return false;
586
        }
587
588
        if (!self::can_delete_user($user_id)) {
589
            return false;
590
        }
591
592
        $table_user = Database :: get_main_table(TABLE_MAIN_USER);
593
        $usergroup_rel_user = Database :: get_main_table(TABLE_USERGROUP_REL_USER);
594
        $table_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
595
        $table_course = Database :: get_main_table(TABLE_MAIN_COURSE);
596
        $table_session = Database :: get_main_table(TABLE_MAIN_SESSION);
597
        $table_admin = Database :: get_main_table(TABLE_MAIN_ADMIN);
598
        $table_session_user = Database :: get_main_table(TABLE_MAIN_SESSION_USER);
599
        $table_session_course_user = Database :: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
600
        $table_group = Database :: get_course_table(TABLE_GROUP_USER);
601
        $table_work = Database :: get_course_table(TABLE_STUDENT_PUBLICATION);
602
603
        // Unsubscribe the user from all groups in all his courses
604
        $sql = "SELECT c.id FROM $table_course c, $table_course_user cu
605
                WHERE
606
                    cu.user_id = '".$user_id."' AND
607
                    relation_type<>".COURSE_RELATION_TYPE_RRHH." AND
608
                    c.id = cu.c_id";
609
610
        $res = Database::query($sql);
611
        while ($course = Database::fetch_object($res)) {
612
            $sql = "DELETE FROM $table_group
613
                    WHERE c_id = {$course->id} AND user_id = $user_id";
614
            Database::query($sql);
615
        }
616
617
        // Unsubscribe user from usergroup_rel_user
618
        $sql = "DELETE FROM $usergroup_rel_user WHERE user_id = '".$user_id."'";
619
        Database::query($sql);
620
621
        // Unsubscribe user from all courses
622
        $sql = "DELETE FROM $table_course_user WHERE user_id = '".$user_id."'";
623
        Database::query($sql);
624
625
        // Unsubscribe user from all courses in sessions
626
        $sql = "DELETE FROM $table_session_course_user WHERE user_id = '".$user_id."'";
627
        Database::query($sql);
628
629
        // If the user was added as a id_coach then set the current admin as coach see BT#
630
        $currentUserId = api_get_user_id();
631
        $sql = "UPDATE $table_session SET id_coach = $currentUserId
632
                WHERE id_coach = '".$user_id."'";
633
        Database::query($sql);
634
635
        $sql = "UPDATE $table_session SET id_coach = $currentUserId
636
                WHERE session_admin_id = '".$user_id."'";
637
        Database::query($sql);
638
639
        // Unsubscribe user from all sessions
640
        $sql = "DELETE FROM $table_session_user
641
                WHERE user_id = '".$user_id."'";
642
        Database::query($sql);
643
644
        // Delete user picture
645
        /* TODO: Logic about api_get_setting('split_users_upload_directory') == 'true'
646
        a user has 4 different sized photos to be deleted. */
647
        $user_info = api_get_user_info($user_id);
648
649
        if (strlen($user_info['picture_uri']) > 0) {
650
            $path = self::getUserPathById($user_id, 'system');
651
            $img_path = $path.$user_info['picture_uri'];
652
            if (file_exists($img_path)) {
653
                unlink($img_path);
654
            }
655
        }
656
657
        // Delete the personal course categories
658
        $course_cat_table = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
659
        $sql = "DELETE FROM $course_cat_table WHERE user_id = '".$user_id."'";
660
        Database::query($sql);
661
662
        // Delete user from the admin table
663
        $sql = "DELETE FROM $table_admin WHERE user_id = '".$user_id."'";
664
        Database::query($sql);
665
666
        // Delete the personal agenda-items from this user
667
        $agenda_table = Database :: get_main_table(TABLE_PERSONAL_AGENDA);
668
        $sql = "DELETE FROM $agenda_table WHERE user = '".$user_id."'";
669
        Database::query($sql);
670
671
        $gradebook_results_table = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_RESULT);
672
        $sql = 'DELETE FROM '.$gradebook_results_table.' WHERE user_id = '.$user_id;
673
        Database::query($sql);
674
675
        $extraFieldValue = new ExtraFieldValue('user');
676
        $extraFieldValue->deleteValuesByItem($user_id);
677
678
        UrlManager::deleteUserFromAllUrls($user_id);
679
680
        if (api_get_setting('allow_social_tool') == 'true') {
681
            $userGroup = new UserGroup();
682
            //Delete user from portal groups
683
            $group_list = $userGroup->get_groups_by_user($user_id);
684
            if (!empty($group_list)) {
685
                foreach ($group_list as $group_id => $data) {
686
                    $userGroup->delete_user_rel_group($user_id, $group_id);
687
                }
688
            }
689
690
            // Delete user from friend lists
691
            SocialManager::remove_user_rel_user($user_id, true);
692
        }
693
694
        // Removing survey invitation
695
        SurveyManager::delete_all_survey_invitations_by_user($user_id);
696
697
        // Delete students works
698
        $sql = "DELETE FROM $table_work WHERE user_id = $user_id AND c_id <> 0";
699
        Database::query($sql);
700
701
        $sql = "UPDATE c_item_property SET to_user_id = NULL
702
                WHERE to_user_id = '".$user_id."'";
703
        Database::query($sql);
704
705
        $sql = "UPDATE c_item_property SET insert_user_id = NULL
706
                WHERE insert_user_id = '".$user_id."'";
707
        Database::query($sql);
708
709
        $sql = "UPDATE c_item_property SET lastedit_user_id = NULL
710
                WHERE lastedit_user_id = '".$user_id."'";
711
        Database::query($sql);
712
713
        // Skills
714
        $table = Database::get_main_table(TABLE_MAIN_SKILL_REL_USER);
715
        $sql = "DELETE FROM $table WHERE user_id = $user_id";
716
        Database::query($sql);
717
718
        // Delete user from database
719
        $sql = "DELETE FROM $table_user WHERE id = '".$user_id."'";
720
        Database::query($sql);
721
722
        // Add event to system log
723
        $user_id_manager = api_get_user_id();
724
725
        Event::addEvent(
726
            LOG_USER_DELETE,
727
            LOG_USER_ID,
728
            $user_id,
729
            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...
730
            $user_id_manager
731
        );
732
733
        Event::addEvent(
734
            LOG_USER_DELETE,
735
            LOG_USER_OBJECT,
736
            $user_info,
737
            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...
738
            $user_id_manager
739
        );
740
741
        return true;
742
    }
743
744
    /**
745
     * Deletes users completely. Can be called either as:
746
     * - UserManager :: delete_users(1, 2, 3); or
747
     * - UserManager :: delete_users(array(1, 2, 3));
748
     * @param array|int $ids
749
     * @return boolean  True if at least one user was successfuly deleted. False otherwise.
750
     * @author Laurent Opprecht
751
     * @uses UserManager::delete_user() to actually delete each user
752
     * @assert (null) === false
753
     * @assert (-1) === false
754
     * @assert (array(-1)) === false
755
     */
756
    public static function delete_users($ids = array())
757
    {
758
        $result = false;
759
        $ids = is_array($ids) ? $ids : func_get_args();
760
        if (!is_array($ids) || count($ids) == 0) {
761
            return false;
762
        }
763
        $ids = array_map('intval', $ids);
764
        foreach ($ids as $id) {
765
            if (empty($id) || $id < 1) {
766
                continue;
767
            }
768
            $deleted = self::delete_user($id);
769
            $result = $deleted || $result;
770
        }
771
772
        return $result;
773
    }
774
775
    /**
776
     * Disable users. Can be called either as:
777
     * - UserManager :: deactivate_users(1, 2, 3);
778
     * - UserManager :: deactivate_users(array(1, 2, 3));
779
     * @param array|int $ids
780
     * @return boolean
781
     * @author Laurent Opprecht
782
     * @assert (null) === false
783
     * @assert (array(-1)) === false
784
     */
785 View Code Duplication
    public static function deactivate_users($ids = array())
786
    {
787
        if (empty($ids)) {
788
789
            return false;
790
        }
791
792
        $table_user = Database :: get_main_table(TABLE_MAIN_USER);
793
794
        $ids = is_array($ids) ? $ids : func_get_args();
795
        $ids = array_map('intval', $ids);
796
        $ids = implode(',', $ids);
797
798
        $sql = "UPDATE $table_user SET active = 0 WHERE id IN ($ids)";
799
        $r = Database::query($sql);
800
        if ($r !== false) {
801
            Event::addEvent(LOG_USER_DISABLE, LOG_USER_ID, $ids);
802
        }
803
        return $r;
804
    }
805
806
    /**
807
     * Enable users. Can be called either as:
808
     * - UserManager :: activate_users(1, 2, 3);
809
     * - UserManager :: activate_users(array(1, 2, 3));
810
     * @param array|int IDs of the users to enable
811
     * @return boolean
812
     * @author Laurent Opprecht
813
     * @assert (null) === false
814
     * @assert (array(-1)) === false
815
     */
816 View Code Duplication
    public static function activate_users($ids = array())
817
    {
818
        if (empty($ids)) {
819
820
            return false;
821
        }
822
823
        $table_user = Database :: get_main_table(TABLE_MAIN_USER);
824
825
        $ids = is_array($ids) ? $ids : func_get_args();
826
        $ids = array_map('intval', $ids);
827
        $ids = implode(',', $ids);
828
829
        $sql = "UPDATE $table_user SET active = 1 WHERE id IN ($ids)";
830
        $r = Database::query($sql);
831
        if ($r !== false) {
832
            Event::addEvent(LOG_USER_ENABLE, LOG_USER_ID, $ids);
833
        }
834
        return $r;
835
    }
836
837
    /**
838
     * Update user information with new openid
839
     * @param int $user_id
840
     * @param string $openid
841
     * @return boolean true if the user information was updated
842
     * @assert (false,'') === false
843
     * @assert (-1,'') === false
844
     */
845
    public static function update_openid($user_id, $openid)
846
    {
847
        $table_user = Database:: get_main_table(TABLE_MAIN_USER);
848
        if ($user_id != strval(intval($user_id))) {
849
            return false;
850
        }
851
        if ($user_id === false) {
852
            return false;
853
        }
854
        $sql = "UPDATE $table_user SET
855
                openid='".Database::escape_string($openid)."'";
856
        $sql .= " WHERE id= $user_id";
857
858
        return Database::query($sql);
859
    }
860
861
    /**
862
     * Update user information with all the parameters passed to this function
863
     * @param int The ID of the user to be updated
864
     * @param string The user's firstname
865
     * @param string The user's lastname
866
     * @param string The user's username (login)
867
     * @param string The user's password
868
     * @param string The authentication source (default: "platform")
869
     * @param string The user's e-mail address
870
     * @param int The user's status
871
     * @param string The user's official code (usually just an internal institutional code)
872
     * @param string The user's phone number
873
     * @param string The user's picture URL (internal to the Chamilo directory)
874
     * @param int The user ID of the person who registered this user (optional, defaults to null)
875
     * @param int The department of HR in which the user is registered (optional, defaults to 0)
876
     * @param array A series of additional fields to add to this user as extra fields (optional, defaults to null)
877
     * @return boolean|integer False on error, or the user ID if the user information was updated
878
     * @assert (false, false, false, false, false, false, false, false, false, false, false, false, false) === false
879
     */
880
    public static function update_user(
881
        $user_id,
882
        $firstname,
883
        $lastname,
884
        $username,
885
        $password = null,
886
        $auth_source = null,
887
        $email,
888
        $status,
889
        $official_code,
890
        $phone,
891
        $picture_uri,
892
        $expiration_date,
893
        $active,
894
        $creator_id = null,
895
        $hr_dept_id = 0,
896
        $extra = null,
897
        $language = 'english',
898
        $encrypt_method = '',
899
        $send_email = false,
900
        $reset_password = 0,
901
        $address = null
902
    ) {
903
        $hook = HookUpdateUser::create();
904
        if (!empty($hook)) {
905
            $hook->notifyUpdateUser(HOOK_EVENT_TYPE_PRE);
906
        }
907
        $original_password = $password;
908
909
        if ($user_id != strval(intval($user_id))) {
910
            return false;
911
        }
912
913
        if (empty($user_id)) {
914
            return false;
915
        }
916
917
        $userManager = self::getManager();
918
        /** @var Chamilo\UserBundle\Entity\User $user */
919
        $user = self::getRepository()->find($user_id);
920
921
        if (empty($user)) {
922
            return false;
923
        }
924
925
        if ($reset_password == 0) {
926
            $password = null;
927
            $auth_source = $user->getAuthSource();
928
        } elseif ($reset_password == 1) {
929
            $original_password = $password = api_generate_password();
930
            $auth_source = PLATFORM_AUTH_SOURCE;
931
        } elseif ($reset_password == 2) {
932
            $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...
933
            $auth_source = PLATFORM_AUTH_SOURCE;
934
        } elseif ($reset_password == 3) {
935
            $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...
936
            $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...
937
        }
938
939
        // Checking the user language
940
        $languages = api_get_languages();
941
        if (!in_array($language, $languages['folder'])) {
942
            $language = api_get_setting('platformLanguage');
943
        }
944
945
        $change_active = 0;
946
        $isUserActive = $user->getActive();
947
        if ($isUserActive != $active) {
948
            $change_active = 1;
949
        }
950
951
        $originalUsername = $user->getUsername();
952
953
        // If username is different from original then check if it exists.
954
        if ($originalUsername !== $username) {
955
            $available = self::is_username_available($username);
956
            if ($available === false) {
957
                return false;
958
            }
959
        }
960
961
        if (!empty($expiration_date)) {
962
            $expiration_date = api_get_utc_datetime($expiration_date);
963
            $expiration_date = new \DateTime(
964
                $expiration_date,
965
                new DateTimeZone('UTC')
966
            );
967
        }
968
969
        $user
970
            ->setLastname($lastname)
971
            ->setFirstname($firstname)
972
            ->setUsername($username)
973
            ->setStatus($status)
974
            ->setAuthSource($auth_source)
975
            ->setLanguage($language)
976
            ->setEmail($email)
977
            ->setOfficialCode($official_code)
978
            ->setPhone($phone)
979
            ->setAddress($address)
980
            ->setPictureUri($picture_uri)
981
            ->setExpirationDate($expiration_date)
982
            ->setActive($active)
983
            ->setEnabled($active)
984
            ->setHrDeptId($hr_dept_id)
985
        ;
986
987
        if (!is_null($password)) {
988
            $user->setPlainPassword($password);
989
        }
990
991
        $userManager->updateUser($user, true);
992
993
        if ($change_active == 1) {
994
            if ($active == 1) {
995
                $event_title = LOG_USER_ENABLE;
996
            } else {
997
                $event_title = LOG_USER_DISABLE;
998
            }
999
            Event::addEvent($event_title, LOG_USER_ID, $user_id);
1000
        }
1001
1002
        if (is_array($extra) && count($extra) > 0) {
1003
            $res = true;
1004
            foreach ($extra as $fname => $fvalue) {
1005
                $res = $res && self::update_extra_field_value(
1006
                    $user_id,
1007
                    $fname,
1008
                    $fvalue
1009
                );
1010
            }
1011
        }
1012
1013
        if (!empty($email) && $send_email) {
1014
            $recipient_name = api_get_person_name($firstname, $lastname, null, PERSON_NAME_EMAIL_ADDRESS);
1015
            $emailsubject = '['.api_get_setting('siteName').'] '.get_lang('YourReg').' '.api_get_setting('siteName');
1016
            $sender_name = api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'), null, PERSON_NAME_EMAIL_ADDRESS);
1017
            $email_admin = api_get_setting('emailAdministrator');
1018
1019
            if (api_is_multiple_url_enabled()) {
1020
                $access_url_id = api_get_current_access_url_id();
1021
                if ($access_url_id != -1) {
1022
                    $url = api_get_access_url($access_url_id);
1023
                    $emailbody = get_lang('Dear')." ".stripslashes(api_get_person_name($firstname, $lastname)).",\n\n".
1024
                        get_lang('YouAreReg')." ".api_get_setting('siteName')." ".get_lang('WithTheFollowingSettings')."\n\n".
1025
                        get_lang('Username')." : ".$username.(($reset_password > 0) ? "\n".
1026
                        get_lang('Pass')." : ".stripslashes($original_password) : "")."\n\n".
1027
                        get_lang('Address')." ".api_get_setting('siteName')." ".get_lang('Is')." : ".$url['url']."\n\n".
1028
                        get_lang('Problem')."\n\n".
1029
                        get_lang('SignatureFormula').",\n\n".
1030
                        api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'))."\n".
1031
                        get_lang('Manager')." ".api_get_setting('siteName')."\nT. ".api_get_setting('administratorTelephone')."\n".
1032
                        get_lang('Email')." : ".api_get_setting('emailAdministrator');
1033
                }
1034
            } else {
1035
                $emailbody = get_lang('Dear')." ".stripslashes(api_get_person_name($firstname, $lastname)).",\n\n".
1036
                    get_lang('YouAreReg')." ".api_get_setting('siteName')." ".get_lang('WithTheFollowingSettings')."\n\n".
1037
                    get_lang('Username')." : ".$username.(($reset_password > 0) ? "\n".
1038
                    get_lang('Pass')." : ".stripslashes($original_password) : "")."\n\n".
1039
                    get_lang('Address')." ".api_get_setting('siteName')." ".get_lang('Is')." : ".api_get_path(WEB_PATH)."\n\n".
1040
                    get_lang('Problem')."\n\n".
1041
                    get_lang('SignatureFormula').",\n\n".
1042
                    api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'))."\n".
1043
                    get_lang('Manager')." ".api_get_setting('siteName')."\nT. ".api_get_setting('administratorTelephone')."\n".
1044
                    get_lang('Email')." : ".api_get_setting('emailAdministrator');
1045
            }
1046
1047
            $emailbody = nl2br($emailbody);
1048
            api_mail_html(
1049
                $recipient_name,
1050
                $email,
1051
                $emailsubject,
1052
                $emailbody,
1053
                $sender_name,
1054
                $email_admin
1055
            );
1056
        }
1057
1058
        if (!empty($hook)) {
1059
            $hook->notifyUpdateUser(HOOK_EVENT_TYPE_POST);
1060
        }
1061
1062
        return $user->getId();
1063
    }
1064
1065
    /**
1066
     * Disables or enables a user
1067
     * @param int $user_id
1068
     * @param int $active Enable or disable
1069
     * @return void
1070
     * @assert (-1,0) === false
1071
     * @assert (1,1) === true
1072
     */
1073
    private static function change_active_state($user_id, $active)
1074
    {
1075
        if (strval(intval($user_id)) != $user_id) {
1076
            return false;
1077
        }
1078
        if ($user_id < 1) {
1079
            return false;
1080
        }
1081
        $user_id = intval($user_id);
1082
        $table_user = Database :: get_main_table(TABLE_MAIN_USER);
1083
        $sql = "UPDATE $table_user SET active = '$active' WHERE id = $user_id";
1084
        $r = Database::query($sql);
1085
        $ev = LOG_USER_DISABLE;
1086
        if ($active == 1) {
1087
            $ev = LOG_USER_ENABLE;
1088
        }
1089
        if ($r !== false) {
1090
            Event::addEvent($ev, LOG_USER_ID, $user_id);
1091
        }
1092
1093
        return $r;
1094
    }
1095
1096
    /**
1097
     * Disables a user
1098
     * @param int User id
1099
     * @return bool
1100
     * @uses UserManager::change_active_state() to actually disable the user
1101
     * @assert (0) === false
1102
     */
1103
    public static function disable($user_id)
1104
    {
1105
        if (empty($user_id)) {
1106
            return false;
1107
        }
1108
        self::change_active_state($user_id, 0);
1109
        return true;
1110
    }
1111
1112
    /**
1113
     * Enable a user
1114
     * @param int User id
1115
     * @return bool
1116
     * @uses UserManager::change_active_state() to actually disable the user
1117
     * @assert (0) === false
1118
     */
1119
    public static function enable($user_id)
1120
    {
1121
        if (empty($user_id)) {
1122
            return false;
1123
        }
1124
        self::change_active_state($user_id, 1);
1125
        return true;
1126
    }
1127
1128
    /**
1129
     * Returns the user's id based on the original id and field name in
1130
     * the extra fields. Returns 0 if no user was found. This function is
1131
     * mostly useful in the context of a web services-based sinchronization
1132
     * @param string Original user id
1133
     * @param string Original field name
1134
     * @return int User id
1135
     * @assert ('0','---') === 0
1136
     */
1137 View Code Duplication
    public static function get_user_id_from_original_id($original_user_id_value, $original_user_id_name)
1138
    {
1139
        $t_uf = Database::get_main_table(TABLE_EXTRA_FIELD);
1140
        $t_ufv = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
1141
        $extraFieldType = EntityExtraField::USER_FIELD_TYPE;
1142
        $sql = "SELECT item_id as user_id
1143
                FROM $t_uf uf
1144
                INNER JOIN $t_ufv ufv
1145
                ON ufv.field_id=uf.id
1146
                WHERE
1147
                    variable='$original_user_id_name' AND
1148
                    value='$original_user_id_value' AND
1149
                    extra_field_type = $extraFieldType
1150
                ";
1151
        $res = Database::query($sql);
1152
        $row = Database::fetch_object($res);
1153
        if ($row) {
1154
            return $row->user_id;
1155
        } else {
1156
            return 0;
1157
        }
1158
    }
1159
1160
    /**
1161
     * Check if a username is available
1162
     * @param string $username the wanted username
1163
     * @return boolean true if the wanted username is available
1164
     * @assert ('') === false
1165
     * @assert ('xyzxyzxyz') === true
1166
     */
1167 View Code Duplication
    public static function is_username_available($username)
1168
    {
1169
        if (empty($username)) {
1170
            return false;
1171
        }
1172
        $table_user = Database :: get_main_table(TABLE_MAIN_USER);
1173
        $sql = "SELECT username FROM $table_user
1174
                WHERE username = '".Database::escape_string($username)."'";
1175
        $res = Database::query($sql);
1176
1177
        return Database::num_rows($res) == 0;
1178
    }
1179
1180
    /**
1181
     * Creates a username using person's names, i.e. creates jmontoya from Julio Montoya.
1182
     * @param string $firstname The first name of the user.
1183
     * @param string $lastname The last name of the user.
1184
     * @return string Suggests a username that contains only ASCII-letters and digits,
1185
     * without check for uniqueness within the system.
1186
     * @author Julio Montoya Armas
1187
     * @author Ivan Tcholakov, 2009 - rework about internationalization.
1188
     * @assert ('','') === false
1189
     * @assert ('a','b') === 'ab'
1190
     */
1191
    public static function create_username($firstname, $lastname)
1192
    {
1193
        if (empty($firstname) && empty($lastname)) {
1194
1195
            return false;
1196
        }
1197
1198
        $firstname = api_substr(preg_replace(USERNAME_PURIFIER, '', $firstname), 0, 1); // The first letter only.
1199
        //Looking for a space in the lastname
1200
        $pos = api_strpos($lastname, ' ');
1201
        if ($pos !== false) {
1202
            $lastname = api_substr($lastname, 0, $pos);
1203
        }
1204
1205
        $lastname = preg_replace(USERNAME_PURIFIER, '', $lastname);
1206
        $username = $firstname.$lastname;
1207
        if (empty($username)) {
1208
            $username = 'user';
1209
        }
1210
1211
        $username = URLify::transliterate($username);
1212
1213
        return strtolower(substr($username, 0, USERNAME_MAX_LENGTH - 3));
1214
    }
1215
1216
    /**
1217
     * Creates a unique username, using:
1218
     * 1. the first name and the last name of a user;
1219
     * 2. an already created username but not checked for uniqueness yet.
1220
     * @param string $firstname                The first name of a given user. If the second parameter $lastname is NULL, then this
1221
     * parameter is treated as username which is to be checked for uniqueness and to be modified when it is necessary.
1222
     * @param string $lastname                The last name of the user.
1223
     * @return string                        Returns a username that contains only ASCII-letters and digits, and that is unique within the system.
1224
     * Note: When the method is called several times with same parameters, its results look like the following sequence: ivan, ivan2, ivan3, ivan4, ...
1225
     * @author Ivan Tcholakov, 2009
1226
     */
1227
    public static function create_unique_username($firstname, $lastname = null)
1228
    {
1229
        if (is_null($lastname)) {
1230
            // In this case the actual input parameter $firstname should contain ASCII-letters and digits only.
1231
            // For making this method tolerant of mistakes, let us transliterate and purify the suggested input username anyway.
1232
            // So, instead of the sentence $username = $firstname; we place the following:
1233
            $username = strtolower(preg_replace(USERNAME_PURIFIER, '', $firstname));
1234
        } else {
1235
            $username = self::create_username($firstname, $lastname);
1236
        }
1237
        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 1235 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...
1238
            $i = 2;
1239
            $temp_username = substr($username, 0, USERNAME_MAX_LENGTH - strlen((string) $i)).$i;
1240
            while (!self::is_username_available($temp_username)) {
1241
                $i++;
1242
                $temp_username = substr($username, 0, USERNAME_MAX_LENGTH - strlen((string) $i)).$i;
1243
            }
1244
            $username = $temp_username;
1245
        }
1246
1247
        $username = URLify::transliterate($username);
1248
1249
        return $username;
1250
    }
1251
1252
    /**
1253
     * Modifies a given username accordingly to the specification for valid characters and length.
1254
     * @param $username string          The input username.
1255
     * @param bool $strict (optional)   When this flag is TRUE, the result is guaranteed for full compliance,
1256
     * otherwise compliance may be partial. The default value is FALSE.
1257
     * @return string                   The resulting purified username.
1258
     */
1259
    public static function purify_username($username, $strict = false)
1260
    {
1261
        if ($strict) {
1262
            // 1. Conversion of unacceptable letters (latinian letters with accents for example)
1263
            // into ASCII letters in order they not to be totally removed.
1264
            // 2. Applying the strict purifier.
1265
            // 3. Length limitation.
1266
            $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);
1267
            $return = URLify::transliterate($return);
1268
1269
            return $return;
1270
        }
1271
1272
        // 1. Applying the shallow purifier.
1273
        // 2. Length limitation.
1274
        return substr(preg_replace(USERNAME_PURIFIER_SHALLOW, '', $username), 0, USERNAME_MAX_LENGTH);
1275
    }
1276
1277
    /**
1278
     * Checks whether the user id exists in the database
1279
     *
1280
     * @param int User id
1281
     * @return bool True if user id was found, false otherwise
1282
     */
1283 View Code Duplication
    public static function is_user_id_valid($userId)
1284
    {
1285
        $resultData = Database::select(
1286
            'COUNT(1) AS count',
1287
            Database::get_main_table(TABLE_MAIN_USER),
1288
            [
1289
                'where' => ['id = ?' => intval($userId)]
1290
            ],
1291
            'first'
1292
        );
1293
1294
        if ($resultData === false) {
1295
            return false;
1296
        }
1297
1298
        return $resultData['count'] > 0;
1299
    }
1300
1301
    /**
1302
     * Checks whether a given username matches to the specification strictly. The empty username is assumed here as invalid.
1303
     * Mostly this function is to be used in the user interface built-in validation routines for providing feedback while usernames are enterd manually.
1304
     * @param string $username The input username.
1305
     * @return bool Returns TRUE if the username is valid, FALSE otherwise.
1306
     */
1307
    public static function is_username_valid($username)
1308
    {
1309
        return !empty($username) && $username == self::purify_username($username, true);
1310
    }
1311
1312
    /**
1313
     * Checks whether a username is empty. If the username contains whitespace characters, such as spaces, tabulators, newlines, etc.,
1314
     * it is assumed as empty too. This function is safe for validation unpurified data (during importing).
1315
     * @param string $username The given username.
1316
     * @return bool  Returns TRUE if length of the username exceeds the limit, FALSE otherwise.
1317
     */
1318
    public static function is_username_empty($username)
1319
    {
1320
        return (strlen(self::purify_username($username, false)) == 0);
1321
    }
1322
1323
    /**
1324
     * Checks whether a username is too long or not.
1325
     * @param string $username The given username, it should contain only ASCII-letters and digits.
1326
     * @return bool Returns TRUE if length of the username exceeds the limit, FALSE otherwise.
1327
     */
1328
    public static function is_username_too_long($username)
1329
    {
1330
        return (strlen($username) > USERNAME_MAX_LENGTH);
1331
    }
1332
1333
    /**
1334
    * Get the users by ID
1335
    * @param array $ids student ids
1336
    * @param string $active
1337
    * @param string $order
1338
    * @param string $limit
1339
    * @return array $result student information
1340
    */
1341
    public static function get_user_list_by_ids($ids = array(), $active = null, $order = null, $limit = null)
1342
    {
1343
        if (empty($ids)) {
1344
1345
            return array();
1346
        }
1347
1348
        $ids = is_array($ids) ? $ids : array($ids);
1349
        $ids = array_map('intval', $ids);
1350
        $ids = implode(',', $ids);
1351
1352
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
1353
        $sql = "SELECT * FROM $tbl_user WHERE id IN ($ids)";
1354
        if (!is_null($active)) {
1355
            $sql .= ' AND active='.($active ? '1' : '0');
1356
        }
1357
1358
        if (!is_null($order)) {
1359
            $order = Database::escape_string($order);
1360
            $sql .= ' ORDER BY ' . $order;
1361
        }
1362
1363
        if (!is_null($limit)) {
1364
            $limit = Database::escape_string($limit);
1365
            $sql .= ' LIMIT ' . $limit;
1366
        }
1367
1368
        $rs = Database::query($sql);
1369
        $result = array();
1370
        while ($row = Database::fetch_array($rs)) {
1371
            $result[] = $row;
1372
        }
1373
1374
        return $result;
1375
    }
1376
1377
    /**
1378
     * Get a list of users of which the given conditions match with an = 'cond'
1379
     * @param array $conditions a list of condition (example : status=>STUDENT)
1380
     * @param array $order_by a list of fields on which sort
1381
     * @return array An array with all users of the platform.
1382
     * @todo optional course code parameter, optional sorting parameters...
1383
     * @todo security filter order by
1384
     */
1385
    public static function get_user_list(
1386
        $conditions = array(),
1387
        $order_by = array(),
1388
        $limit_from = false,
1389
        $limit_to = false
1390
    ) {
1391
        $user_table = Database :: get_main_table(TABLE_MAIN_USER);
1392
        $return_array = array();
1393
        $sql_query = "SELECT * FROM $user_table";
1394
        if (count($conditions) > 0) {
1395
            $sql_query .= ' WHERE ';
1396
            foreach ($conditions as $field => $value) {
1397
                $field = Database::escape_string($field);
1398
                $value = Database::escape_string($value);
1399
                $sql_query .= "$field = '$value'";
1400
            }
1401
        }
1402 View Code Duplication
        if (count($order_by) > 0) {
1403
            $sql_query .= ' ORDER BY '.Database::escape_string(implode(',', $order_by), null, false);
1404
        }
1405
1406
        if (is_numeric($limit_from) && is_numeric($limit_from)) {
1407
            $limit_from = intval($limit_from);
1408
            $limit_to = intval($limit_to);
1409
            $sql_query .= " LIMIT $limit_from, $limit_to";
1410
        }
1411
        $sql_result = Database::query($sql_query);
1412 View Code Duplication
        while ($result = Database::fetch_array($sql_result)) {
1413
            $result['complete_name'] = api_get_person_name($result['firstname'], $result['lastname']);
1414
            $return_array[] = $result;
1415
        }
1416
        return $return_array;
1417
    }
1418
1419
    /**
1420
     * Get a list of users of which the given conditions match with a LIKE '%cond%'
1421
     * @param array $conditions a list of condition (exemple : status=>STUDENT)
1422
     * @param array $order_by a list of fields on which sort
1423
     * @return array An array with all users of the platform.
1424
     * @todo optional course code parameter, optional sorting parameters...
1425
     * @todo security filter order_by
1426
     */
1427
    public static function get_user_list_like(
1428
        $conditions = array(),
1429
        $order_by = array(),
1430
        $simple_like = false,
1431
        $condition = 'AND'
1432
    ) {
1433
        $user_table = Database :: get_main_table(TABLE_MAIN_USER);
1434
        $tblAccessUrlRelUser = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
1435
        $return_array = array();
1436
        $sql_query = "SELECT * FROM $user_table ";
1437
1438
        if (api_is_multiple_url_enabled()) {
1439
            $sql_query .= " INNER JOIN $tblAccessUrlRelUser auru ON auru.user_id = user.id ";
1440
        }
1441
1442
        if (count($conditions) > 0) {
1443
            $sql_query .= ' WHERE ';
1444
            $temp_conditions = array();
1445
            foreach ($conditions as $field => $value) {
1446
                $field = Database::escape_string($field);
1447
                $value = Database::escape_string($value);
1448 View Code Duplication
                if ($simple_like) {
1449
                    $temp_conditions[] = $field." LIKE '$value%'";
1450
                } else {
1451
                    $temp_conditions[] = $field.' LIKE \'%'.$value.'%\'';
1452
                }
1453
            }
1454
            if (!empty($temp_conditions)) {
1455
                $sql_query .= implode(' '.$condition.' ', $temp_conditions);
1456
            }
1457
1458
            if (api_is_multiple_url_enabled()) {
1459
                $sql_query .= ' AND auru.access_url_id = ' . api_get_current_access_url_id();
1460
            }
1461
        } else {
1462
            if (api_is_multiple_url_enabled()) {
1463
                $sql_query .= ' WHERE auru.access_url_id = ' . api_get_current_access_url_id();
1464
            }
1465
        }
1466 View Code Duplication
        if (count($order_by) > 0) {
1467
            $sql_query .= ' ORDER BY '.Database::escape_string(implode(',', $order_by), null, false);
1468
        }
1469
        $sql_result = Database::query($sql_query);
1470 View Code Duplication
        while ($result = Database::fetch_array($sql_result)) {
1471
1472
            $result['complete_name'] = api_get_person_name(
1473
                $result['firstname'],
1474
                $result['lastname']
1475
            );
1476
            $return_array[] = $result;
1477
        }
1478
1479
        return $return_array;
1480
    }
1481
1482
    /**
1483
     * Get user picture URL or path from user ID (returns an array).
1484
     * The return format is a complete path, enabling recovery of the directory
1485
     * with dirname() or the file with basename(). This also works for the
1486
     * functions dealing with the user's productions, as they are located in
1487
     * the same directory.
1488
     * @param   integer   $id User ID
1489
     * @param   string    $type Type of path to return (can be 'system', 'web')
1490
     * @param   array $userInfo user information to avoid query the DB
1491
     * returns the /main/img/unknown.jpg image set it at true
1492
     *
1493
     * @return    array     Array of 2 elements: 'dir' and 'file' which contain
1494
     * the dir and file as the name implies if image does not exist it will
1495
     * return the unknow image if anonymous parameter is true if not it returns an empty array
1496
     */
1497 View Code Duplication
    public static function get_user_picture_path_by_id($id, $type = 'web', $userInfo = [])
1498
    {
1499
        switch ($type) {
1500
            case 'system': // Base: absolute system path.
1501
                $base = api_get_path(SYS_CODE_PATH);
1502
                break;
1503
            case 'web': // Base: absolute web path.
1504
            default:
1505
                $base = api_get_path(WEB_CODE_PATH);
1506
                break;
1507
        }
1508
1509
        $anonymousPath = array(
1510
            'dir' => $base.'img/',
1511
            'file' => 'unknown.jpg',
1512
            'email' => ''
1513
        );
1514
1515
        if (empty($id) || empty($type)) {
1516
            return $anonymousPath;
1517
        }
1518
1519
        $id = intval($id);
1520
        if (empty($userInfo)) {
1521
            $user_table = Database:: get_main_table(TABLE_MAIN_USER);
1522
            $sql = "SELECT email, picture_uri FROM $user_table
1523
                    WHERE id=".$id;
1524
            $res = Database::query($sql);
1525
1526
            if (!Database::num_rows($res)) {
1527
                return $anonymousPath;
1528
            }
1529
            $user = Database::fetch_array($res);
1530
            if (empty($user['picture_uri'])) {
1531
                return $anonymousPath;
1532
            }
1533
        } else {
1534
            $user = $userInfo;
1535
        }
1536
1537
        $pictureFilename = trim($user['picture_uri']);
1538
1539
        $dir = self::getUserPathById($id, $type);
1540
1541
        return array(
1542
            'dir' => $dir,
1543
            'file' => $pictureFilename,
1544
            'email' => $user['email']
1545
        );
1546
    }
1547
1548
    /**
1549
     * *** READ BEFORE REVIEW THIS FUNCTION ***
1550
     * This function is a exact copy from get_user_picture_path_by_id() and it was create it to avoid
1551
     * a recursive calls for get_user_picture_path_by_id() in another functions when you update a user picture
1552
     * in same script, so you can find this function usage in update_user_picture() function.
1553
     *
1554
     * @param   integer   $id User ID
1555
     * @param   string    $type Type of path to return (can be 'system', 'web')
1556
     * @param   array $userInfo user information to avoid query the DB
1557
     * returns the /main/img/unknown.jpg image set it at true
1558
     *
1559
     * @return    array     Array of 2 elements: 'dir' and 'file' which contain
1560
     * the dir and file as the name implies if image does not exist it will
1561
     * return the unknow image if anonymous parameter is true if not it returns an empty array
1562
     */
1563 View Code Duplication
    public static function getUserPicturePathById($id, $type = 'web', $userInfo = [])
1564
    {
1565
        switch ($type) {
1566
            case 'system': // Base: absolute system path.
1567
                $base = api_get_path(SYS_CODE_PATH);
1568
                break;
1569
            case 'web': // Base: absolute web path.
1570
            default:
1571
                $base = api_get_path(WEB_CODE_PATH);
1572
                break;
1573
        }
1574
1575
        $anonymousPath = array(
1576
            'dir' => $base.'img/',
1577
            'file' => 'unknown.jpg',
1578
            'email' => ''
1579
        );
1580
1581
        if (empty($id) || empty($type)) {
1582
            return $anonymousPath;
1583
        }
1584
1585
        $id = intval($id);
1586
1587
        if (empty($userInfo)) {
1588
            $user_table = Database:: get_main_table(TABLE_MAIN_USER);
1589
            $sql = "SELECT email, picture_uri FROM $user_table WHERE id=$id";
1590
            $res = Database::query($sql);
1591
1592
            if (!Database::num_rows($res)) {
1593
                return $anonymousPath;
1594
            }
1595
            $user = Database::fetch_array($res);
1596
1597
            if (empty($user['picture_uri'])) {
1598
                return $anonymousPath;
1599
            }
1600
        } else {
1601
            $user = $userInfo;
1602
        }
1603
1604
        $pictureFilename = trim($user['picture_uri']);
1605
1606
        $dir = self::getUserPathById($id, $type);
1607
1608
        return array(
1609
            'dir' => $dir,
1610
            'file' => $pictureFilename,
1611
            'email' => $user['email']
1612
        );
1613
    }
1614
1615
    /**
1616
     * Get user path from user ID (returns an array).
1617
     * The return format is a complete path to a folder ending with "/"
1618
     * In case the first level of subdirectory of users/ does not exist, the
1619
     * function will attempt to create it. Probably not the right place to do it
1620
     * but at least it avoids headaches in many other places.
1621
     * @param   integer $id User ID
1622
     * @param   string  $type Type of path to return (can be 'system', 'web', 'last')
1623
     * @return  string  User folder path (i.e. /var/www/chamilo/app/upload/users/1/1/)
1624
     */
1625
    public static function getUserPathById($id, $type)
1626
    {
1627
        $id = intval($id);
1628
        if (!$id) {
1629
            return null;
1630
        }
1631
1632
        $userPath = "users/$id/";
1633
        if (api_get_setting('split_users_upload_directory') === 'true') {
1634
            $userPath = 'users/'.substr((string) $id, 0, 1).'/'.$id.'/';
1635
            // In exceptional cases, on some portals, the intermediate base user
1636
            // directory might not have been created. Make sure it is before
1637
            // going further.
1638
1639
            $rootPath = api_get_path(SYS_UPLOAD_PATH) . 'users/' . substr((string) $id, 0, 1);
1640
            if (!is_dir($rootPath)) {
1641
                $perm = api_get_permissions_for_new_directories();
1642
                try {
1643
                    mkdir($rootPath, $perm);
1644
                } catch (Exception $e) {
1645
                    error_log($e->getMessage());
1646
                }
1647
            }
1648
        }
1649
        switch ($type) {
1650
            case 'system': // Base: absolute system path.
1651
                $userPath = api_get_path(SYS_UPLOAD_PATH).$userPath;
1652
                break;
1653
            case 'web': // Base: absolute web path.
1654
                $userPath = api_get_path(WEB_UPLOAD_PATH).$userPath;
1655
                break;
1656
            case 'last': // Only the last part starting with users/
1657
                break;
1658
        }
1659
1660
        return $userPath;
1661
    }
1662
1663
    /**
1664
     * Gets the current user image
1665
     * @param string $user_id
1666
     * @param int $size it can be USER_IMAGE_SIZE_SMALL,
1667
     * USER_IMAGE_SIZE_MEDIUM, USER_IMAGE_SIZE_BIG or  USER_IMAGE_SIZE_ORIGINAL
1668
     * @param bool $addRandomId
1669
     * @param array $userInfo to avoid query the DB
1670
     *
1671
     * @return string
1672
     */
1673
    public static function getUserPicture(
1674
        $user_id,
1675
        $size = USER_IMAGE_SIZE_MEDIUM,
1676
        $addRandomId = true,
1677
        $userInfo = []
1678
    ) {
1679
        // Make sure userInfo is defined. Otherwise, define it!
1680
        if (empty($userInfo) || !is_array($userInfo) || count($userInfo) == 0) {
1681
            if (empty($user_id)) {
1682
                return '';
1683
            } else {
1684
                $userInfo = api_get_user_info($user_id);
1685
            }
1686
        }
1687
1688
        $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 1684 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...
1689
        $pictureWebFile = $imageWebPath['file'];
1690
        $pictureWebDir = $imageWebPath['dir'];
1691
1692
        $pictureAnonymousSize = '128';
1693
        $gravatarSize = 22;
1694
        $realSizeName = 'small_';
1695
1696
        switch ($size) {
1697
            case USER_IMAGE_SIZE_SMALL:
1698
                $pictureAnonymousSize = '32';
1699
                $realSizeName = 'small_';
1700
                $gravatarSize = 22;
1701
                break;
1702
            case USER_IMAGE_SIZE_MEDIUM:
1703
                $pictureAnonymousSize = '64';
1704
                $realSizeName = 'medium_';
1705
                $gravatarSize = 50;
1706
                break;
1707
            case USER_IMAGE_SIZE_ORIGINAL:
1708
                $pictureAnonymousSize = '128';
1709
                $realSizeName = '';
1710
                $gravatarSize = 200;
1711
                break;
1712
            case USER_IMAGE_SIZE_BIG:
1713
                $pictureAnonymousSize = '128';
1714
                $realSizeName = 'big_';
1715
                $gravatarSize = 200;
1716
                break;
1717
        }
1718
1719
        $gravatarEnabled = api_get_setting('gravatar_enabled');
1720
        $anonymousPath = Display::returnIconPath('unknown.png', $pictureAnonymousSize);
1721
        if ($pictureWebFile == 'unknown.jpg' || empty($pictureWebFile)) {
1722
1723
            if ($gravatarEnabled === 'true') {
1724
                $file = self::getGravatar(
1725
                    $imageWebPath['email'],
1726
                    $gravatarSize,
1727
                    api_get_setting('gravatar_type')
1728
                );
1729
1730
                if ($addRandomId) {
1731
                    $file .= '&rand='.uniqid();
1732
                }
1733
1734
                return $file;
1735
            }
1736
1737
            return $anonymousPath;
1738
        }
1739
1740
        $pictureSysPath = self::get_user_picture_path_by_id($user_id, 'system');
1741
1742
        $file = $pictureSysPath['dir'].$realSizeName.$pictureWebFile;
1743
        $picture = '';
1744
        if (file_exists($file)) {
1745
            $picture = $pictureWebDir.$realSizeName.$pictureWebFile;
1746
        } else {
1747
            $file = $pictureSysPath['dir'].$pictureWebFile;
1748
            if (file_exists($file) && !is_dir($file)) {
1749
                $picture = $pictureWebFile['dir'].$pictureWebFile;
1750
            }
1751
        }
1752
1753
        if (empty($picture)) {
1754
            return $anonymousPath;
1755
        }
1756
1757
        if ($addRandomId) {
1758
            $picture .= '?rand='.uniqid();
1759
        }
1760
1761
        return $picture;
1762
    }
1763
1764
    /**
1765
     * Creates new user photos in various sizes of a user, or deletes user photos.
1766
     * Note: This method relies on configuration setting from main/inc/conf/profile.conf.php
1767
     * @param   int $user_id The user internal identification number.
1768
     * @param   string $file The common file name for the newly created photos.
1769
     *                       It will be checked and modified for compatibility with the file system.
1770
     *                       If full name is provided, path component is ignored.
1771
     *                       If an empty name is provided, then old user photos are deleted only,
1772
     * @see     UserManager::delete_user_picture() as the prefered way for deletion.
1773
     * @param   string $source_file The full system name of the image from which user photos will be created.
1774
     * @param   string $cropParameters Optional string that contents "x,y,width,height" of a cropped image format
1775
     * @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...
1776
     * When deletion is requested returns empty string. In case of internal error or negative validation returns FALSE.
1777
     */
1778
    public static function update_user_picture($user_id, $file = null, $source_file = null, $cropParameters = '')
1779
    {
1780
        if (empty($user_id)) {
1781
            return false;
1782
        }
1783
        $delete = empty($file);
1784
        if (empty($source_file)) {
1785
            $source_file = $file;
1786
        }
1787
1788
        // User-reserved directory where photos have to be placed.
1789
        $path_info = self::getUserPicturePathById($user_id, 'system');
1790
1791
        $path = $path_info['dir'];
1792
1793
        // If this directory does not exist - we create it.
1794
        if (!file_exists($path)) {
1795
            mkdir($path, api_get_permissions_for_new_directories(), true);
1796
        }
1797
1798
        // The old photos (if any).
1799
        $old_file = $path_info['file'];
1800
1801
        // Let us delete them.
1802 View Code Duplication
        if ($old_file != 'unknown.jpg') {
1803
            if (KEEP_THE_OLD_IMAGE_AFTER_CHANGE) {
1804
                $prefix = 'saved_'.date('Y_m_d_H_i_s').'_'.uniqid('').'_';
1805
                @rename($path.'small_'.$old_file, $path.$prefix.'small_'.$old_file);
1806
                @rename($path.'medium_'.$old_file, $path.$prefix.'medium_'.$old_file);
1807
                @rename($path.'big_'.$old_file, $path.$prefix.'big_'.$old_file);
1808
                @rename($path.$old_file, $path.$prefix.$old_file);
1809
            } else {
1810
                @unlink($path.'small_'.$old_file);
1811
                @unlink($path.'medium_'.$old_file);
1812
                @unlink($path.'big_'.$old_file);
1813
                @unlink($path.$old_file);
1814
            }
1815
        }
1816
1817
        // Exit if only deletion has been requested. Return an empty picture name.
1818
        if ($delete) {
1819
            return '';
1820
        }
1821
1822
        // Validation 2.
1823
        $allowed_types = api_get_supported_image_extensions();
1824
        $file = str_replace('\\', '/', $file);
1825
        $filename = (($pos = strrpos($file, '/')) !== false) ? substr($file, $pos + 1) : $file;
1826
        $extension = strtolower(substr(strrchr($filename, '.'), 1));
1827
        if (!in_array($extension, $allowed_types)) {
1828
            return false;
1829
        }
1830
1831
        // This is the common name for the new photos.
1832
        if (KEEP_THE_NAME_WHEN_CHANGE_IMAGE && $old_file != 'unknown.jpg') {
1833
            $old_extension = strtolower(substr(strrchr($old_file, '.'), 1));
1834
            $filename = in_array($old_extension, $allowed_types) ? substr($old_file, 0, -strlen($old_extension)) : $old_file;
1835
            $filename = (substr($filename, -1) == '.') ? $filename.$extension : $filename.'.'.$extension;
1836
        } else {
1837
            $filename = api_replace_dangerous_char($filename);
1838
            if (PREFIX_IMAGE_FILENAME_WITH_UID) {
1839
                $filename = uniqid('').'_'.$filename;
1840
            }
1841
            // We always prefix user photos with user ids, so on setting
1842
            // api_get_setting('split_users_upload_directory') === 'true'
1843
            // the correspondent directories to be found successfully.
1844
            $filename = $user_id.'_'.$filename;
1845
        }
1846
1847
        //Crop the image to adjust 1:1 ratio
1848
        $image = new Image($source_file);
1849
        $image->crop($cropParameters);
1850
1851
        // Storing the new photos in 4 versions with various sizes.
1852
        $userPath = self::getUserPathById($user_id, 'system');
1853
1854
        // If this path does not exist - we create it.
1855
        if (!file_exists($userPath)) {
1856
            mkdir($userPath, api_get_permissions_for_new_directories(), true);
1857
        }
1858
        $small = new Image($source_file);
1859
        $small->resize(32);
1860
        $small->send_image($userPath.'small_'.$filename);
1861
        $medium = new Image($source_file);
1862
        $medium->resize(85);
1863
        $medium->send_image($userPath.'medium_'.$filename);
1864
        $normal = new Image($source_file);
1865
        $normal->resize(200);
1866
        $normal->send_image($userPath.$filename);
1867
1868
        $big = new Image($source_file); // This is the original picture.
1869
        $big->send_image($userPath.'big_'.$filename);
1870
1871
        $result = $small && $medium && $normal && $big;
1872
1873
        return $result ? $filename : false;
1874
    }
1875
1876
    /**
1877
     * Update User extra field file type into {user_folder}/{$extra_field}
1878
     * @param int $user_id          The user internal identification number
1879
     * @param string $extra_field   The $extra_field The extra field name
1880
     * @param null $file            The filename
1881
     * @param null $source_file     The temporal filename
1882
     * @return bool|null            return filename if success, but false
1883
     */
1884
    public static function update_user_extra_file($user_id, $extra_field = '', $file = null, $source_file = null)
1885
    {
1886
        // Add Filter
1887
        $source_file = Security::filter_filename($source_file);
1888
        $file = Security::filter_filename($file);
1889
1890
        if (empty($user_id)) {
1891
            return false;
1892
        }
1893
1894
        if (empty($source_file)) {
1895
            $source_file = $file;
1896
        }
1897
1898
        // User-reserved directory where extra file have to be placed.
1899
        $path_info = self::get_user_picture_path_by_id($user_id, 'system');
1900
        $path = $path_info['dir'];
1901
        if (!empty($extra_field)) {
1902
            $path .= $extra_field . '/';
1903
        }
1904
        // If this directory does not exist - we create it.
1905
        if (!file_exists($path)) {
1906
            @mkdir($path, api_get_permissions_for_new_directories(), true);
1907
        }
1908
1909
        if (filter_extension($file)) {
1910
            if (@move_uploaded_file($source_file, $path.$file)) {
1911
                if ($extra_field) {
1912
                    return $extra_field.'/'.$file;
1913
                } else {
1914
                    return $file;
1915
                }
1916
            }
1917
        }
1918
        return false; // this should be returned if anything went wrong with the upload
1919
    }
1920
1921
1922
    /**
1923
     * Deletes user photos.
1924
     * Note: This method relies on configuration setting from main/inc/conf/profile.conf.php
1925
     * @param int $user_id            The user internal identitfication number.
1926
     * @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...
1927
     */
1928
    public static function delete_user_picture($user_id)
1929
    {
1930
        return self::update_user_picture($user_id);
1931
    }
1932
1933
    /**
1934
     * Returns an XHTML formatted list of productions for a user, or FALSE if he
1935
     * doesn't have any.
1936
     *
1937
     * If there has been a request to remove a production, the function will return
1938
     * without building the list unless forced to do so by the optional second
1939
     * parameter. This increases performance by avoiding to read through the
1940
     * productions on the filesystem before the removal request has been carried
1941
     * out because they'll have to be re-read afterwards anyway.
1942
     *
1943
     * @param   int $user_id    User id
1944
     * @param   bool $force    Optional parameter to force building after a removal request
1945
     * @param   bool $showDelete
1946
     *
1947
     * @return  string A string containing the XHTML code to display the production list, or FALSE
1948
     */
1949
    public static function build_production_list($user_id, $force = false, $showDelete = false)
1950
    {
1951
        if (!$force && !empty($_POST['remove_production'])) {
1952
1953
            return true; // postpone reading from the filesystem
1954
        }
1955
1956
        $productions = self::get_user_productions($user_id);
1957
1958
        if (empty($productions)) {
1959
1960
            return false;
1961
        }
1962
1963
        $production_dir = self::getUserPathById($user_id, 'web');
1964
        $del_image = Display::returnIconPath('delete.png');
1965
        $add_image = Display::returnIconPath('archive.png');
1966
        $del_text = get_lang('Delete');
1967
        $production_list = '';
1968
        if (count($productions) > 0) {
1969
            $production_list = '<div class="files-production"><ul id="productions">';
1970
            foreach ($productions as $file) {
1971
                $production_list .= '<li><img src="'.$add_image.'" /><a href="'.$production_dir.urlencode($file).'" target="_blank">'.htmlentities($file).'</a>';
1972 View Code Duplication
                if ($showDelete) {
1973
                    $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>';
1974
                }
1975
            }
1976
            $production_list .= '</ul></div>';
1977
        }
1978
1979
        return $production_list;
1980
    }
1981
1982
    /**
1983
     * Returns an array with the user's productions.
1984
     *
1985
     * @param    $user_id    User id
1986
     * @return   array  An array containing the user's productions
1987
     */
1988
    public static function get_user_productions($user_id)
1989
    {
1990
        $production_repository = self::getUserPathById($user_id, 'system');
1991
        $productions = array();
1992
1993
        if (is_dir($production_repository)) {
1994
            $handle = opendir($production_repository);
1995
            while ($file = readdir($handle)) {
1996
                if ($file == '.' ||
1997
                    $file == '..' ||
1998
                    $file == '.htaccess' ||
1999
                    is_dir($production_repository.$file)
2000
                ) {
2001
                    // skip current/parent directory and .htaccess
2002
                    continue;
2003
                }
2004
2005
                if (preg_match('/('.$user_id.'|[0-9a-f]{13}|saved)_.+\.(png|jpg|jpeg|gif)$/i', $file)) {
2006
                    // User's photos should not be listed as productions.
2007
                    continue;
2008
                }
2009
                $productions[] = $file;
2010
            }
2011
        }
2012
2013
        return $productions;
2014
    }
2015
2016
    /**
2017
     * Remove a user production.
2018
     *
2019
     * @param int $user_id        User id
2020
     * @param string $production    The production to remove
2021
     */
2022
    public static function remove_user_production($user_id, $production)
2023
    {
2024
        $production_path = self::get_user_picture_path_by_id($user_id, 'system');
2025
        $production_file = $production_path['dir'].$production;
2026
        if (is_file($production_file)) {
2027
            unlink($production_file);
2028
            return true;
2029
        }
2030
        return false;
2031
    }
2032
2033
    /**
2034
     * Update an extra field value for a given user
2035
     * @param    integer   $userId User ID
2036
     * @param    string    $variable Field variable name
2037
     * @param    string    $value Field value
2038
     *
2039
     * @return    boolean    true if field updated, false otherwise
2040
     */
2041 View Code Duplication
    public static function update_extra_field_value($userId, $variable, $value = '')
2042
    {
2043
        $extraFieldValue = new ExtraFieldValue('user');
2044
        $params = [
2045
            'item_id' => $userId,
2046
            'variable' => $variable,
2047
            'value' => $value
2048
        ];
2049
2050
        return $extraFieldValue->save($params);
2051
    }
2052
2053
    /**
2054
     * Get an array of extra fields with field details (type, default value and options)
2055
     * @param    integer    Offset (from which row)
2056
     * @param    integer    Number of items
2057
     * @param    integer    Column on which sorting is made
2058
     * @param    string    Sorting direction
2059
     * @param    boolean    Optional. Whether we get all the fields or just the visible ones
2060
     * @param    int        Optional. Whether we get all the fields with field_filter 1 or 0 or everything
2061
     * @return    array    Extra fields details (e.g. $list[2]['type'], $list[4]['options'][2]['title']
2062
     */
2063
    public static function get_extra_fields(
2064
        $from = 0,
2065
        $number_of_items = 0,
2066
        $column = 5,
2067
        $direction = 'ASC',
2068
        $all_visibility = true,
2069
        $field_filter = null
2070
    ) {
2071
        $fields = array();
2072
        $t_uf = Database :: get_main_table(TABLE_EXTRA_FIELD);
2073
        $t_ufo = Database :: get_main_table(TABLE_EXTRA_FIELD_OPTIONS);
2074
        $columns = array(
2075
            'id',
2076
            'variable',
2077
            'field_type',
2078
            'display_text',
2079
            'default_value',
2080
            'field_order',
2081
            'filter'
2082
        );
2083
        $column = intval($column);
2084
        $sort_direction = '';
2085
        if (in_array(strtoupper($direction), array('ASC', 'DESC'))) {
2086
            $sort_direction = strtoupper($direction);
2087
        }
2088
        $extraFieldType = EntityExtraField::USER_FIELD_TYPE;
2089
        $sqlf = "SELECT * FROM $t_uf WHERE extra_field_type = $extraFieldType ";
2090
        if (!$all_visibility) {
2091
            $sqlf .= " AND visible_to_self = 1 ";
2092
        }
2093
        if (!is_null($field_filter)) {
2094
            $field_filter = intval($field_filter);
2095
            $sqlf .= " AND filter = $field_filter ";
2096
        }
2097
        $sqlf .= " ORDER BY ".$columns[$column]." $sort_direction ";
2098
        if ($number_of_items != 0) {
2099
            $sqlf .= " LIMIT ".intval($from).','.intval($number_of_items);
2100
        }
2101
        $resf = Database::query($sqlf);
2102
        if (Database::num_rows($resf) > 0) {
2103
            while ($rowf = Database::fetch_array($resf)) {
2104
                $fields[$rowf['id']] = array(
2105
                    0 => $rowf['id'],
2106
                    1 => $rowf['variable'],
2107
                    2 => $rowf['field_type'],
2108
                    3 => empty($rowf['display_text']) ? '' : $rowf['display_text'],
2109
                    4 => $rowf['default_value'],
2110
                    5 => $rowf['field_order'],
2111
                    6 => $rowf['visible_to_self'],
2112
                    7 => $rowf['changeable'],
2113
                    8 => $rowf['filter'],
2114
                    9 => array(),
2115
                    10 => '<a name="'.$rowf['id'].'"></a>',
2116
                );
2117
2118
                $sqlo = "SELECT * FROM $t_ufo
2119
                         WHERE field_id = ".$rowf['id']."
2120
                         ORDER BY option_order ASC";
2121
                $reso = Database::query($sqlo);
2122
                if (Database::num_rows($reso) > 0) {
2123
                    while ($rowo = Database::fetch_array($reso)) {
2124
                        $fields[$rowf['id']][9][$rowo['id']] = array(
2125
                            0 => $rowo['id'],
2126
                            1 => $rowo['option_value'],
2127
                            2 => empty($rowo['display_text']) ? '' : $rowo['display_text'],
2128
                            3 => $rowo['option_order']
2129
                        );
2130
                    }
2131
                }
2132
            }
2133
        }
2134
2135
        return $fields;
2136
    }
2137
2138
    /**
2139
     * Build a list of extra file already uploaded in $user_folder/{$extra_field}/
2140
     * @param $user_id
2141
     * @param $extra_field
2142
     * @param bool $force
2143
     * @param bool $showDelete
2144
     * @return bool|string
2145
     */
2146
    public static function build_user_extra_file_list($user_id, $extra_field, $force = false, $showDelete = false)
2147
    {
2148
        if (!$force && !empty($_POST['remove_'.$extra_field])) {
2149
            return true; // postpone reading from the filesystem
2150
        }
2151
2152
        $extra_files = self::get_user_extra_files($user_id, $extra_field);
2153
        if (empty($extra_files)) {
2154
            return false;
2155
        }
2156
2157
        $path_info = self::get_user_picture_path_by_id($user_id, 'web');
2158
        $path = $path_info['dir'];
2159
        $del_image = Display::returnIconPath('delete.png');
2160
2161
        $del_text = get_lang('Delete');
2162
        $extra_file_list = '';
2163
        if (count($extra_files) > 0) {
2164
            $extra_file_list = '<div class="files-production"><ul id="productions">';
2165
            foreach ($extra_files as $file) {
2166
                $filename = substr($file,strlen($extra_field)+1);
2167
                $extra_file_list .= '<li>'.Display::return_icon('archive.png').'<a href="'.$path.$extra_field.'/'.urlencode($filename).'" target="_blank">'.htmlentities($filename).'</a> ';
2168 View Code Duplication
                if ($showDelete) {
2169
                    $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>';
2170
                }
2171
            }
2172
            $extra_file_list .= '</ul></div>';
2173
        }
2174
2175
        return $extra_file_list;
2176
    }
2177
2178
    /**
2179
     * Get valid filenames in $user_folder/{$extra_field}/
2180
     * @param $user_id
2181
     * @param $extra_field
2182
     * @param bool $full_path
2183
     * @return array
2184
     */
2185
    public static function get_user_extra_files($user_id, $extra_field, $full_path = false)
2186
    {
2187
        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...
2188
            // Nothing to do
2189
        } else {
2190
            $path_info = self::get_user_picture_path_by_id($user_id, 'system');
2191
            $path = $path_info['dir'];
2192
        }
2193
        $extra_data = self::get_extra_user_data_by_field($user_id, $extra_field);
2194
        $extra_files = $extra_data[$extra_field];
2195
        if (is_array($extra_files)) {
2196
            foreach ($extra_files as $key => $value) {
2197
                if (!$full_path) {
2198
                    // Relative path from user folder
2199
                    $files[] = $value;
2200
                } else {
2201
                    $files[] = $path.$value;
2202
                }
2203
            }
2204
        } elseif (!empty($extra_files)) {
2205
            if (!$full_path) {
2206
                // Relative path from user folder
2207
                $files[] = $extra_files;
2208
            } else {
2209
                $files[] = $path.$extra_files;
2210
            }
2211
        }
2212
2213
        return $files; // can be an empty array
2214
    }
2215
2216
    /**
2217
     * Remove an {$extra_file} from the user folder $user_folder/{$extra_field}/
2218
     * @param $user_id
2219
     * @param $extra_field
2220
     * @param $extra_file
2221
     * @return bool
2222
     */
2223
    public static function remove_user_extra_file($user_id, $extra_field, $extra_file)
2224
    {
2225
        $extra_file = Security::filter_filename($extra_file);
2226
        $path_info = self::get_user_picture_path_by_id($user_id, 'system');
2227
        if (strpos($extra_file, $extra_field) !== false) {
2228
            $path_extra_file = $path_info['dir'].$extra_file;
2229
        } else {
2230
            $path_extra_file = $path_info['dir'].$extra_field.'/'.$extra_file;
2231
        }
2232
        if (is_file($path_extra_file)) {
2233
            unlink($path_extra_file);
2234
            return true;
2235
        }
2236
        return false;
2237
    }
2238
2239
    /**
2240
     * Creates a new extra field
2241
     * @param    string    $variable Field's internal variable name
2242
     * @param    int       $fieldType  Field's type
2243
     * @param    string    $displayText Field's language var name
2244
     * @param    string    $default Field's default value
2245
     * @return int
2246
     */
2247 View Code Duplication
    public static function create_extra_field($variable, $fieldType, $displayText, $default)
2248
    {
2249
        $extraField = new ExtraField('user');
2250
        $params = [
2251
            'variable' => $variable,
2252
            'field_type' => $fieldType,
2253
            'display_text' => $displayText,
2254
            'default_value' => $default
2255
        ];
2256
2257
        return $extraField->save($params);
2258
    }
2259
2260
    /**
2261
     * Check if a field is available
2262
     * @param    string    $variable
2263
     * @return    boolean
2264
     */
2265
    public static function is_extra_field_available($variable)
2266
    {
2267
        $extraField = new ExtraField('user');
2268
        $data = $extraField->get_handler_field_info_by_field_variable($variable);
2269
2270
        return !empty($data) ? true : false;
2271
    }
2272
2273
    /**
2274
     * Gets user extra fields data
2275
     * @param    integer    User ID
2276
     * @param    boolean    Whether to prefix the fields indexes with "extra_" (might be used by formvalidator)
2277
     * @param    boolean    Whether to return invisible fields as well
2278
     * @param    boolean    Whether to split multiple-selection fields or not
2279
     * @return    array    Array of fields => value for the given user
2280
     */
2281
    public static function get_extra_user_data(
2282
        $user_id,
2283
        $prefix = false,
2284
        $all_visibility = true,
2285
        $splitmultiple = false,
2286
        $field_filter = null
2287
    ) {
2288
        // A sanity check.
2289 View Code Duplication
        if (empty($user_id)) {
2290
            $user_id = 0;
2291
        } else {
2292
            if ($user_id != strval(intval($user_id)))
2293
                return array();
2294
        }
2295
        $extra_data = array();
2296
        $t_uf = Database::get_main_table(TABLE_EXTRA_FIELD);
2297
        $t_ufv = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
2298
        $user_id = intval($user_id);
2299
        $sql = "SELECT f.id as id, f.variable as fvar, f.field_type as type
2300
                FROM $t_uf f
2301
                WHERE
2302
                    extra_field_type = ".EntityExtraField::USER_FIELD_TYPE."
2303
                ";
2304
        $filter_cond = '';
2305
2306
        if (!$all_visibility) {
2307
            if (isset($field_filter)) {
2308
                $field_filter = intval($field_filter);
2309
                $filter_cond .= " AND filter = $field_filter ";
2310
            }
2311
            $sql .= " AND f.visible_to_self = 1 $filter_cond ";
2312
        } else {
2313
            if (isset($field_filter)) {
2314
                $field_filter = intval($field_filter);
2315
                $sql .= " AND filter = $field_filter ";
2316
            }
2317
        }
2318
2319
        $sql .= " ORDER BY f.field_order";
2320
2321
        $res = Database::query($sql);
2322
        if (Database::num_rows($res) > 0) {
2323
            while ($row = Database::fetch_array($res)) {
2324
                if ($row['type'] == self::USER_FIELD_TYPE_TAG) {
2325
                    $tags = self::get_user_tags_to_string($user_id, $row['id'], false);
2326
                    $extra_data['extra_'.$row['fvar']] = $tags;
2327
                } else {
2328
                    $sqlu = "SELECT value as fval
2329
                            FROM $t_ufv
2330
                            WHERE field_id=".$row['id']." AND item_id = ".$user_id;
2331
                    $resu = Database::query($sqlu);
2332
                    // get default value
2333
                    $sql_df = "SELECT default_value as fval_df FROM $t_uf
2334
                               WHERE id=".$row['id'];
2335
                    $res_df = Database::query($sql_df);
2336
2337
                    if (Database::num_rows($resu) > 0) {
2338
                        $rowu = Database::fetch_array($resu);
2339
                        $fval = $rowu['fval'];
2340
                        if ($row['type'] == self::USER_FIELD_TYPE_SELECT_MULTIPLE) {
2341
                            $fval = explode(';', $rowu['fval']);
2342
                        }
2343
                    } else {
2344
                        $row_df = Database::fetch_array($res_df);
2345
                        $fval = $row_df['fval_df'];
2346
                    }
2347
                    // We get here (and fill the $extra_data array) even if there
2348
                    // is no user with data (we fill it with default values)
2349
                    if ($prefix) {
2350 View Code Duplication
                        if ($row['type'] == self::USER_FIELD_TYPE_RADIO) {
2351
                            $extra_data['extra_'.$row['fvar']]['extra_'.$row['fvar']] = $fval;
2352
                        } else {
2353
                            $extra_data['extra_'.$row['fvar']] = $fval;
2354
                        }
2355 View Code Duplication
                    } else {
2356
                        if ($row['type'] == self::USER_FIELD_TYPE_RADIO) {
2357
                            $extra_data['extra_'.$row['fvar']]['extra_'.$row['fvar']] = $fval;
2358
                        } else {
2359
                            $extra_data[$row['fvar']] = $fval;
2360
                        }
2361
                    }
2362
                }
2363
            }
2364
        }
2365
2366
        return $extra_data;
2367
    }
2368
2369
    /** Get extra user data by field
2370
     * @param int    user ID
2371
     * @param string the internal variable name of the field
2372
     * @return array with extra data info of a user i.e array('field_variable'=>'value');
2373
     */
2374
    public static function get_extra_user_data_by_field(
2375
        $user_id,
2376
        $field_variable,
2377
        $prefix = false,
2378
        $all_visibility = true,
2379
        $splitmultiple = false
2380
    ) {
2381
        // A sanity check.
2382 View Code Duplication
        if (empty($user_id)) {
2383
            $user_id = 0;
2384
        } else {
2385
            if ($user_id != strval(intval($user_id)))
2386
                return array();
2387
        }
2388
        $extra_data = array();
2389
        $t_uf = Database::get_main_table(TABLE_EXTRA_FIELD);
2390
        $t_ufv = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
2391
        $user_id = intval($user_id);
2392
2393
        $sql = "SELECT f.id as id, f.variable as fvar, f.field_type as type
2394
                FROM $t_uf f
2395
                WHERE f.variable = '$field_variable' ";
2396
2397
        if (!$all_visibility) {
2398
            $sql .= " AND f.visible_to_self = 1 ";
2399
        }
2400
2401
        $sql .= " AND extra_field_type = ".EntityExtraField::USER_FIELD_TYPE;
2402
2403
        $sql .= " ORDER BY f.field_order";
2404
2405
        $res = Database::query($sql);
2406
        if (Database::num_rows($res) > 0) {
2407
            while ($row = Database::fetch_array($res)) {
2408
                $sqlu = "SELECT value as fval FROM $t_ufv v INNER JOIN $t_uf f
2409
                         ON (v.field_id = f.id)
2410
                         WHERE
2411
                            extra_field_type = ".EntityExtraField::USER_FIELD_TYPE." AND
2412
                            field_id = ".$row['id']." AND
2413
                            item_id = ".$user_id;
2414
                $resu = Database::query($sqlu);
2415
                $fval = '';
2416 View Code Duplication
                if (Database::num_rows($resu) > 0) {
2417
                    $rowu = Database::fetch_array($resu);
2418
                    $fval = $rowu['fval'];
2419
                    if ($row['type'] == self::USER_FIELD_TYPE_SELECT_MULTIPLE) {
2420
                        $fval = explode(';', $rowu['fval']);
2421
                    }
2422
                }
2423
                if ($prefix) {
2424
                    $extra_data['extra_'.$row['fvar']] = $fval;
2425
                } else {
2426
                    $extra_data[$row['fvar']] = $fval;
2427
                }
2428
            }
2429
        }
2430
2431
        return $extra_data;
2432
    }
2433
2434
    /**
2435
     * Get the extra field information for a certain field (the options as well)
2436
     * @param  int     $variable The name of the field we want to know everything about
2437
     * @return array   Array containing all the information about the extra profile field
2438
     * (first level of array contains field details, then 'options' sub-array contains options details,
2439
     * as returned by the database)
2440
     * @author Julio Montoya
2441
     * @since v1.8.6
2442
     */
2443
    public static function get_extra_field_information_by_name($variable)
2444
    {
2445
        $extraField = new ExtraField('user');
2446
2447
        return $extraField->get_handler_field_info_by_field_variable($variable);
2448
    }
2449
2450
    /**
2451
     * Get the extra field information for user tag (the options as well)
2452
     * @param  int     $variable The name of the field we want to know everything about
2453
     * @return array   Array containing all the information about the extra profile field
2454
     * (first level of array contains field details, then 'options' sub-array contains options details,
2455
     * as returned by the database)
2456
     * @author José Loguercio
2457
     * @since v1.11.0
2458
     */
2459
    public static function get_extra_field_tags_information_by_name($variable)
2460
    {
2461
        $extraField = new ExtraField('user');
2462
2463
        return $extraField->get_handler_field_info_by_tags($variable);
2464
    }
2465
2466
    /**
2467
     * @param string $type
2468
     *
2469
     * @return array
2470
     */
2471
    public static function get_all_extra_field_by_type($type)
2472
    {
2473
        $extraField = new ExtraField('user');
2474
2475
        return $extraField->get_all_extra_field_by_type($type);
2476
    }
2477
2478
    /**
2479
     * Get all the extra field information of a certain field (also the options)
2480
     *
2481
     * @param int $fieldId the ID of the field we want to know everything of
2482
     * @return array $return containing all th information about the extra profile field
2483
     * @author Julio Montoya
2484
     * @deprecated
2485
     * @since v1.8.6
2486
     */
2487
    public static function get_extra_field_information($fieldId)
2488
    {
2489
        $extraField = new ExtraField('user');
2490
2491
        return $extraField->getFieldInfoByFieldId($fieldId);
2492
    }
2493
2494
    /**
2495
     * Get extra user data by value
2496
     * @param string $variable the internal variable name of the field
2497
     * @param string $value the internal value of the field
2498
     * @param bool $all_visibility
2499
     *
2500
     * @return array with extra data info of a user i.e array('field_variable'=>'value');
2501
     */
2502
     public static function get_extra_user_data_by_value($variable, $value, $all_visibility = true)
2503
    {
2504
        $extraFieldValue = new ExtraFieldValue('user');
2505
        $extraField = new ExtraField('user');
2506
2507
        $info = $extraField->get_handler_field_info_by_field_variable($variable);
2508
2509
        if (false === $info) {
2510
            return [];
2511
        }
2512
2513
        $data = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
2514
            $variable,
2515
            $value,
2516
            false,
2517
            false,
2518
            true
2519
        );
2520
2521
        $result = [];
2522
        if (!empty($data)) {
2523
            foreach ($data as $item) {
2524
                $result[] = $item['item_id'];
2525
            }
2526
        }
2527
2528
        return $result;
2529
    }
2530
2531
    /**
2532
     * Get extra user data by tags value
2533
     *
2534
     * @param int $fieldId the ID of the field we want to know everything of
2535
     * @param string $tag the tag name for search
2536
     * @return array with extra data info of a user
2537
     * @author José Loguercio
2538
     * @since v1.11.0
2539
     */
2540
    public static function get_extra_user_data_by_tags($fieldId, $tag)
2541
    {
2542
        $extraField = new ExtraField('user');
2543
        $result = $extraField->getAllUserPerTag($fieldId, $tag);
2544
        $array = [];
2545
        foreach ($result as $index => $user) {
2546
            $array[] = $user['user_id'];
2547
        }
2548
        return $array;
2549
    }
2550
2551
    /**
2552
     * Get extra user data by field variable
2553
     * @param string    $variable field variable
2554
     * @return array    data
2555
     */
2556
    public static function get_extra_user_data_by_field_variable($variable)
2557
    {
2558
        $extra_information_by_variable = self::get_extra_field_information_by_name($variable);
2559
        $field_id = intval($extra_information_by_variable['id']);
2560
2561
        $extraField = new ExtraFieldValue('user');
2562
        $data = $extraField->getValuesByFieldId($field_id);
2563
2564
        if (!empty($data) > 0) {
2565
            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...
2566
                $user_id = $row['item_id'];
2567
                $data[$user_id] = $row;
2568
            }
2569
        }
2570
2571
        return $data;
2572
    }
2573
2574
    /**
2575
     * Get extra user data tags by field variable
2576
     *
2577
     * @param string $variable field variable
2578
     * @return array
2579
     */
2580
    public static function get_extra_user_data_for_tags($variable)
2581
    {
2582
        $data = self::get_extra_field_tags_information_by_name($variable);
2583
2584
        return $data;
2585
    }
2586
2587
    /**
2588
     * Gives a list of [session_category][session_id] for the current user.
2589
     * @param integer $user_id
2590
     * @param boolean whether to fill the first element or not (to give space for courses out of categories)
2591
     * @param boolean  optional true if limit time from session is over, false otherwise
2592
     * @param boolean $ignoreTimeLimit ignore time start/end
2593
     * @return array  list of statuses [session_category][session_id]
2594
     *
2595
     * @todo ensure multiple access urls are managed correctly
2596
     */
2597
    public static function get_sessions_by_category(
2598
        $user_id,
2599
        $is_time_over = true,
2600
        $ignore_visibility_for_admins = false,
2601
        $ignoreTimeLimit = false
2602
    ) {
2603
        if ($user_id != strval(intval($user_id))) {
2604
            return array();
2605
        }
2606
2607
        // Get the list of sessions per user
2608
        $now = new DateTime('now', new DateTimeZone('UTC'));
2609
2610
        $dql = "SELECT DISTINCT
2611
                    s.id,
2612
                    s.name,
2613
                    s.accessStartDate AS access_start_date,
2614
                    s.accessEndDate AS access_end_date,
2615
                    sc.id AS session_category_id,
2616
                    sc.name AS session_category_name,
2617
                    sc.dateStart AS session_category_date_start,
2618
                    sc.dateEnd AS session_category_date_end,
2619
                    s.coachAccessStartDate AS coach_access_start_date,
2620
                    s.coachAccessEndDate AS coach_access_end_date
2621
                FROM ChamiloCoreBundle:Session AS s                                
2622
                INNER JOIN ChamiloCoreBundle:SessionRelCourseRelUser AS scu WITH scu.session = s
2623
                LEFT JOIN ChamiloCoreBundle:SessionCategory AS sc WITH s.category = sc
2624
                WHERE scu.user = :user OR s.generalCoach = :user
2625
                ORDER BY sc.name, s.name";
2626
2627
        $dql = Database::getManager()
2628
            ->createQuery($dql)
2629
            ->setParameters(['user' => $user_id])
2630
        ;
2631
2632
        $sessionData = $dql->getResult();
2633
        $categories = [];
2634
2635
        foreach ($sessionData as $row) {
2636
            // User portal filters:
2637
            if ($ignoreTimeLimit === false) {
2638
                if ($is_time_over) {
2639
                    // History
2640
                    if (empty($row['access_end_date'])) {
2641
                        continue;
2642
                    }
2643
2644
                    if (!empty($row['access_end_date'])) {
2645
                        if ($row['access_end_date'] > $now) {
2646
                            continue;
2647
                        }
2648
2649
                    }
2650
                } else {
2651
                    // Current user portal
2652
                    if (api_is_allowed_to_create_course()) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

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

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

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

could be turned into

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

This is much more concise to read.

Loading history...
2653
                        // Teachers can access the session depending in the access_coach date
2654
                    } else {
2655
                        if (isset($row['access_end_date']) &&
2656
                            !empty($row['access_end_date'])
2657
                        ) {
2658
                            if ($row['access_end_date'] <= $now) {
2659
                                continue;
2660
                            }
2661
                        }
2662
                    }
2663
                }
2664
            }
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
            $categories[$row['session_category_id']]['session_category'] = array(
2670
                'id' => $row['session_category_id'],
2671
                'name' => $row['session_category_name'],
2672
                'date_start' => $categoryStart,
2673
                'date_end' => $categoryEnd
2674
            );
2675
2676
            $session_id = $row['id'];
2677
            $courseList = UserManager::get_courses_list_by_session(
2678
                $user_id,
2679
                $session_id
2680
            );
2681
2682
            $visibility = api_get_session_visibility(
2683
                $session_id,
2684
                null,
2685
                $ignore_visibility_for_admins
2686
            );
2687
2688 View Code Duplication
            if ($visibility != SESSION_VISIBLE) {
2689
                // Course Coach session visibility.
2690
                $blockedCourseCount = 0;
2691
                $closedVisibilityList = array(
2692
                    COURSE_VISIBILITY_CLOSED,
2693
                    COURSE_VISIBILITY_HIDDEN
2694
                );
2695
2696
                foreach ($courseList as $course) {
2697
                    // Checking session visibility
2698
                    $sessionCourseVisibility = api_get_session_visibility(
2699
                        $session_id,
2700
                        $course['real_id'],
2701
                        $ignore_visibility_for_admins
2702
                    );
2703
2704
                    $courseIsVisible = !in_array(
2705
                        $course['visibility'],
2706
                        $closedVisibilityList
2707
                    );
2708
                    if ($courseIsVisible === false || $sessionCourseVisibility == SESSION_INVISIBLE) {
2709
                        $blockedCourseCount++;
2710
                    }
2711
                }
2712
2713
                // If all courses are blocked then no show in the list.
2714
                if ($blockedCourseCount === count($courseList)) {
2715
                    $visibility = SESSION_INVISIBLE;
2716
                } else {
2717
                    $visibility = SESSION_VISIBLE;
2718
                }
2719
            }
2720
2721
            switch ($visibility) {
2722
                case SESSION_VISIBLE_READ_ONLY:
2723
                case SESSION_VISIBLE:
2724
                case SESSION_AVAILABLE:
2725
                    break;
2726
                case SESSION_INVISIBLE:
2727
                    if ($ignore_visibility_for_admins === false) {
2728
                        continue 2;
2729
                    }
2730
            }
2731
2732
            $categories[$row['session_category_id']]['sessions'][$row['id']] = array(
2733
                'session_name' => $row['name'],
2734
                'session_id' => $row['id'],
2735
                'access_start_date' => $row['access_start_date'] ? $row['access_start_date']->format('Y-m-d H:i:s') : null,
2736
                'access_end_date' => $row['access_end_date'] ? $row['access_end_date']->format('Y-m-d H:i:s') : null,
2737
                'coach_access_start_date' => $row['coach_access_start_date'] ? $row['coach_access_start_date']->format('Y-m-d H:i:s') : null,
2738
                'coach_access_end_date' => $row['coach_access_end_date'] ? $row['coach_access_end_date']->format('Y-m-d H:i:s') : null,
2739
                'courses' => $courseList
2740
            );
2741
        }
2742
2743
        return $categories;
2744
    }
2745
2746
    /**
2747
     * Gives a list of [session_id-course_code] => [status] for the current user.
2748
     * @param integer $user_id
2749
     * @param int $sessionLimit
2750
     * @return array  list of statuses (session_id-course_code => status)
2751
     */
2752
    public static function get_personal_session_course_list($user_id, $sessionLimit = null)
2753
    {
2754
        // Database Table Definitions
2755
        $tbl_course = Database :: get_main_table(TABLE_MAIN_COURSE);
2756
        $tbl_user = Database :: get_main_table(TABLE_MAIN_USER);
2757
        $tbl_session = Database :: get_main_table(TABLE_MAIN_SESSION);
2758
        $tbl_session_user = Database :: get_main_table(TABLE_MAIN_SESSION_USER);
2759
        $tbl_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
2760
        $tbl_session_course_user = Database :: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2761
2762
        if ($user_id != strval(intval($user_id))) {
2763
            return array();
2764
        }
2765
2766
        // We filter the courses from the URL
2767
        $join_access_url = $where_access_url = '';
2768
2769 View Code Duplication
        if (api_get_multiple_access_url()) {
2770
            $access_url_id = api_get_current_access_url_id();
2771
            if ($access_url_id != -1) {
2772
                $tbl_url_course = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2773
                $join_access_url = "LEFT JOIN $tbl_url_course url_rel_course ON url_rel_course.c_id = course.id";
2774
                $where_access_url = " AND access_url_id = $access_url_id ";
2775
            }
2776
        }
2777
2778
        // Courses in which we subscribed out of any session
2779
        $tbl_user_course_category = Database :: get_main_table(TABLE_USER_COURSE_CATEGORY);
2780
2781
        $sql = "SELECT
2782
                    course.code,
2783
                    course_rel_user.status course_rel_status,
2784
                    course_rel_user.sort sort,
2785
                    course_rel_user.user_course_cat user_course_cat
2786
                 FROM $tbl_course_user course_rel_user
2787
                 LEFT JOIN $tbl_course course
2788
                 ON course.id = course_rel_user.c_id
2789
                 LEFT JOIN $tbl_user_course_category user_course_category
2790
                 ON course_rel_user.user_course_cat = user_course_category.id
2791
                 $join_access_url
2792
                 WHERE
2793
                    course_rel_user.user_id = '".$user_id."' AND
2794
                    course_rel_user.relation_type <> ".COURSE_RELATION_TYPE_RRHH."
2795
                    $where_access_url
2796
                 ORDER BY user_course_category.sort, course_rel_user.sort, course.title ASC";
2797
2798
        $course_list_sql_result = Database::query($sql);
2799
2800
        $personal_course_list = array();
2801
        if (Database::num_rows($course_list_sql_result) > 0) {
2802
            while ($result_row = Database::fetch_array($course_list_sql_result, 'ASSOC')) {
2803
                $course_info = api_get_course_info($result_row['code']);
2804
                $result_row['course_info'] = $course_info;
2805
                $personal_course_list[] = $result_row;
2806
            }
2807
        }
2808
2809
        $coachCourseConditions = null;
2810
2811
        // Getting sessions that are related to a coach in the session_rel_course_rel_user table
2812
2813
        if (api_is_allowed_to_create_course()) {
2814
            $sessionListFromCourseCoach = array();
2815
            $sql =" SELECT DISTINCT session_id
2816
                    FROM $tbl_session_course_user
2817
                    WHERE user_id = $user_id AND status = 2 ";
2818
2819
            $result = Database::query($sql);
2820
            if (Database::num_rows($result)) {
2821
                $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...
2822
                foreach ($result as $session) {
2823
                    $sessionListFromCourseCoach[]= $session['session_id'];
2824
                }
2825
            }
2826
            if (!empty($sessionListFromCourseCoach)) {
2827
                $condition = implode("','", $sessionListFromCourseCoach);
2828
                $coachCourseConditions = " OR ( s.id IN ('$condition'))";
2829
            }
2830
        }
2831
2832
        // Get the list of sessions where the user is subscribed
2833
        // This is divided into two different queries
2834
        $sessions = array();
2835
2836
        $sessionLimitRestriction = '';
2837
        if (!empty($sessionLimit)) {
2838
            $sessionLimit = (int) $sessionLimit;
2839
            $sessionLimitRestriction = "LIMIT $sessionLimit";
2840
        }
2841
2842
        $sql = "SELECT DISTINCT s.id, name, access_start_date, access_end_date
2843
                FROM $tbl_session_user su INNER JOIN $tbl_session s
2844
                ON (s.id = su.session_id)
2845
                WHERE (
2846
                    su.user_id = $user_id AND
2847
                    su.relation_type <> ".SESSION_RELATION_TYPE_RRHH."
2848
                )
2849
                $coachCourseConditions
2850
                ORDER BY access_start_date, access_end_date, name
2851
                $sessionLimitRestriction
2852
        ";
2853
2854
        $result = Database::query($sql);
2855
        if (Database::num_rows($result)>0) {
2856
            while ($row = Database::fetch_assoc($result)) {
2857
                $sessions[$row['id']] = $row;
2858
            }
2859
        }
2860
2861
        $sql = "SELECT DISTINCT
2862
                id, name, access_start_date, access_end_date
2863
                FROM $tbl_session s
2864
                WHERE (
2865
                    id_coach = $user_id
2866
                )
2867
                $coachCourseConditions
2868
                ORDER BY access_start_date, access_end_date, name";
2869
2870
        $result = Database::query($sql);
2871
        if (Database::num_rows($result)>0) {
2872
            while ($row = Database::fetch_assoc($result)) {
2873
                if (empty($sessions[$row['id']])) {
2874
                    $sessions[$row['id']] = $row;
2875
                }
2876
            }
2877
        }
2878
2879
        if (api_is_allowed_to_create_course()) {
2880
            foreach ($sessions as $enreg) {
2881
                $session_id = $enreg['id'];
2882
                $session_visibility = api_get_session_visibility($session_id);
2883
2884
                if ($session_visibility == SESSION_INVISIBLE) {
2885
                    continue;
2886
                }
2887
2888
                // This query is horribly slow when more than a few thousand
2889
                // users and just a few sessions to which they are subscribed
2890
                $sql = "SELECT DISTINCT
2891
                        course.code code,
2892
                        course.title i,
2893
                        ".(api_is_western_name_order() ? "CONCAT(user.firstname,' ',user.lastname)" : "CONCAT(user.lastname,' ',user.firstname)")." t,
2894
                        email, course.course_language l,
2895
                        1 sort,
2896
                        category_code user_course_cat,
2897
                        access_start_date,
2898
                        access_end_date,
2899
                        session.id as session_id,
2900
                        session.name as session_name
2901
                    FROM $tbl_session_course_user as session_course_user
2902
                        INNER JOIN $tbl_course AS course
2903
                            ON course.id = session_course_user.c_id
2904
                        INNER JOIN $tbl_session as session
2905
                            ON session.id = session_course_user.session_id
2906
                        LEFT JOIN $tbl_user as user
2907
                            ON user.id = session_course_user.user_id OR session.id_coach = user.id
2908
                    WHERE
2909
                        session_course_user.session_id = $session_id AND (
2910
                            (session_course_user.user_id = $user_id AND session_course_user.status = 2)
2911
                            OR session.id_coach = $user_id
2912
                        )
2913
                    ORDER BY i";
2914
                $course_list_sql_result = Database::query($sql);
2915 View Code Duplication
                while ($result_row = Database::fetch_array($course_list_sql_result, 'ASSOC')) {
2916
                    $result_row['course_info'] = api_get_course_info($result_row['code']);
2917
                    $key = $result_row['session_id'].' - '.$result_row['code'];
2918
                    $personal_course_list[$key] = $result_row;
2919
                }
2920
            }
2921
        }
2922
2923
        foreach ($sessions as $enreg) {
2924
            $session_id = $enreg['id'];
2925
            $session_visibility = api_get_session_visibility($session_id);
2926
            if ($session_visibility == SESSION_INVISIBLE) {
2927
                continue;
2928
            }
2929
2930
            /* This query is very similar to the above query,
2931
               but it will check the session_rel_course_user table if there are courses registered to our user or not */
2932
            $sql = "SELECT DISTINCT
2933
                course.code code,
2934
                course.title i, CONCAT(user.lastname,' ',user.firstname) t,
2935
                email,
2936
                course.course_language l,
2937
                1 sort,
2938
                category_code user_course_cat,
2939
                access_start_date,
2940
                access_end_date,
2941
                session.id as session_id,
2942
                session.name as session_name,
2943
                IF((session_course_user.user_id = 3 AND session_course_user.status=2),'2', '5')
2944
            FROM $tbl_session_course_user as session_course_user
2945
            INNER JOIN $tbl_course AS course
2946
            ON course.id = session_course_user.c_id AND session_course_user.session_id = $session_id
2947
            INNER JOIN $tbl_session as session 
2948
            ON session_course_user.session_id = session.id
2949
            LEFT JOIN $tbl_user as user ON user.id = session_course_user.user_id
2950
            WHERE session_course_user.user_id = $user_id
2951
            ORDER BY i";
2952
2953
            $course_list_sql_result = Database::query($sql);
2954 View Code Duplication
            while ($result_row = Database::fetch_array($course_list_sql_result, 'ASSOC')) {
2955
                $result_row['course_info'] = api_get_course_info($result_row['code']);
2956
                $key = $result_row['session_id'].' - '.$result_row['code'];
2957
                if (!isset($personal_course_list[$key])) {
2958
                    $personal_course_list[$key] = $result_row;
2959
                }
2960
            }
2961
        }
2962
2963
        return $personal_course_list;
2964
    }
2965
2966
    /**
2967
     * Gives a list of courses for the given user in the given session
2968
     * @param integer $user_id
2969
     * @param integer $session_id
2970
     * @return array  list of statuses (session_id-course_code => status)
2971
     */
2972
    public static function get_courses_list_by_session($user_id, $session_id)
2973
    {
2974
        // Database Table Definitions
2975
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2976
        $tableCourse = Database::get_main_table(TABLE_MAIN_COURSE);
2977
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2978
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2979
2980
        $user_id = intval($user_id);
2981
        $session_id = intval($session_id);
2982
        //we filter the courses from the URL
2983
        $join_access_url = $where_access_url = '';
2984
2985 View Code Duplication
        if (api_get_multiple_access_url()) {
2986
            $urlId = api_get_current_access_url_id();
2987
            if ($urlId != -1) {
2988
                $tbl_url_session = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
2989
                $join_access_url = " ,  $tbl_url_session url_rel_session ";
2990
                $where_access_url = " AND access_url_id = $urlId AND url_rel_session.session_id = $session_id ";
2991
            }
2992
        }
2993
2994
        /* This query is very similar to the query below, but it will check the
2995
        session_rel_course_user table if there are courses registered
2996
        to our user or not */
2997
        $sql = "SELECT DISTINCT
2998
                    c.visibility,
2999
                    c.id as real_id,                    
3000
                    sc.position
3001
                FROM $tbl_session_course_user as scu
3002
                INNER JOIN $tbl_session_course sc
3003
                ON (scu.session_id = sc.session_id AND scu.c_id = sc.c_id)
3004
                INNER JOIN $tableCourse as c
3005
                ON (scu.c_id = c.id)
3006
                $join_access_url
3007
                WHERE
3008
                    scu.user_id = $user_id AND
3009
                    scu.session_id = $session_id
3010
                    $where_access_url
3011
                ORDER BY sc.position ASC";
3012
3013
        $personal_course_list = array();
3014
        $courses = array();
3015
3016
        $result = Database::query($sql);
3017 View Code Duplication
        if (Database::num_rows($result) > 0) {
3018
            while ($result_row = Database::fetch_array($result, 'ASSOC')) {
3019
                $result_row['status'] = 5;
3020
                if (!in_array($result_row['real_id'], $courses)) {
3021
                    $personal_course_list[] = $result_row;
3022
                    $courses[] = $result_row['real_id'];
3023
                }
3024
            }
3025
        }
3026
3027
        if (api_is_allowed_to_create_course()) {
3028
            $sql = "SELECT DISTINCT
3029
                        c.visibility, 
3030
                        c.id as real_id,
3031
                        sc.position
3032
                    FROM $tbl_session_course_user as scu
3033
                    INNER JOIN $tbl_session as s
3034
                    ON (scu.session_id = s.id)
3035
                    INNER JOIN $tbl_session_course sc
3036
                    ON (scu.session_id = sc.session_id AND scu.c_id = sc.c_id)
3037
                    INNER JOIN $tableCourse as c
3038
                    ON (scu.c_id = c.id)
3039
                    $join_access_url
3040
                    WHERE
3041
                      s.id = $session_id AND
3042
                      (
3043
                        (scu.user_id = $user_id AND scu.status = 2) OR
3044
                        s.id_coach = $user_id
3045
                      )
3046
                    $where_access_url
3047
                    ORDER BY sc.position ASC";
3048
            $result = Database::query($sql);
3049
3050 View Code Duplication
            if (Database::num_rows($result) > 0) {
3051
                while ($result_row = Database::fetch_array($result, 'ASSOC')) {
3052
                    $result_row['status'] = 2;
3053
                    if (!in_array($result_row['real_id'], $courses)) {
3054
                        $personal_course_list[] = $result_row;
3055
                        $courses[] = $result_row['real_id'];
3056
                    }
3057
                }
3058
            }
3059
        }
3060
3061
        if (api_is_drh()) {
3062
            $sessionList = SessionManager::get_sessions_followed_by_drh($user_id);
3063
            $sessionList = array_keys($sessionList);
3064
            if (in_array($session_id, $sessionList)) {
3065
                $courseList = SessionManager::get_course_list_by_session_id($session_id);
3066 View Code Duplication
                if (!empty($courseList)) {
3067
                    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...
3068
                        if (!in_array($course['id'], $courses)) {
3069
                            $personal_course_list[] = $course;
3070
                        }
3071
                    }
3072
                }
3073
            }
3074
        } else {
3075
            //check if user is general coach for this session
3076
            $sessionInfo = api_get_session_info($session_id);
3077
            if ($sessionInfo['id_coach'] == $user_id) {
3078
                $courseList = SessionManager::get_course_list_by_session_id($session_id);
3079 View Code Duplication
                if (!empty($courseList)) {
3080
                    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...
3081
                        if (!in_array($course['id'], $courses)) {
3082
                            $personal_course_list[] = $course;
3083
                        }
3084
                    }
3085
                }
3086
            }
3087
        }
3088
3089
        return $personal_course_list;
3090
    }
3091
3092
    /**
3093
     * Get user id from a username
3094
     * @param    string    $username
3095
     * @return    int        User ID (or false if not found)
3096
     */
3097
    public static function get_user_id_from_username($username)
3098
    {
3099
        if (empty($username)) {
3100
3101
            return false;
3102
        }
3103
        $username = trim($username);
3104
        $username = Database::escape_string($username);
3105
        $t_user = Database::get_main_table(TABLE_MAIN_USER);
3106
        $sql = "SELECT id FROM $t_user WHERE username = '$username'";
3107
        $res = Database::query($sql);
3108
3109
        if ($res === false) {
3110
            return false;
3111
        }
3112
        if (Database::num_rows($res) !== 1) {
3113
            return false;
3114
        }
3115
        $row = Database::fetch_array($res);
3116
3117
        return $row['id'];
3118
    }
3119
3120
    /**
3121
     * Get the users files upload from his share_folder
3122
     * @param    string  $user_id   User ID
3123
     * @param   string  $course course directory
3124
     * @param   string  $resourcetype resourcetype: images, all
3125
     * @return    int        User ID (or false if not found)
3126
     */
3127
    public static function get_user_upload_files_by_course($user_id, $course, $resourcetype = 'all')
3128
    {
3129
        $return = '';
3130
        if (!empty($user_id) && !empty($course)) {
3131
            $user_id = intval($user_id);
3132
            $path = api_get_path(SYS_COURSE_PATH).$course.'/document/shared_folder/sf_user_'.$user_id.'/';
3133
            $web_path = api_get_path(WEB_COURSE_PATH).$course.'/document/shared_folder/sf_user_'.$user_id.'/';
3134
            $file_list = array();
3135
3136
            if (is_dir($path)) {
3137
                $handle = opendir($path);
3138
                while ($file = readdir($handle)) {
3139
                    if ($file == '.' || $file == '..' || $file == '.htaccess' || is_dir($path.$file)) {
3140
                        continue; // skip current/parent directory and .htaccess
3141
                    }
3142
                    $file_list[] = $file;
3143
                }
3144
                if (count($file_list) > 0) {
3145
                    $return = "<h4>$course</h4>";
3146
                    $return .= '<ul class="thumbnails">';
3147
                }
3148
                $extensionList = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'tif'];
3149
                foreach ($file_list as $file) {
3150
                    if ($resourcetype == "all") {
3151
                        $return .= '<li><a href="'.$web_path.urlencode($file).'" target="_blank">'.htmlentities($file).'</a></li>';
3152
                    } elseif ($resourcetype == "images") {
3153
                        //get extension
3154
                        $ext = explode('.', $file);
3155
                        if (isset($ext[1]) && in_array($ext[1], $extensionList)) {
3156
                            $return .= '<li class="span2">
3157
                                            <a class="thumbnail" href="'.$web_path.urlencode($file).'" target="_blank">
3158
                                                <img src="'.$web_path.urlencode($file).'" >
3159
                                            </a>
3160
                                        </li>';
3161
                        }
3162
                    }
3163
                }
3164
                if (count($file_list) > 0) {
3165
                    $return .= '</ul>';
3166
                }
3167
            }
3168
        }
3169
3170
        return $return;
3171
    }
3172
3173
    /**
3174
     * Gets the API key (or keys) and return them into an array
3175
     * @param   int     Optional user id (defaults to the result of api_get_user_id())
3176
     * @return  array   Non-indexed array containing the list of API keys for this user, or FALSE on error
3177
     */
3178
    public static function get_api_keys($user_id = null, $api_service = 'dokeos')
3179
    {
3180
        if ($user_id != strval(intval($user_id)))
3181
            return false;
3182
        if (empty($user_id)) {
3183
            $user_id = api_get_user_id();
3184
        }
3185
        if ($user_id === false)
3186
            return false;
3187
        $service_name = Database::escape_string($api_service);
3188
        if (is_string($service_name) === false) {
3189
            return false;
3190
        }
3191
        $t_api = Database::get_main_table(TABLE_MAIN_USER_API_KEY);
3192
        $sql = "SELECT * FROM $t_api WHERE user_id = $user_id AND api_service='$api_service';";
3193
        $res = Database::query($sql);
3194
        if ($res === false)
3195
            return false; //error during query
3196
        $num = Database::num_rows($res);
3197
        if ($num == 0)
3198
            return false;
3199
        $list = array();
3200
        while ($row = Database::fetch_array($res)) {
3201
            $list[$row['id']] = $row['api_key'];
3202
        }
3203
        return $list;
3204
    }
3205
3206
    /**
3207
     * Adds a new API key to the users' account
3208
     * @param   int     Optional user ID (defaults to the results of api_get_user_id())
3209
     * @return  boolean True on success, false on failure
3210
     */
3211
    public static function add_api_key($user_id = null, $api_service = 'dokeos')
3212
    {
3213
        if ($user_id != strval(intval($user_id)))
3214
            return false;
3215
        if (empty($user_id)) {
3216
            $user_id = api_get_user_id();
3217
        }
3218
        if ($user_id === false)
3219
            return false;
3220
        $service_name = Database::escape_string($api_service);
3221
        if (is_string($service_name) === false) {
3222
            return false;
3223
        }
3224
        $t_api = Database::get_main_table(TABLE_MAIN_USER_API_KEY);
3225
        $md5 = md5((time() + ($user_id * 5)) - rand(10000, 10000)); //generate some kind of random key
3226
        $sql = "INSERT INTO $t_api (user_id, api_key,api_service) VALUES ($user_id,'$md5','$service_name')";
3227
        $res = Database::query($sql);
3228
        if ($res === false)
3229
            return false; //error during query
3230
        $num = Database::insert_id();
3231
        return ($num == 0) ? false : $num;
3232
    }
3233
3234
    /**
3235
     * Deletes an API key from the user's account
3236
     * @param   int     API key's internal ID
3237
     * @return  boolean True on success, false on failure
3238
     */
3239
    public static function delete_api_key($key_id)
3240
    {
3241
        if ($key_id != strval(intval($key_id)))
3242
            return false;
3243
        if ($key_id === false)
3244
            return false;
3245
        $t_api = Database::get_main_table(TABLE_MAIN_USER_API_KEY);
3246
        $sql = "SELECT * FROM $t_api WHERE id = ".$key_id;
3247
        $res = Database::query($sql);
3248
        if ($res === false)
3249
            return false; //error during query
3250
        $num = Database::num_rows($res);
3251
        if ($num !== 1)
3252
            return false;
3253
        $sql = "DELETE FROM $t_api WHERE id = ".$key_id;
3254
        $res = Database::query($sql);
3255
        if ($res === false)
3256
            return false; //error during query
3257
        return true;
3258
    }
3259
3260
    /**
3261
     * Regenerate an API key from the user's account
3262
     * @param   int     user ID (defaults to the results of api_get_user_id())
3263
     * @param   string  API key's internal ID
3264
     * @return  int        num
3265
     */
3266
    public static function update_api_key($user_id, $api_service)
3267
    {
3268
        if ($user_id != strval(intval($user_id)))
3269
            return false;
3270
        if ($user_id === false)
3271
            return false;
3272
        $service_name = Database::escape_string($api_service);
3273
        if (is_string($service_name) === false) {
3274
            return false;
3275
        }
3276
        $t_api = Database::get_main_table(TABLE_MAIN_USER_API_KEY);
3277
        $sql = "SELECT id FROM $t_api WHERE user_id=".$user_id." AND api_service='".$api_service."'";
3278
        $res = Database::query($sql);
3279
        $num = Database::num_rows($res);
3280
        if ($num == 1) {
3281
            $id_key = Database::fetch_array($res, 'ASSOC');
3282
            self::delete_api_key($id_key['id']);
3283
            $num = self::add_api_key($user_id, $api_service);
3284
        } elseif ($num == 0) {
3285
            $num = self::add_api_key($user_id, $api_service);
3286
        }
3287
        return $num;
3288
    }
3289
3290
    /**
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    row ID, or return false if not found
3294
     */
3295
    public static function get_api_key_id($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
        if (empty($api_service))
3302
            return false;
3303
        $t_api = Database::get_main_table(TABLE_MAIN_USER_API_KEY);
3304
        $api_service = Database::escape_string($api_service);
3305
        $sql = "SELECT id FROM $t_api WHERE user_id=".$user_id." AND api_service='".$api_service."'";
3306
        $res = Database::query($sql);
3307
        if (Database::num_rows($res) < 1) {
3308
            return false;
3309
        }
3310
        $row = Database::fetch_array($res, 'ASSOC');
3311
        return $row['id'];
3312
    }
3313
3314
    /**
3315
     * Checks if a user_id is platform admin
3316
     * @param   int user ID
3317
     * @return  boolean True if is admin, false otherwise
3318
     * @see main_api.lib.php::api_is_platform_admin() for a context-based check
3319
     */
3320
    public static function is_admin($user_id)
3321
    {
3322
        if (empty($user_id) or $user_id != strval(intval($user_id))) {
3323
            return false;
3324
        }
3325
        $admin_table = Database::get_main_table(TABLE_MAIN_ADMIN);
3326
        $sql = "SELECT * FROM $admin_table WHERE user_id = $user_id";
3327
        $res = Database::query($sql);
3328
3329
        return Database::num_rows($res) === 1;
3330
    }
3331
3332
    /**
3333
     * Get the total count of users
3334
     * @param   int     Status of users to be counted
3335
     * @param   int     Access URL ID (optional)
3336
     * @return    mixed    Number of users or false on error
3337
     */
3338
    public static function get_number_of_users($status = 0, $access_url_id = null)
3339
    {
3340
        $t_u = Database::get_main_table(TABLE_MAIN_USER);
3341
        $t_a = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
3342
        $sql = "SELECT count(*) FROM $t_u u";
3343
        $sql2 = '';
3344
        if (is_int($status) && $status > 0) {
3345
            $sql2 .= " WHERE u.status = $status ";
3346
        }
3347
        if (!empty($access_url_id) && $access_url_id == intval($access_url_id)) {
3348
            $sql .= ", $t_a a ";
3349
            $sql2 .= " AND a.access_url_id = $access_url_id AND u.id = a.user_id ";
3350
        }
3351
        $sql = $sql.$sql2;
3352
        $res = Database::query($sql);
3353
        if (Database::num_rows($res) === 1) {
3354
            return (int) Database::result($res, 0, 0);
3355
        }
3356
        return false;
3357
    }
3358
3359
    /**
3360
     * @author Isaac flores <[email protected]>
3361
     * @param string The email administrator
3362
     * @param integer The user id
3363
     * @param string The message title
3364
     * @param string The content message
3365
     */
3366
    public static function send_message_in_outbox($email_administrator, $user_id, $title, $content)
3367
    {
3368
        $table_message = Database::get_main_table(TABLE_MESSAGE);
3369
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
3370
        $title = api_utf8_decode($title);
3371
        $content = api_utf8_decode($content);
3372
        $email_administrator = Database::escape_string($email_administrator);
3373
        //message in inbox
3374
        $sql_message_outbox = 'SELECT id from '.$table_user.' WHERE email="'.$email_administrator.'" ';
3375
        //$num_row_query = Database::num_rows($sql_message_outbox);
3376
        $res_message_outbox = Database::query($sql_message_outbox);
3377
        $array_users_administrator = array();
3378
        while ($row_message_outbox = Database::fetch_array($res_message_outbox, 'ASSOC')) {
3379
            $array_users_administrator[] = $row_message_outbox['id'];
3380
        }
3381
        //allow to insert messages in outbox
3382
        for ($i = 0; $i < count($array_users_administrator); $i++) {
3383
            $sql_insert_outbox = "INSERT INTO $table_message(user_sender_id, user_receiver_id, msg_status, send_date, title, content ) ".
3384
                " VALUES (".
3385
                "'".(int) $user_id."', '".(int) ($array_users_administrator[$i])."', '4', '".api_get_utc_datetime()."','".Database::escape_string($title)."','".Database::escape_string($content)."'".
3386
                ")";
3387
            Database::query($sql_insert_outbox);
3388
        }
3389
    }
3390
3391
    /**
3392
     *
3393
     * Gets the tags of a specific field_id
3394
     * USER TAGS
3395
     *
3396
     * Instructions to create a new user tag by Julio Montoya <[email protected]>
3397
     *
3398
     * 1. Create a new extra field in main/admin/user_fields.php with the "TAG" field type make it available and visible.
3399
     *    Called it "books" for example.
3400
     * 2. Go to profile main/auth/profile.php There you will see a special input (facebook style) that will show suggestions of tags.
3401
     * 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
3402
     * 4. Tags are independent this means that tags can't be shared between tags + book + hobbies.
3403
     * 5. Test and enjoy.
3404
     *
3405
     * @param string $tag
3406
     * @param int $field_id field_id
3407
     * @param string $return_format how we are going to result value in array or in a string (json)
3408
     * @param $limit
3409
     *
3410
     * @return mixed
3411
     *
3412
     */
3413
    public static function get_tags($tag, $field_id, $return_format = 'json', $limit = 10)
3414
    {
3415
        // database table definition
3416
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3417
        $field_id = intval($field_id);
3418
        $limit = intval($limit);
3419
        $tag = trim(Database::escape_string($tag));
3420
3421
        // all the information of the field
3422
        $sql = "SELECT DISTINCT id, tag from $table_user_tag
3423
                WHERE field_id = $field_id AND tag LIKE '$tag%' ORDER BY tag LIMIT $limit";
3424
        $result = Database::query($sql);
3425
        $return = array();
3426 View Code Duplication
        if (Database::num_rows($result) > 0) {
3427
            while ($row = Database::fetch_array($result, 'ASSOC')) {
3428
                $return[] = array('key' => $row['tag'], 'value' => $row['tag']);
3429
            }
3430
        }
3431
        if ($return_format === 'json') {
3432
            $return = json_encode($return);
3433
        }
3434
3435
        return $return;
3436
    }
3437
3438
    /**
3439
     * @param int $field_id
3440
     * @param int $limit
3441
     *
3442
     * @return array
3443
     */
3444
    public static function get_top_tags($field_id, $limit = 100)
3445
    {
3446
        // database table definition
3447
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3448
        $table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
3449
        $field_id = intval($field_id);
3450
        $limit = intval($limit);
3451
        // all the information of the field
3452
        $sql = "SELECT count(*) count, tag FROM $table_user_tag_values  uv
3453
                INNER JOIN $table_user_tag ut
3454
                ON(ut.id = uv.tag_id)
3455
                WHERE field_id = $field_id
3456
                GROUP BY tag_id
3457
                ORDER BY count DESC
3458
                LIMIT $limit";
3459
        $result = Database::query($sql);
3460
        $return = array();
3461
        if (Database::num_rows($result) > 0) {
3462
            while ($row = Database::fetch_array($result, 'ASSOC')) {
3463
                $return[] = $row;
3464
            }
3465
        }
3466
        return $return;
3467
    }
3468
3469
    /**
3470
     * Get user's tags
3471
     * @param int $user_id
3472
     * @param int $field_id
3473
     *
3474
     * @return array
3475
     */
3476
    public static function get_user_tags($user_id, $field_id)
3477
    {
3478
        // database table definition
3479
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3480
        $table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
3481
        $field_id = intval($field_id);
3482
        $user_id = intval($user_id);
3483
3484
        // all the information of the field
3485
        $sql = "SELECT ut.id, tag, count
3486
                FROM $table_user_tag ut
3487
                INNER JOIN $table_user_tag_values uv
3488
                ON (uv.tag_id=ut.ID)
3489
                WHERE field_id = $field_id AND user_id = $user_id
3490
                ORDER BY tag";
3491
        $result = Database::query($sql);
3492
        $return = array();
3493 View Code Duplication
        if (Database::num_rows($result) > 0) {
3494
            while ($row = Database::fetch_array($result, 'ASSOC')) {
3495
                $return[$row['id']] = array('tag' => $row['tag'], 'count' => $row['count']);
3496
            }
3497
        }
3498
3499
        return $return;
3500
    }
3501
3502
    /**
3503
     * Get user's tags
3504
     * @param int $user_id
3505
     * @param int $field_id
3506
     * @param bool $show_links show links or not
3507
     *
3508
     * @return array
3509
     */
3510
    public static function get_user_tags_to_string($user_id, $field_id, $show_links = true)
3511
    {
3512
        // database table definition
3513
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3514
        $table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
3515
        $field_id = intval($field_id);
3516
        $user_id = intval($user_id);
3517
3518
        // all the information of the field
3519
        $sql = "SELECT ut.id, tag,count FROM $table_user_tag ut
3520
                INNER JOIN $table_user_tag_values uv
3521
                ON (uv.tag_id = ut.id)
3522
                WHERE field_id = $field_id AND user_id = $user_id
3523
                ORDER BY tag";
3524
3525
        $result = Database::query($sql);
3526
        $return = array();
3527 View Code Duplication
        if (Database::num_rows($result) > 0) {
3528
            while ($row = Database::fetch_array($result, 'ASSOC')) {
3529
                $return[$row['id']] = array('tag' => $row['tag'], 'count' => $row['count']);
3530
            }
3531
        }
3532
        $user_tags = $return;
3533
        $tag_tmp = array();
3534
        foreach ($user_tags as $tag) {
3535
            if ($show_links) {
3536
                $tag_tmp[] = '<a href="'.api_get_path(WEB_PATH).'main/search/index.php?q='.$tag['tag'].'">'.$tag['tag'].'</a>';
3537
            } else {
3538
                $tag_tmp[] = $tag['tag'];
3539
            }
3540
        }
3541
3542
        if (is_array($user_tags) && count($user_tags) > 0) {
3543
            $return = implode(', ', $tag_tmp);
3544
        } else {
3545
3546
            return '';
3547
        }
3548
3549
        return $return;
3550
    }
3551
3552
    /**
3553
     * Get the tag id
3554
     * @param int $tag
3555
     * @param int $field_id
3556
     * @return int returns 0 if fails otherwise the tag id
3557
     */
3558
    public static function get_tag_id($tag, $field_id)
3559
    {
3560
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3561
        $tag = Database::escape_string($tag);
3562
        $field_id = intval($field_id);
3563
        //with COLLATE latin1_bin to select query in a case sensitive mode
3564
        $sql = "SELECT id FROM $table_user_tag
3565
                WHERE tag LIKE '$tag' AND field_id = $field_id";
3566
        $result = Database::query($sql);
3567
        if (Database::num_rows($result) > 0) {
3568
            $row = Database::fetch_array($result, 'ASSOC');
3569
3570
            return $row['id'];
3571
        } else {
3572
3573
            return 0;
3574
        }
3575
    }
3576
3577
    /**
3578
     * Get the tag id
3579
     * @param int $tag_id
3580
     * @param int $field_id
3581
     *
3582
     * @return int 0 if fails otherwise the tag id
3583
     */
3584 View Code Duplication
    public static function get_tag_id_from_id($tag_id, $field_id)
3585
    {
3586
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3587
        $tag_id = intval($tag_id);
3588
        $field_id = intval($field_id);
3589
        $sql = "SELECT id FROM $table_user_tag
3590
                WHERE id = '$tag_id' AND field_id = $field_id";
3591
        $result = Database::query($sql);
3592
        if (Database::num_rows($result) > 0) {
3593
            $row = Database::fetch_array($result, 'ASSOC');
3594
            return $row['id'];
3595
        } else {
3596
            return false;
3597
        }
3598
    }
3599
3600
    /**
3601
     * Adds a user-tag value
3602
     * @param mixed $tag
3603
     * @param int $user_id
3604
     * @param int $field_id field id of the tag
3605
     * @return bool
3606
     */
3607
    public static function add_tag($tag, $user_id, $field_id)
3608
    {
3609
        // database table definition
3610
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3611
        $table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
3612
        $tag = trim(Database::escape_string($tag));
3613
        $user_id = intval($user_id);
3614
        $field_id = intval($field_id);
3615
3616
        $tag_id = UserManager::get_tag_id($tag, $field_id);
3617
3618
        /* IMPORTANT
3619
         *  @todo we don't create tags with numbers
3620
         *
3621
         */
3622
        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...
3623
            //the form is sending an id this means that the user select it from the list so it MUST exists
3624
            /* $new_tag_id = UserManager::get_tag_id_from_id($tag,$field_id);
3625
              if ($new_tag_id !== false) {
3626
              $sql = "UPDATE $table_user_tag SET count = count + 1 WHERE id  = $new_tag_id";
3627
              $result = Database::query($sql);
3628
              $last_insert_id = $new_tag_id;
3629
              } else {
3630
              $sql = "INSERT INTO $table_user_tag (tag, field_id,count) VALUES ('$tag','$field_id', count + 1)";
3631
              $result = Database::query($sql);
3632
              $last_insert_id = Database::insert_id();
3633
              } */
3634
        }
3635
3636
        //this is a new tag
3637
        if ($tag_id == 0) {
3638
            //the tag doesn't exist
3639
            $sql = "INSERT INTO $table_user_tag (tag, field_id,count) VALUES ('$tag','$field_id', count + 1)";
3640
             Database::query($sql);
3641
            $last_insert_id = Database::insert_id();
3642
        } else {
3643
            //the tag exists we update it
3644
            $sql = "UPDATE $table_user_tag SET count = count + 1 WHERE id  = $tag_id";
3645
             Database::query($sql);
3646
            $last_insert_id = $tag_id;
3647
        }
3648
3649
        if (!empty($last_insert_id) && ($last_insert_id != 0)) {
3650
            //we insert the relationship user-tag
3651
            $sql = "SELECT tag_id FROM $table_user_tag_values
3652
                    WHERE user_id = $user_id AND tag_id = $last_insert_id ";
3653
            $result = Database::query($sql);
3654
            //if the relationship does not exist we create it
3655
            if (Database::num_rows($result) == 0) {
3656
                $sql = "INSERT INTO $table_user_tag_values SET user_id = $user_id, tag_id = $last_insert_id";
3657
                Database::query($sql);
3658
            }
3659
        }
3660
    }
3661
3662
    /**
3663
     * Deletes an user tag
3664
     * @param int $user_id
3665
     * @param int $field_id
3666
     *
3667
     */
3668
    public static function delete_user_tags($user_id, $field_id)
3669
    {
3670
        // database table definition
3671
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3672
        $table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
3673
        $tags = UserManager::get_user_tags($user_id, $field_id);
3674
        if (is_array($tags) && count($tags) > 0) {
3675
            foreach ($tags as $key => $tag) {
3676
                if ($tag['count'] > '0') {
3677
                    $sql = "UPDATE $table_user_tag SET count = count - 1  WHERE id = $key ";
3678
                    Database::query($sql);
3679
                }
3680
                $sql = "DELETE FROM $table_user_tag_values
3681
                        WHERE user_id = $user_id AND tag_id = $key";
3682
                Database::query($sql);
3683
            }
3684
        }
3685
    }
3686
3687
    /**
3688
     * Process the tag list comes from the UserManager::update_extra_field_value() function
3689
     * @param array $tags the tag list that will be added
3690
     * @param int $user_id
3691
     * @param int $field_id
3692
     *
3693
     * @return bool
3694
     */
3695
    public static function process_tags($tags, $user_id, $field_id)
3696
    {
3697
        // We loop the tags and add it to the DB
3698
        if (is_array($tags)) {
3699
            foreach ($tags as $tag) {
3700
                UserManager::add_tag($tag, $user_id, $field_id);
3701
            }
3702
        } else {
3703
            UserManager::add_tag($tags, $user_id, $field_id);
3704
        }
3705
3706
        return true;
3707
    }
3708
3709
    /**
3710
     * Returns a list of all administrators
3711
     *
3712
     * @return array
3713
     */
3714
    public static function get_all_administrators()
3715
    {
3716
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
3717
        $table_admin = Database::get_main_table(TABLE_MAIN_ADMIN);
3718
        $tbl_url_rel_user = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
3719
        $access_url_id = api_get_current_access_url_id();
3720
        if (api_get_multiple_access_url()) {
3721
            $sql = "SELECT admin.user_id, username, firstname, lastname, email, active
3722
                    FROM $tbl_url_rel_user as url
3723
                    INNER JOIN $table_admin as admin
3724
                    ON (admin.user_id=url.user_id)
3725
                    INNER JOIN $table_user u
3726
                    ON (u.id=admin.user_id)
3727
                    WHERE access_url_id ='".$access_url_id."'";
3728
        } else {
3729
            $sql = "SELECT admin.user_id, username, firstname, lastname, email, active
3730
                    FROM $table_admin as admin
3731
                    INNER JOIN $table_user u
3732
                    ON (u.id=admin.user_id)";
3733
        }
3734
        $result = Database::query($sql);
3735
        $return = array();
3736
        if (Database::num_rows($result) > 0) {
3737
            while ($row = Database::fetch_array($result, 'ASSOC')) {
3738
                $return[$row['user_id']] = $row;
3739
            }
3740
        }
3741
3742
        return $return;
3743
    }
3744
3745
    /**
3746
     * Search an user (tags, first name, last name and email )
3747
     * @param string $tag
3748
     * @param int $field_id field id of the tag
3749
     * @param int $from where to start in the query
3750
     * @param int $number_of_items
3751
     * @param bool $getCount get count or not
3752
     * @return array
3753
     */
3754
    public static function get_all_user_tags(
3755
        $tag,
3756
        $field_id = 0,
3757
        $from = 0,
3758
        $number_of_items = 10,
3759
        $getCount = false
3760
    ) {
3761
        $user_table = Database::get_main_table(TABLE_MAIN_USER);
3762
        $table_user_tag = Database::get_main_table(TABLE_MAIN_TAG);
3763
        $table_user_tag_values = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
3764
        $access_url_rel_user_table = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
3765
3766
        $field_id = intval($field_id);
3767
        $from = intval($from);
3768
        $number_of_items = intval($number_of_items);
3769
3770
        $where_field = "";
3771
        $where_extra_fields = UserManager::get_search_form_where_extra_fields();
3772
        if ($field_id != 0) {
3773
            $where_field = " field_id = $field_id AND ";
3774
        }
3775
3776
        // all the information of the field
3777
3778
        if ($getCount) {
3779
            $select = "SELECT count(DISTINCT u.id) count";
3780
        } else {
3781
            $select = "SELECT DISTINCT u.id, u.username, firstname, lastname, email, tag, picture_uri";
3782
        }
3783
3784
        $sql = " $select
3785
                FROM $user_table u
3786
                INNER JOIN $access_url_rel_user_table url_rel_user
3787
                ON (u.id = url_rel_user.user_id)
3788
                LEFT JOIN $table_user_tag_values uv
3789
                ON (u.id AND uv.user_id AND uv.user_id = url_rel_user.user_id)
3790
                LEFT JOIN $table_user_tag ut ON (uv.tag_id = ut.id)
3791
                WHERE
3792
                    ($where_field tag LIKE '".Database::escape_string($tag."%")."') OR
3793
                    (
3794
                        u.firstname LIKE '".Database::escape_string("%".$tag."%")."' OR
3795
                        u.lastname LIKE '".Database::escape_string("%".$tag."%")."' OR
3796
                        u.username LIKE '".Database::escape_string("%".$tag."%")."' OR
3797
                        concat(u.firstname, ' ', u.lastname) LIKE '".Database::escape_string("%".$tag."%")."' OR
3798
                        concat(u.lastname, ' ', u.firstname) LIKE '".Database::escape_string("%".$tag."%")."'
3799
                     )
3800
                     ".(!empty($where_extra_fields) ? $where_extra_fields : '')."
3801
                     AND url_rel_user.access_url_id=".api_get_current_access_url_id();
3802
3803
        $keyword_active = true;
3804
        // only active users
3805
        if ($keyword_active) {
3806
            $sql .= " AND u.active='1'";
3807
        }
3808
        // avoid anonymous
3809
        $sql .= " AND u.status <> 6 ";
3810
        $sql .= " ORDER BY username";
3811
        $sql .= " LIMIT $from , $number_of_items";
3812
3813
        $result = Database::query($sql);
3814
        $return = array();
3815
3816
        if (Database::num_rows($result) > 0) {
3817
            if ($getCount) {
3818
                $row = Database::fetch_array($result, 'ASSOC');
3819
                return $row['count'];
3820
            }
3821
            while ($row = Database::fetch_array($result, 'ASSOC')) {
3822
                if (isset($return[$row['id']]) &&
3823
                    !empty($return[$row['id']]['tag'])
3824
                ) {
3825
                    $url = Display::url(
3826
                        $row['tag'],
3827
                        api_get_path(WEB_PATH).'main/social/search.php?q='.$row['tag'],
3828
                        array('class' => 'tag')
3829
                    );
3830
                    $row['tag'] = $url;
3831
                }
3832
                $return[$row['id']] = $row;
3833
            }
3834
        }
3835
3836
        return $return;
3837
    }
3838
3839
    /**
3840
      * Get extra filtrable user fields (only type select)
3841
      * @return array
3842
      */
3843
    public static function get_extra_filtrable_fields()
3844
    {
3845
        $extraFieldList = UserManager::get_extra_fields();
3846
3847
        $extraFiltrableFields = array();
3848 View Code Duplication
        if (is_array($extraFieldList)) {
3849
            foreach ($extraFieldList as $extraField) {
3850
                // If is enabled to filter and is a "<select>" field type
3851
                if ($extraField[8] == 1 && $extraField[2] == 4) {
3852
                    $extraFiltrableFields[] = array(
3853
                        'name' => $extraField[3],
3854
                        'variable' => $extraField[1],
3855
                        'data' => $extraField[9]
3856
                    );
3857
                }
3858
            }
3859
        }
3860
3861
        if (is_array($extraFiltrableFields) && count($extraFiltrableFields) > 0) {
3862
            return $extraFiltrableFields;
3863
        }
3864
    }
3865
3866
    /**
3867
      * Get extra where clauses for finding users based on extra filtrable user fields (type select)
3868
      * @return string With AND clauses based on user's ID which have the values to search in extra user fields
3869
      */
3870
    public static function get_search_form_where_extra_fields()
3871
    {
3872
        $useExtraFields = false;
3873
        $extraFields = UserManager::get_extra_filtrable_fields();
3874
        $extraFieldResult = array();
3875 View Code Duplication
        if (is_array($extraFields) && count($extraFields)>0 ) {
3876
            foreach ($extraFields as $extraField) {
3877
                $varName = 'field_'.$extraField['variable'];
3878
                if (UserManager::is_extra_field_available($extraField['variable'])) {
3879
                    if (isset($_GET[$varName]) && $_GET[$varName]!='0') {
3880
                        $useExtraFields = true;
3881
                        $extraFieldResult[]= UserManager::get_extra_user_data_by_value(
3882
                            $extraField['variable'],
3883
                            $_GET[$varName]
3884
                        );
3885
                    }
3886
                }
3887
            }
3888
        }
3889
3890
        if ($useExtraFields) {
3891
            $finalResult = array();
3892
            if (count($extraFieldResult)>1) {
3893
                for ($i=0; $i < count($extraFieldResult) -1; $i++) {
3894
                if (is_array($extraFieldResult[$i]) && is_array($extraFieldResult[$i+1])) {
3895
                        $finalResult  = array_intersect($extraFieldResult[$i], $extraFieldResult[$i+1]);
3896
                    }
3897
                }
3898
            } else {
3899
                $finalResult = $extraFieldResult[0];
3900
            }
3901
3902
            if (is_array($finalResult) && count($finalResult)>0) {
3903
                $whereFilter = " AND u.id IN  ('".implode("','", $finalResult)."') ";
3904
            } else {
3905
                //no results
3906
                $whereFilter = " AND u.id  = -1 ";
3907
            }
3908
3909
            return $whereFilter;
3910
        }
3911
    }
3912
3913
    /**
3914
     * Show the search form
3915
     * @param string $query the value of the search box
3916
     * @return string HTML form
3917
     */
3918
    public static function get_search_form($query, $defaultParams = [])
3919
    {
3920
        $searchType = isset($_GET['search_type']) ? $_GET['search_type'] : null;
3921
        $form = new FormValidator(
3922
            'search_user',
3923
            'get',
3924
            api_get_path(WEB_PATH).'main/social/search.php',
3925
            '',
3926
            array(),
3927
            FormValidator::LAYOUT_HORIZONTAL
3928
        );
3929
3930
        $form->addText('q', get_lang('UsersGroups'), false);
3931
        $options = array(
3932
            0 => get_lang('Select'),
3933
            1 => get_lang('User'),
3934
            2 => get_lang('Group'),
3935
        );
3936
        $form->addSelect(
3937
            'search_type',
3938
            get_lang('Type'),
3939
            $options,
3940
            array('onchange' => 'javascript: extra_field_toogle();')
3941
        );
3942
3943
        // Extra fields
3944
3945
        $extraFields = UserManager::get_extra_filtrable_fields();
3946
        $defaults = [];
3947
        if (is_array($extraFields) && count($extraFields) > 0) {
3948
            foreach ($extraFields as $extraField) {
3949
                $varName = 'field_'.$extraField['variable'];
3950
3951
                $options = [
3952
                    0 => get_lang('Select')
3953
                ];
3954
                foreach ($extraField['data'] as $option) {
3955
                    $checked = '';
3956
                    if (isset($_GET[$varName])) {
3957
                        if ($_GET[$varName] == $option[1]) {
3958
                            $defaults[$option[1]] = true;
3959
                        }
3960
                    }
3961
3962
                    $options[$option[1]] = $option[1];
3963
                }
3964
                $form->addSelect($varName, $extraField['name'], $options);
3965
            }
3966
        }
3967
3968
        $defaults['search_type'] = intval($searchType);
3969
        $defaults['q'] = api_htmlentities(Security::remove_XSS($query));
3970
3971
        if (!empty($defaultParams)) {
3972
            $defaults = array_merge($defaults, $defaultParams);
3973
        }
3974
        $form->setDefaults($defaults);
3975
3976
        $form->addButtonSearch(get_lang('Search'));
3977
3978
        $js = '<script>
3979
        extra_field_toogle();
3980
        function extra_field_toogle() {
3981
            if (jQuery("select[name=search_type]").val() != "1") { jQuery(".extra_field").hide(); } else { jQuery(".extra_field").show(); }
3982
        }
3983
        </script>';
3984
3985
        return $js.$form->returnForm();
3986
    }
3987
3988
    /**
3989
     * Shows the user menu
3990
     */
3991
    public static function show_menu()
3992
    {
3993
        echo '<div class="actions">';
3994
        echo '<a href="/main/auth/profile.php">'.Display::return_icon('profile.png').' '.get_lang('PersonalData').'</a>';
3995
        echo '<a href="/main/messages/inbox.php">'.Display::return_icon('inbox.png').' '.get_lang('Inbox').'</a>';
3996
        echo '<a href="/main/messages/outbox.php">'.Display::return_icon('outbox.png').' '.get_lang('Outbox').'</a>';
3997
        echo '<span style="float:right; padding-top:7px;">'.
3998
        '<a href="/main/auth/profile.php?show=1">'.Display::return_icon('edit.gif').' '.get_lang('Configuration').'</a>';
3999
        '</span>';
4000
        echo '</div>';
4001
    }
4002
4003
    /**
4004
     * Allow to register contact to social network
4005
     * @param int $friend_id user friend id
4006
     * @param int $my_user_id user id
4007
     * @param int $relation_type relation between users see constants definition
4008
     */
4009
    public static function relate_users($friend_id, $my_user_id, $relation_type)
4010
    {
4011
        $tbl_my_friend = Database :: get_main_table(TABLE_MAIN_USER_REL_USER);
4012
4013
        $friend_id = intval($friend_id);
4014
        $my_user_id = intval($my_user_id);
4015
        $relation_type = intval($relation_type);
4016
4017
        $sql = 'SELECT COUNT(*) as count FROM '.$tbl_my_friend.'
4018
                WHERE
4019
                    friend_user_id='.$friend_id.' AND
4020
                    user_id='.$my_user_id.' AND
4021
                    relation_type <> '.USER_RELATION_TYPE_RRHH.' ';
4022
        $result = Database::query($sql);
4023
        $row = Database :: fetch_array($result, 'ASSOC');
4024
        $current_date = api_get_utc_datetime();
4025
4026
        if ($row['count'] == 0) {
4027
            $sql = 'INSERT INTO '.$tbl_my_friend.'(friend_user_id,user_id,relation_type,last_edit)
4028
                    VALUES ('.$friend_id.','.$my_user_id.','.$relation_type.',"'.$current_date.'")';
4029
            Database::query($sql);
4030
            return true;
4031
        }
4032
4033
        $sql = 'SELECT COUNT(*) as count, relation_type  FROM '.$tbl_my_friend.'
4034
                WHERE
4035
                    friend_user_id='.$friend_id.' AND
4036
                    user_id='.$my_user_id.' AND
4037
                    relation_type <> '.USER_RELATION_TYPE_RRHH.' ';
4038
        $result = Database::query($sql);
4039
        $row = Database :: fetch_array($result, 'ASSOC');
4040
4041
        if ($row['count'] == 1) {
4042
            //only for the case of a RRHH
4043
            if ($row['relation_type'] != $relation_type && $relation_type == USER_RELATION_TYPE_RRHH) {
4044
                $sql = 'INSERT INTO '.$tbl_my_friend.'(friend_user_id,user_id,relation_type,last_edit)
4045
                        VALUES ('.$friend_id.','.$my_user_id.','.$relation_type.',"'.$current_date.'")';
4046
            } else {
4047
                $sql = 'UPDATE '.$tbl_my_friend.' SET relation_type='.$relation_type.'
4048
                        WHERE friend_user_id='.$friend_id.' AND user_id='.$my_user_id;
4049
            }
4050
            Database::query($sql);
4051
4052
            return true;
4053
        }
4054
4055
        return false;
4056
    }
4057
4058
    /**
4059
     * Deletes a contact
4060
     * @param int user friend id
4061
     * @param bool true will delete ALL friends relationship from $friend_id
4062
     * @author isaac flores paz <[email protected]>
4063
     * @author Julio Montoya <[email protected]> Cleaning code
4064
     */
4065
    public static function remove_user_rel_user($friend_id, $real_removed = false, $with_status_condition = '')
4066
    {
4067
        $tbl_my_friend = Database :: get_main_table(TABLE_MAIN_USER_REL_USER);
4068
        $tbl_my_message = Database :: get_main_table(TABLE_MESSAGE);
4069
        $friend_id = intval($friend_id);
4070
4071
        if ($real_removed) {
4072
            $extra_condition = '';
4073
            if ($with_status_condition != '') {
4074
                $extra_condition = ' AND relation_type = '.intval($with_status_condition);
4075
            }
4076
            $sql = 'DELETE FROM '.$tbl_my_friend.'
4077
                    WHERE relation_type <> '.USER_RELATION_TYPE_RRHH.' AND friend_user_id='.$friend_id.' '.$extra_condition;
4078
            Database::query($sql);
4079
            $sql= 'DELETE FROM '.$tbl_my_friend.'
4080
                   WHERE relation_type <> '.USER_RELATION_TYPE_RRHH.' AND user_id='.$friend_id.' '.$extra_condition;
4081
            Database::query($sql);
4082
        } else {
4083
            $user_id = api_get_user_id();
4084
            $sql = 'SELECT COUNT(*) as count FROM '.$tbl_my_friend.'
4085
                    WHERE
4086
                        user_id='.$user_id.' AND
4087
                        relation_type NOT IN('.USER_RELATION_TYPE_DELETED.', '.USER_RELATION_TYPE_RRHH.') AND
4088
                        friend_user_id='.$friend_id;
4089
            $result = Database::query($sql);
4090
            $row = Database :: fetch_array($result, 'ASSOC');
4091
            if ($row['count'] == 1) {
4092
                //Delete user rel user
4093
                $sql_i = 'UPDATE '.$tbl_my_friend.' SET relation_type='.USER_RELATION_TYPE_DELETED.'
4094
                          WHERE user_id='.$user_id.' AND friend_user_id='.$friend_id;
4095
                $sql_j = 'UPDATE '.$tbl_my_message.' SET msg_status='.MESSAGE_STATUS_INVITATION_DENIED.'
4096
                          WHERE user_receiver_id='.$user_id.' AND user_sender_id='.$friend_id.' AND update_date="0000-00-00 00:00:00" ';
4097
                //Delete user
4098
                $sql_ij = 'UPDATE '.$tbl_my_friend.'  SET relation_type='.USER_RELATION_TYPE_DELETED.'
4099
                           WHERE user_id='.$friend_id.' AND friend_user_id='.$user_id;
4100
                $sql_ji = 'UPDATE '.$tbl_my_message.' SET msg_status='.MESSAGE_STATUS_INVITATION_DENIED.'
4101
                           WHERE user_receiver_id='.$friend_id.' AND user_sender_id='.$user_id.' AND update_date="0000-00-00 00:00:00" ';
4102
                Database::query($sql_i);
4103
                Database::query($sql_j);
4104
                Database::query($sql_ij);
4105
                Database::query($sql_ji);
4106
            }
4107
        }
4108
    }
4109
4110
    /**
4111
     * @param int $userId
4112
     * @return array
4113
     */
4114
    public static function getDrhListFromUser($userId)
4115
    {
4116
        $tblUser = Database::get_main_table(TABLE_MAIN_USER);
4117
        $tblUserRelUser = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
4118
        $tblUserRelAccessUrl = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
4119
        $userId = intval($userId);
4120
4121
        $orderBy = null;
4122
        if (api_is_western_name_order()) {
4123
            $orderBy .= " ORDER BY firstname, lastname ";
4124
        } else {
4125
            $orderBy .= " ORDER BY lastname, firstname ";
4126
        }
4127
4128
        $sql = "SELECT u.id, username, u.firstname, u.lastname
4129
                FROM $tblUser u
4130
                INNER JOIN $tblUserRelUser uru ON (uru.friend_user_id = u.id)
4131
                INNER JOIN $tblUserRelAccessUrl a ON (a.user_id = u.id)
4132
                WHERE
4133
                    access_url_id = ".api_get_current_access_url_id()." AND
4134
                    uru.user_id = '$userId' AND
4135
                    relation_type = '".USER_RELATION_TYPE_RRHH."'
4136
                $orderBy
4137
                ";
4138
        $result = Database::query($sql);
4139
4140
        return Database::store_result($result);
4141
    }
4142
4143
    /**
4144
     * get users followed by human resource manager
4145
     * @param int $userId
4146
     * @param int $userStatus (STUDENT, COURSEMANAGER, etc)
4147
     * @param bool $getOnlyUserId
4148
     * @param bool $getSql
4149
     * @param bool $getCount
4150
     * @param int $from
4151
     * @param int $numberItems
4152
     * @param int $column
4153
     * @param string $direction
4154
     * @param int $active
4155
     * @param string $lastConnectionDate
4156
     * @return array     users
4157
     */
4158 View Code Duplication
    public static function get_users_followed_by_drh(
4159
        $userId,
4160
        $userStatus = 0,
4161
        $getOnlyUserId = false,
4162
        $getSql = false,
4163
        $getCount = false,
4164
        $from = null,
4165
        $numberItems = null,
4166
        $column = null,
4167
        $direction = null,
4168
        $active = null,
4169
        $lastConnectionDate = null
4170
    ) {
4171
        return self::getUsersFollowedByUser(
4172
            $userId,
4173
            $userStatus,
4174
            $getOnlyUserId,
4175
            $getSql,
4176
            $getCount,
4177
            $from,
4178
            $numberItems,
4179
            $column,
4180
            $direction,
4181
            $active,
4182
            $lastConnectionDate,
4183
            DRH
4184
        );
4185
    }
4186
4187
    /**
4188
    * Get users followed by human resource manager
4189
    * @param int $userId
4190
    * @param int  $userStatus Filter users by status (STUDENT, COURSEMANAGER, etc)
4191
    * @param bool $getOnlyUserId
4192
    * @param bool $getSql
4193
    * @param bool $getCount
4194
    * @param int $from
4195
    * @param int $numberItems
4196
    * @param int $column
4197
    * @param string $direction
4198
    * @param int $active
4199
    * @param string $lastConnectionDate
4200
    * @param int $status the function is called by who? COURSEMANAGER, DRH?
4201
    * @param string $keyword
4202
     *
4203
    * @return array user list
4204
    */
4205
    public static function getUsersFollowedByUser(
4206
        $userId,
4207
        $userStatus = null,
4208
        $getOnlyUserId = false,
4209
        $getSql = false,
4210
        $getCount = false,
4211
        $from = null,
4212
        $numberItems = null,
4213
        $column = null,
4214
        $direction = null,
4215
        $active = null,
4216
        $lastConnectionDate = null,
4217
        $status = null,
4218
        $keyword = null
4219
    ) {
4220
        // Database Table Definitions
4221
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
4222
        $tbl_user_rel_user = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
4223
        $tbl_user_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
4224
4225
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
4226
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4227
4228
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4229
        $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
4230
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
4231
4232
        $userId = intval($userId);
4233
4234
        $limitCondition = '';
4235
4236 View Code Duplication
        if (isset($from) && isset($numberItems)) {
4237
            $from = intval($from);
4238
            $numberItems = intval($numberItems);
4239
            $limitCondition = "LIMIT $from, $numberItems";
4240
        }
4241
4242
        $column = Database::escape_string($column);
4243
        $direction = in_array(strtolower($direction), array('asc', 'desc')) ? $direction : null;
4244
4245
        $userConditions = '';
4246
        if (!empty($userStatus)) {
4247
            $userConditions .= ' AND u.status = '.intval($userStatus);
4248
        }
4249
4250
        $select = " SELECT DISTINCT u.id user_id, u.username, u.lastname, u.firstname, u.email ";
4251
        if ($getOnlyUserId) {
4252
            $select = " SELECT DISTINCT u.id user_id";
4253
        }
4254
4255
        $masterSelect = "SELECT DISTINCT * FROM ";
4256
4257
        if ($getCount) {
4258
            $masterSelect = "SELECT COUNT(DISTINCT(user_id)) as count FROM ";
4259
            $select = " SELECT DISTINCT(u.id) user_id";
4260
        }
4261
4262
        if (!is_null($active)) {
4263
            $active = intval($active);
4264
            $userConditions .= " AND u.active = $active ";
4265
        }
4266
4267 View Code Duplication
        if (!empty($keyword)) {
4268
            $keyword = Database::escape_string($keyword);
4269
            $userConditions .= " AND (
4270
                u.username LIKE '%$keyword%' OR
4271
                u.firstname LIKE '%$keyword%' OR
4272
                u.lastname LIKE '%$keyword%' OR
4273
                u.official_code LIKE '%$keyword%' OR
4274
                u.email LIKE '%$keyword%'
4275
            )";
4276
        }
4277
4278
        if (!empty($lastConnectionDate)) {
4279
            $lastConnectionDate = Database::escape_string($lastConnectionDate);
4280
            $userConditions .=  " AND u.last_login <= '$lastConnectionDate' ";
4281
        }
4282
4283
        $courseConditions = null;
4284
        $sessionConditionsCoach = null;
4285
        $sessionConditionsTeacher = null;
4286
        $drhConditions = null;
4287
        $teacherSelect = null;
4288
4289
        switch ($status) {
4290
            case DRH:
4291
                $drhConditions .= " AND
4292
                    friend_user_id = '$userId' AND
4293
                    relation_type = '".USER_RELATION_TYPE_RRHH."'
4294
                ";
4295
                break;
4296
            case COURSEMANAGER:
4297
                $drhConditions .= " AND
4298
                    friend_user_id = '$userId' AND
4299
                    relation_type = '".USER_RELATION_TYPE_RRHH."'
4300
                ";
4301
4302
                $sessionConditionsCoach .= " AND
4303
                    (s.id_coach = '$userId')
4304
                ";
4305
4306
                $sessionConditionsTeacher .= " AND
4307
                    (scu.status = 2 AND scu.user_id = '$userId')
4308
                ";
4309
4310
                $teacherSelect =
4311
                "UNION ALL (
4312
                        $select
4313
                        FROM $tbl_user u
4314
                        INNER JOIN $tbl_session_rel_user sru ON (sru.user_id = u.id)
4315
                        WHERE
4316
                            (
4317
                                sru.session_id IN (
4318
                                    SELECT DISTINCT(s.id) FROM $tbl_session s INNER JOIN
4319
                                    $tbl_session_rel_access_url session_rel_access_rel_user
4320
                                    ON session_rel_access_rel_user.session_id = s.id
4321
                                    WHERE access_url_id = ".api_get_current_access_url_id()."
4322
                                    $sessionConditionsCoach                                  
4323
                                ) OR sru.session_id IN (
4324
                                    SELECT DISTINCT(s.id) FROM $tbl_session s
4325
                                    INNER JOIN $tbl_session_rel_access_url url
4326
                                    ON (url.session_id = s.id)
4327
                                    INNER JOIN $tbl_session_rel_course_rel_user scu
4328
                                    ON (scu.session_id = s.id)
4329
                                    WHERE access_url_id = ".api_get_current_access_url_id()."
4330
                                    $sessionConditionsTeacher
4331
                                )
4332
                            )                            
4333
                            $userConditions
4334
                    )
4335
                    UNION ALL(
4336
                        $select
4337
                        FROM $tbl_user u
4338
                        INNER JOIN $tbl_course_user cu ON (cu.user_id = u.id)
4339
                        WHERE cu.c_id IN (
4340
                            SELECT DISTINCT(c_id) FROM $tbl_course_user
4341
                            WHERE user_id = $userId AND status = ".COURSEMANAGER."
4342
                        )
4343
                        $userConditions
4344
                    )"
4345
                ;
4346
                break;
4347
            case STUDENT_BOSS:
4348
                $drhConditions = " AND friend_user_id = $userId AND relation_type = " . USER_RELATION_TYPE_BOSS;
4349
                break;
4350
        }
4351
4352
        $join = null;
4353
        $sql = " $masterSelect
4354
                (
4355
                    (
4356
                        $select
4357
                        FROM $tbl_user u
4358
                        INNER JOIN $tbl_user_rel_user uru ON (uru.user_id = u.id)
4359
                        LEFT JOIN $tbl_user_rel_access_url a ON (a.user_id = u.id)
4360
                        $join
4361
                        WHERE
4362
                            access_url_id = ".api_get_current_access_url_id()."
4363
                            $drhConditions
4364
                            $userConditions
4365
                    )
4366
                    $teacherSelect
4367
4368
                ) as t1";
4369
4370
        if ($getSql) {
4371
            return $sql;
4372
        }
4373 View Code Duplication
        if ($getCount) {
4374
            $result = Database::query($sql);
4375
            $row = Database::fetch_array($result);
4376
            return $row['count'];
4377
        }
4378
4379
        $orderBy = null;
4380
        if ($getOnlyUserId == false) {
4381
            if (api_is_western_name_order()) {
4382
                $orderBy .= " ORDER BY firstname, lastname ";
4383
            } else {
4384
                $orderBy .= " ORDER BY lastname, firstname ";
4385
            }
4386
4387 View Code Duplication
            if (!empty($column) && !empty($direction)) {
4388
                // Fixing order due the UNIONs
4389
                $column = str_replace('u.', '', $column);
4390
                $orderBy = " ORDER BY $column $direction ";
4391
            }
4392
        }
4393
4394
        $sql .= $orderBy;
4395
        $sql .= $limitCondition;
4396
4397
        $result = Database::query($sql);
4398
        $users = array();
4399
        if (Database::num_rows($result) > 0) {
4400
4401
            while ($row = Database::fetch_array($result)) {
4402
                $users[$row['user_id']] = $row;
4403
            }
4404
        }
4405
4406
        return $users;
4407
    }
4408
4409
    /**
4410
     * Subscribes users to human resource manager (Dashboard feature)
4411
     * @param   int    $hr_dept_id
4412
     * @param   array   $users_id
4413
     * @param   int     affected rows
4414
     * */
4415
    public static function subscribeUsersToHRManager($hr_dept_id, $users_id)
4416
    {
4417
        return self::subscribeUsersToUser($hr_dept_id, $users_id, USER_RELATION_TYPE_RRHH);
4418
    }
4419
4420
    /**
4421
     * Add subscribed users to a user by relation type
4422
     * @param int $userId The user id
4423
     * @param array $subscribedUsersId The id of suscribed users
4424
     * @param string $relationType The relation type
4425
     * @param bool $deleteUsersBeforeInsert
4426
     */
4427
    public static function subscribeUsersToUser($userId, $subscribedUsersId, $relationType, $deleteUsersBeforeInsert = false)
4428
    {
4429
        $userRelUserTable = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
4430
        $userRelAccessUrlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
4431
4432
        $userId = intval($userId);
4433
        $relationType = intval($relationType);
4434
        $affectedRows = 0;
4435
4436
        if (api_get_multiple_access_url()) {
4437
            // Deleting assigned users to hrm_id
4438
            $sql = "SELECT s.user_id FROM $userRelUserTable s 
4439
                    INNER JOIN $userRelAccessUrlTable a ON (a.user_id = s.user_id) 
4440
                    WHERE 
4441
                        friend_user_id = $userId AND 
4442
                        relation_type = $relationType AND 
4443
                        access_url_id = " . api_get_current_access_url_id();
4444
        } else {
4445
            $sql = "SELECT user_id FROM $userRelUserTable 
4446
                    WHERE friend_user_id = $userId 
4447
                    AND relation_type = $relationType";
4448
        }
4449
        $result = Database::query($sql);
4450
4451 View Code Duplication
        if (Database::num_rows($result) > 0) {
4452
            while ($row = Database::fetch_array($result)) {
4453
                $sql = "DELETE FROM $userRelUserTable 
4454
                        WHERE 
4455
                          user_id = {$row['user_id']} AND 
4456
                          friend_user_id = $userId AND 
4457
                          relation_type = $relationType";
4458
                Database::query($sql);
4459
            }
4460
        }
4461
4462
        if ($deleteUsersBeforeInsert) {
4463
            $sql = "DELETE FROM $userRelUserTable 
4464
                    WHERE 
4465
                        user_id = $userId AND
4466
                        relation_type = $relationType";
4467
            Database::query($sql);
4468
        }
4469
4470
        // Inserting new user list
4471
        if (is_array($subscribedUsersId)) {
4472
            foreach ($subscribedUsersId as $subscribedUserId) {
4473
                $subscribedUserId = intval($subscribedUserId);
4474
4475
                $sql = "INSERT IGNORE INTO $userRelUserTable (user_id, friend_user_id, relation_type)
4476
                        VALUES ($subscribedUserId, $userId, $relationType)";
4477
4478
                $result = Database::query($sql);
4479
                $affectedRows = Database::affected_rows($result);
4480
            }
4481
        }
4482
4483
        return $affectedRows;
4484
    }
4485
4486
    /**
4487
     * This function check if an user is followed by human resources manager
4488
     * @param     int     $user_id
4489
     * @param    int      $hr_dept_id  Human resources manager
4490
     * @return    bool
4491
     */
4492
    public static function is_user_followed_by_drh($user_id, $hr_dept_id)
4493
    {
4494
        // Database table and variables Definitions
4495
        $tbl_user_rel_user = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
4496
        $user_id = intval($user_id);
4497
        $hr_dept_id = intval($hr_dept_id);
4498
        $result = false;
4499
4500
        $sql = "SELECT user_id FROM $tbl_user_rel_user
4501
                WHERE
4502
                    user_id = $user_id AND
4503
                    friend_user_id = $hr_dept_id AND
4504
                    relation_type = ".USER_RELATION_TYPE_RRHH;
4505
        $rs = Database::query($sql);
4506
        if (Database::num_rows($rs) > 0) {
4507
            $result = true;
4508
        }
4509
        return $result;
4510
    }
4511
4512
    /**
4513
     * get user id of teacher or session administrator
4514
     * @param array $courseInfo
4515
     *
4516
     * @return int The user id
4517
     */
4518
    public static function get_user_id_of_course_admin_or_session_admin($courseInfo)
4519
    {
4520
        $session = api_get_session_id();
4521
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
4522
        $table_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4523
        $table_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4524
        $courseId = $courseInfo['real_id'];
4525
4526
        if ($session == 0 || is_null($session)) {
4527
            $sql = 'SELECT u.id uid FROM '.$table_user.' u
4528
                    INNER JOIN '.$table_course_user.' ru
4529
                    ON ru.user_id = u.id
4530
                    WHERE
4531
                        ru.status = 1 AND
4532
                        ru.c_id = "'.$courseId.'" ';
4533
            $rs = Database::query($sql);
4534
            $num_rows = Database::num_rows($rs);
4535
            if ($num_rows == 1) {
4536
                $row = Database::fetch_array($rs);
4537
                return $row['uid'];
4538
            } else {
4539
                $my_num_rows = $num_rows;
4540
                $my_user_id = Database::result($rs, $my_num_rows - 1, 'uid');
4541
4542
                return $my_user_id;
4543
            }
4544
        } elseif ($session > 0) {
4545
            $sql = 'SELECT u.id uid FROM '.$table_user.' u
4546
                    INNER JOIN '.$table_session_course_user.' sru
4547
                    ON sru.user_id=u.id
4548
                    WHERE
4549
                        sru.c_id="'.$courseId.'" AND
4550
                        sru.status=2';
4551
            $rs = Database::query($sql);
4552
            $row = Database::fetch_array($rs);
4553
4554
            return $row['uid'];
4555
        }
4556
    }
4557
4558
    /**
4559
     * Determines if a user is a gradebook certified
4560
     * @param int $cat_id The category id of gradebook
4561
     * @param int $user_id The user id
4562
     * @return boolean
4563
     */
4564 View Code Duplication
    public static function is_user_certified($cat_id, $user_id)
4565
    {
4566
        $table_certificate = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
4567
        $sql = 'SELECT path_certificate FROM '.$table_certificate.'
4568
                WHERE
4569
                    cat_id="'.intval($cat_id).'" AND
4570
                    user_id="'.intval($user_id).'"';
4571
        $rs = Database::query($sql);
4572
        $row = Database::fetch_array($rs);
4573
        if ($row['path_certificate'] == '' || is_null($row['path_certificate'])) {
4574
            return false;
4575
        } else {
4576
            return true;
4577
        }
4578
    }
4579
4580
    /**
4581
     * Gets the info about a gradebook certificate for a user by course
4582
     * @param int $courseId course id
4583
     * @param int $user_id The user id
4584
     * @return array  if there is not information return false
4585
     */
4586
    public static function getInfoGradeBookCertificate($courseId, $user_id)
4587
    {
4588
        $tbl_grade_certificate = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
4589
        $tbl_grade_category = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
4590
        $session_id = api_get_session_id();
4591
4592
        if (empty($session_id)) {
4593
            $session_condition = ' AND (session_id = "" OR session_id = 0 OR session_id IS NULL )';
4594
        } else {
4595
            $session_condition = " AND session_id = $session_id";
4596
        }
4597
4598
        $sql = 'SELECT * FROM '.$tbl_grade_certificate.' 
4599
                WHERE cat_id = (
4600
                    SELECT id FROM '.$tbl_grade_category.'
4601
                    WHERE
4602
                        c_id = "'.Database::escape_string($courseId).'" '.$session_condition.' 
4603
                    LIMIT 1
4604
                 ) 
4605
                 AND user_id='.intval($user_id);
4606
4607
        $rs = Database::query($sql);
4608
        if (Database::num_rows($rs) > 0) {
4609
            $row = Database::fetch_array($rs, 'ASSOC');
4610
            $score = $row['score_certificate'];
4611
            $category_id = $row['cat_id'];
4612
            $cat = Category::load($category_id);
4613
            $displayscore = ScoreDisplay::instance();
4614
            if (isset($cat) && $displayscore->is_custom()) {
4615
                $grade = $displayscore->display_score(array($score, $cat[0]->get_weight()), SCORE_DIV_PERCENT_WITH_CUSTOM);
4616
            } else {
4617
                $grade = $displayscore->display_score(array($score, $cat[0]->get_weight()));
4618
            }
4619
            $row['grade'] = $grade;
4620
4621
            return $row;
4622
        }
4623
4624
        return false;
4625
    }
4626
4627
    /**
4628
     * Gets the user path of user certificated
4629
     * @param int The user id
4630
     * @return array  containing path_certificate and cat_id
4631
     */
4632
    public static function get_user_path_certificate($user_id)
4633
    {
4634
        $my_certificate = array();
4635
        $table_certificate = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
4636
        $table_gradebook_category = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
4637
4638
        $session_id = api_get_session_id();
4639
        $user_id = intval($user_id);
4640 View Code Duplication
        if ($session_id == 0 || is_null($session_id)) {
4641
            $sql_session = 'AND (session_id='.intval($session_id).' OR isnull(session_id)) ';
4642
        } elseif ($session_id > 0) {
4643
            $sql_session = 'AND session_id='.intval($session_id);
4644
        } else {
4645
            $sql_session = '';
4646
        }
4647
        $sql = "SELECT tc.path_certificate,tc.cat_id,tgc.course_code,tgc.name
4648
                FROM $table_certificate tc, $table_gradebook_category tgc
4649
                WHERE tgc.id = tc.cat_id AND tc.user_id = $user_id
4650
                ORDER BY tc.date_certificate DESC 
4651
                LIMIT 5";
4652
4653
        $rs = Database::query($sql);
4654
        while ($row = Database::fetch_array($rs)) {
4655
            $my_certificate[] = $row;
4656
        }
4657
        return $my_certificate;
4658
    }
4659
4660
    /**
4661
     * This function check if the user is a coach inside session course
4662
     * @param  int  $user_id    User id
4663
     * @param  int  $courseId
4664
     * @param  int  $session_id
4665
     * @return bool    True if the user is a coach
4666
     *
4667
     */
4668 View Code Duplication
    public static function is_session_course_coach($user_id, $courseId, $session_id)
4669
    {
4670
        $tbl_session_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4671
        // Protect data
4672
        $user_id = intval($user_id);
4673
        $courseId = intval($courseId);
4674
        $session_id = intval($session_id);
4675
        $result = false;
4676
4677
        $sql = "SELECT session_id FROM $tbl_session_course_rel_user
4678
                WHERE
4679
                  session_id = $session_id AND
4680
                  c_id = $courseId AND
4681
                  user_id = $user_id AND
4682
                  status = 2 ";
4683
        $res = Database::query($sql);
4684
4685
        if (Database::num_rows($res) > 0) {
4686
            $result = true;
4687
        }
4688
        return $result;
4689
    }
4690
4691
    /**
4692
     * This function returns an icon path that represents the favicon of the website of which the url given.
4693
     * Defaults to the current Chamilo favicon
4694
     * @param    string    $url1 URL of website where to look for favicon.ico
4695
     * @param    string    $url2 Optional second URL of website where to look for favicon.ico
4696
     * @return    string    Path of icon to load
4697
     */
4698
    public static function get_favicon_from_url($url1, $url2 = null)
4699
    {
4700
        $icon_link = '';
4701
        $url = $url1;
4702
        if (empty($url1)) {
4703
            $url = $url2;
4704
            if (empty($url)) {
4705
                $url = api_get_access_url(api_get_current_access_url_id());
4706
                $url = $url[0];
4707
            }
4708
        }
4709
        if (!empty($url)) {
4710
            $pieces = parse_url($url);
4711
            $icon_link = $pieces['scheme'].'://'.$pieces['host'].'/favicon.ico';
4712
        }
4713
        return $icon_link;
4714
    }
4715
4716
    /**
4717
     *
4718
     * @param int   student id
4719
     * @param int   years
4720
     * @param bool  show warning_message
4721
     * @param bool  return_timestamp
4722
     */
4723
    public static function delete_inactive_student($student_id, $years = 2, $warning_message = false, $return_timestamp = false)
4724
    {
4725
        $tbl_track_login = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
4726
        $sql = 'SELECT login_date FROM '.$tbl_track_login.'
4727
                WHERE login_user_id = '.intval($student_id).'
4728
                ORDER BY login_date DESC LIMIT 0,1';
4729
        if (empty($years)) {
4730
            $years = 1;
4731
        }
4732
        $inactive_time = $years * 31536000;  //1 year
4733
        $rs = Database::query($sql);
4734
        if (Database::num_rows($rs) > 0) {
4735
            if ($last_login_date = Database::result($rs, 0, 0)) {
4736
                $last_login_date = api_get_local_time($last_login_date, null, date_default_timezone_get());
4737
                if ($return_timestamp) {
4738
                    return api_strtotime($last_login_date);
4739
                } else {
4740
                    if (!$warning_message) {
4741
                        return api_format_date($last_login_date, DATE_FORMAT_SHORT);
4742
                    } else {
4743
                        $timestamp = api_strtotime($last_login_date);
4744
                        $currentTimestamp = time();
4745
4746
                        //If the last connection is > than 7 days, the text is red
4747
                        //345600 = 7 days in seconds 63072000= 2 ans
4748
                        // if ($currentTimestamp - $timestamp > 184590 )
4749
                        if ($currentTimestamp - $timestamp > $inactive_time && UserManager::delete_user($student_id)) {
4750
                            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...
4751
                            echo '<p>', 'id', $student_id, ':', $last_login_date, '</p>';
4752
                        }
4753
                    }
4754
                }
4755
            }
4756
        }
4757
        return false;
4758
    }
4759
4760
    /**
4761
     * @param FormValidator $form
4762
     * @param $extra_data
4763
     * @param $form_name
4764
     * @param bool $admin_permissions
4765
     * @param null $user_id
4766
     * @deprecated
4767
     * @return array
4768
     */
4769
    public static function set_extra_fields_in_form(
4770
        $form,
4771
        $extra_data,
4772
        $admin_permissions = false,
4773
        $user_id = null
4774
    ) {
4775
        $user_id = intval($user_id);
4776
4777
        // EXTRA FIELDS
4778
        $extra = UserManager::get_extra_fields(0, 50, 5, 'ASC');
4779
        $jquery_ready_content = null;
4780
        foreach ($extra as $field_details) {
4781
4782
            if (!$admin_permissions) {
4783
                if ($field_details[6] == 0) {
4784
                    continue;
4785
                }
4786
            }
4787
4788
            switch ($field_details[2]) {
4789 View Code Duplication
                case ExtraField::FIELD_TYPE_TEXT:
4790
                    $form->addElement('text', 'extra_'.$field_details[1], $field_details[3], array('size' => 40));
4791
                    $form->applyFilter('extra_'.$field_details[1], 'stripslashes');
4792
                    $form->applyFilter('extra_'.$field_details[1], 'trim');
4793
                    $form->applyFilter('extra_'.$field_details[1], 'html_filter');
4794
4795
                    if (!$admin_permissions) {
4796
                        if ($field_details[7] == 0) {
4797
                            $form->freeze('extra_'.$field_details[1]);
4798
                        }
4799
                    }
4800
                    break;
4801 View Code Duplication
                case ExtraField::FIELD_TYPE_TEXTAREA:
4802
                    $form->addHtmlEditor(
4803
                        'extra_'.$field_details[1],
4804
                        $field_details[3],
4805
                        false,
4806
                        false,
4807
                        array('ToolbarSet' => 'Profile', 'Width' => '100%', 'Height' => '130')
4808
                    );
4809
                    $form->applyFilter('extra_'.$field_details[1], 'stripslashes');
4810
                    $form->applyFilter('extra_'.$field_details[1], 'trim');
4811
                    if (!$admin_permissions) {
4812
                        if ($field_details[7] == 0)
4813
                            $form->freeze('extra_'.$field_details[1]);
4814
                    }
4815
                    break;
4816
                case ExtraField::FIELD_TYPE_RADIO:
4817
                    $group = array();
4818 View Code Duplication
                    foreach ($field_details[9] as $option_id => $option_details) {
4819
                        $options[$option_details[1]] = $option_details[2];
4820
                        $group[] = $form->createElement(
4821
                            'radio',
4822
                            'extra_'.$field_details[1],
4823
                            $option_details[1],
4824
                            $option_details[2].'<br />',
4825
                            $option_details[1]
4826
                        );
4827
                    }
4828
                    $form->addGroup($group, 'extra_'.$field_details[1], $field_details[3]);
4829
                    if (!$admin_permissions) {
4830
                        if ($field_details[7] == 0) {
4831
                            $form->freeze('extra_'.$field_details[1]);
4832
                        }
4833
                    }
4834
                    break;
4835
                case ExtraField::FIELD_TYPE_SELECT:
4836
                    $get_lang_variables = false;
4837 View Code Duplication
                    if (in_array(
4838
                        $field_details[1],
4839
                        array(
4840
                            'mail_notify_message',
4841
                            'mail_notify_invitation',
4842
                            'mail_notify_group_message',
4843
                        )
4844
                    )) {
4845
                        $get_lang_variables = true;
4846
                    }
4847
                    $options = array();
4848
4849
                    foreach ($field_details[9] as $option_id => $option_details) {
4850
                        if ($get_lang_variables) {
4851
                            $options[$option_details[1]] = get_lang($option_details[2]);
4852
                        } else {
4853
                            $options[$option_details[1]] = $option_details[2];
4854
                        }
4855
                    }
4856
4857
                    if ($get_lang_variables) {
4858
                        $field_details[3] = get_lang($field_details[3]);
4859
                    }
4860
4861
                    $form->addElement(
4862
                        'select',
4863
                        'extra_'.$field_details[1],
4864
                        $field_details[3],
4865
                        $options,
4866
                        array('id' => 'extra_' . $field_details[1])
4867
                    );
4868
4869
                    if (!$admin_permissions) {
4870
                        if ($field_details[7] == 0)
4871
                            $form->freeze('extra_'.$field_details[1]);
4872
                    }
4873
                    break;
4874
                case ExtraField::FIELD_TYPE_SELECT_MULTIPLE:
4875
                    $options = array();
4876
                    foreach ($field_details[9] as $option_id => $option_details) {
4877
                        $options[$option_details[1]] = $option_details[2];
4878
                    }
4879
                    $form->addElement(
4880
                        'select',
4881
                        'extra_'.$field_details[1],
4882
                        $field_details[3],
4883
                        $options,
4884
                        array('multiple' => 'multiple')
4885
                    );
4886
                    if (!$admin_permissions) {
4887
                        if ($field_details[7] == 0)
4888
                            $form->freeze('extra_'.$field_details[1]);
4889
                    }
4890
                    break;
4891 View Code Duplication
                case ExtraField::FIELD_TYPE_DATE:
4892
                    $form->addDatePicker('extra_'.$field_details[1], $field_details[3]);
4893
                    $defaults['extra_'.$field_details[1]] = date('Y-m-d 12:00:00');
4894
                    $form->setDefaults($defaults);
4895
                    if (!$admin_permissions) {
4896
                        if ($field_details[7] == 0)
4897
                            $form->freeze('extra_'.$field_details[1]);
4898
                    }
4899
                    $form->applyFilter('theme', 'trim');
4900
                    break;
4901 View Code Duplication
                case ExtraField::FIELD_TYPE_DATETIME:
4902
                    $form->addDateTimePicker('extra_'.$field_details[1], $field_details[3]);
4903
                    $defaults['extra_'.$field_details[1]] = date('Y-m-d 12:00:00');
4904
                    $form->setDefaults($defaults);
4905
                    if (!$admin_permissions) {
4906
                        if ($field_details[7] == 0)
4907
                            $form->freeze('extra_'.$field_details[1]);
4908
                    }
4909
                    $form->applyFilter('theme', 'trim');
4910
                    break;
4911
                case ExtraField::FIELD_TYPE_DOUBLE_SELECT:
4912
                    foreach ($field_details[9] as $key => $element) {
4913
                        if ($element[2][0] == '*') {
4914
                            $values['*'][$element[0]] = str_replace('*', '', $element[2]);
4915
                        } else {
4916
                            $values[0][$element[0]] = $element[2];
4917
                        }
4918
                    }
4919
4920
                    $group = '';
4921
                    $group[] = $form->createElement('select', 'extra_'.$field_details[1], '', $values[0], '');
4922
                    $group[] = $form->createElement('select', 'extra_'.$field_details[1].'*', '', $values['*'], '');
4923
                    $form->addGroup($group, 'extra_'.$field_details[1], $field_details[3]);
4924
4925
                    if (!$admin_permissions) {
4926
                        if ($field_details[7] == 0)
4927
                            $form->freeze('extra_'.$field_details[1]);
4928
                    }
4929
4930
                    /* Recoding the selected values for double : if the user has
4931
                    selected certain values, we have to assign them to the
4932
                    correct select form */
4933
                    if (array_key_exists('extra_'.$field_details[1], $extra_data)) {
4934
                        // exploding all the selected values (of both select forms)
4935
                        $selected_values = explode(';', $extra_data['extra_'.$field_details[1]]);
4936
                        $extra_data['extra_'.$field_details[1]] = array();
4937
4938
                        // looping through the selected values and assigning the selected values to either the first or second select form
4939
                        foreach ($selected_values as $key => $selected_value) {
4940
                            if (array_key_exists($selected_value, $values[0])) {
4941
                                $extra_data['extra_'.$field_details[1]]['extra_'.$field_details[1]] = $selected_value;
4942
                            } else {
4943
                                $extra_data['extra_'.$field_details[1]]['extra_'.$field_details[1].'*'] = $selected_value;
4944
                            }
4945
                        }
4946
                    }
4947
                    break;
4948
                case ExtraField::FIELD_TYPE_DIVIDER:
4949
                    $form->addElement('static', $field_details[1], '<br /><strong>'.$field_details[3].'</strong>');
4950
                    break;
4951
                case ExtraField::FIELD_TYPE_TAG:
4952
                    //the magic should be here
4953
                    $user_tags = UserManager::get_user_tags($user_id, $field_details[0]);
4954
4955
                    $tag_list = '';
4956
                    if (is_array($user_tags) && count($user_tags) > 0) {
4957
                        foreach ($user_tags as $tag) {
4958
                            $tag_list .= '<option value="'.$tag['tag'].'" class="selected">'.$tag['tag'].'</option>';
4959
                        }
4960
                    }
4961
4962
                    $multi_select = '<select id="extra_'.$field_details[1].'" name="extra_'.$field_details[1].'">
4963
                                    '.$tag_list.'
4964
                                    </select>';
4965
4966
                    $form->addElement('label', $field_details[3], $multi_select);
4967
                    $url = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php';
4968
                    $complete_text = get_lang('StartToType');
4969
                    //if cache is set to true the jquery will be called 1 time
4970
                    $jquery_ready_content = <<<EOF
4971
                    $("#extra_$field_details[1]").fcbkcomplete({
4972
                        json_url: "$url?a=search_tags&field_id=$field_details[0]",
4973
                        cache: false,
4974
                        filter_case: true,
4975
                        filter_hide: true,
4976
                        complete_text:"$complete_text",
4977
                        firstselected: true,
4978
                        //onremove: "testme",
4979
                        //onselect: "testme",
4980
                        filter_selected: true,
4981
                        newel: true
4982
                    });
4983
EOF;
4984
                    break;
4985
                case ExtraField::FIELD_TYPE_TIMEZONE:
4986
                    $form->addElement('select', 'extra_'.$field_details[1], $field_details[3], api_get_timezones(), '');
4987
                    if ($field_details[7] == 0)
4988
                        $form->freeze('extra_'.$field_details[1]);
4989
                    break;
4990
                case ExtraField::FIELD_TYPE_SOCIAL_PROFILE:
4991
                    // get the social network's favicon
4992
                    $icon_path = UserManager::get_favicon_from_url($extra_data['extra_'.$field_details[1]], $field_details[4]);
4993
                    // special hack for hi5
4994
                    $leftpad = '1.7';
4995
                    $top = '0.4';
4996
                    $domain = parse_url($icon_path, PHP_URL_HOST);
4997
                    if ($domain == 'www.hi5.com' or $domain == 'hi5.com') {
4998
                        $leftpad = '3';
4999
                        $top = '0';
5000
                    }
5001
                    // print the input field
5002
                    $form->addElement(
5003
                        'text',
5004
                        'extra_'.$field_details[1],
5005
                        $field_details[3],
5006
                        array(
5007
                            'size' => 60,
5008
                            'style' => 'background-image: url(\''.$icon_path.'\'); background-repeat: no-repeat; background-position: 0.4em '.$top.'em; padding-left: '.$leftpad.'em; '
5009
                        )
5010
                    );
5011
                    $form->applyFilter('extra_'.$field_details[1], 'stripslashes');
5012
                    $form->applyFilter('extra_'.$field_details[1], 'trim');
5013
                    if ($field_details[7] == 0)
5014
                        $form->freeze('extra_'.$field_details[1]);
5015
                    break;
5016
                case ExtraField::FIELD_TYPE_FILE:
5017
                    $extra_field = 'extra_'.$field_details[1];
5018
                    $form->addElement('file', $extra_field, $field_details[3], null, '');
5019
                    if ($extra_file_list = UserManager::build_user_extra_file_list($user_id, $field_details[1], '', true)) {
5020
                        $form->addElement('static', $extra_field . '_list', null, $extra_file_list);
5021
                    }
5022
                    if ($field_details[7] == 0) {
5023
                        $form->freeze($extra_field);
5024
                    }
5025
                    break;
5026 View Code Duplication
                case ExtraField::FIELD_TYPE_MOBILE_PHONE_NUMBER:
5027
                    $form->addElement(
5028
                        'text',
5029
                        'extra_'.$field_details[1],
5030
                        $field_details[3]." (".get_lang('CountryDialCode').")",
5031
                        array('size' => 40, 'placeholder'  => '(xx)xxxxxxxxx')
5032
                    );
5033
                    $form->applyFilter('extra_'.$field_details[1], 'stripslashes');
5034
                    $form->applyFilter('extra_'.$field_details[1], 'trim');
5035
                    $form->applyFilter('extra_'.$field_details[1], 'mobile_phone_number_filter');
5036
                    $form->addRule(
5037
                        'extra_'.$field_details[1],
5038
                        get_lang('MobilePhoneNumberWrong'),
5039
                        'mobile_phone_number'
5040
                    );
5041
                    if (!$admin_permissions) {
5042
                        if ($field_details[7] == 0) {
5043
                            $form->freeze('extra_'.$field_details[1]);
5044
                        }
5045
                    }
5046
                    break;
5047
            }
5048
        }
5049
        $return = array();
5050
        $return['jquery_ready_content'] = $jquery_ready_content;
5051
        return $return;
5052
    }
5053
5054
    /**
5055
     * @return array
5056
     */
5057
    public static function get_user_field_types()
5058
    {
5059
        $types = array();
5060
        $types[self::USER_FIELD_TYPE_TEXT] = get_lang('FieldTypeText');
5061
        $types[self::USER_FIELD_TYPE_TEXTAREA] = get_lang('FieldTypeTextarea');
5062
        $types[self::USER_FIELD_TYPE_RADIO] = get_lang('FieldTypeRadio');
5063
        $types[self::USER_FIELD_TYPE_SELECT] = get_lang('FieldTypeSelect');
5064
        $types[self::USER_FIELD_TYPE_SELECT_MULTIPLE] = get_lang('FieldTypeSelectMultiple');
5065
        $types[self::USER_FIELD_TYPE_DATE] = get_lang('FieldTypeDate');
5066
        $types[self::USER_FIELD_TYPE_DATETIME] = get_lang('FieldTypeDatetime');
5067
        $types[self::USER_FIELD_TYPE_DOUBLE_SELECT] = get_lang('FieldTypeDoubleSelect');
5068
        $types[self::USER_FIELD_TYPE_DIVIDER] = get_lang('FieldTypeDivider');
5069
        $types[self::USER_FIELD_TYPE_TAG] = get_lang('FieldTypeTag');
5070
        $types[self::USER_FIELD_TYPE_TIMEZONE] = get_lang('FieldTypeTimezone');
5071
        $types[self::USER_FIELD_TYPE_SOCIAL_PROFILE] = get_lang('FieldTypeSocialProfile');
5072
        $types[self::USER_FIELD_TYPE_FILE] = get_lang('FieldTypeFile');
5073
        $types[self::USER_FIELD_TYPE_MOBILE_PHONE_NUMBER] = get_lang('FieldTypeMobilePhoneNumber');
5074
5075
        return $types;
5076
    }
5077
5078
    /**
5079
     * @param User $user
5080
     */
5081
    public static function add_user_as_admin(User $user)
5082
    {
5083
        $table_admin = Database :: get_main_table(TABLE_MAIN_ADMIN);
5084
        if ($user) {
5085
            $userId = $user->getId();
5086
5087
            if (!self::is_admin($userId)) {
5088
                $sql = "INSERT INTO $table_admin SET user_id = $userId";
5089
                Database::query($sql);
5090
            }
5091
5092
            $user->addRole('ROLE_SUPER_ADMIN');
5093
            self::getManager()->updateUser($user, true);
5094
        }
5095
    }
5096
5097
    /**
5098
     * @param int $userId
5099
     */
5100 View Code Duplication
    public static function remove_user_admin($userId)
5101
    {
5102
        $table_admin = Database :: get_main_table(TABLE_MAIN_ADMIN);
5103
        $userId = intval($userId);
5104
        if (self::is_admin($userId)) {
5105
            $sql = "DELETE FROM $table_admin WHERE user_id = $userId";
5106
            Database::query($sql);
5107
        }
5108
    }
5109
5110
    /**
5111
     * @param string $from
5112
     * @param string $to
5113
     */
5114
    public static function update_all_user_languages($from, $to)
5115
    {
5116
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
5117
        $from = Database::escape_string($from);
5118
        $to = Database::escape_string($to);
5119
5120
        if (!empty($to) && !empty($from)) {
5121
            $sql = "UPDATE $table_user SET language = '$to'
5122
                    WHERE language = '$from'";
5123
            Database::query($sql);
5124
        }
5125
    }
5126
5127
    /**
5128
     * Subscribe boss to students
5129
     *
5130
     * @param int $bossId The boss id
5131
     * @param array $usersId The users array
5132
     * @return int Affected rows
5133
     */
5134
    public static function subscribeBossToUsers($bossId, $usersId)
5135
    {
5136
        return self::subscribeUsersToUser($bossId, $usersId, USER_RELATION_TYPE_BOSS);
5137
    }
5138
5139
    /**
5140
     * Subscribe boss to students
5141
     *
5142
     * @param int $studentId
5143
     * @param array $bossList
5144
     * @return int Affected rows
5145
     */
5146
    public static function subscribeUserToBossList($studentId, $bossList)
5147
    {
5148
        if ($bossList) {
5149
            $studentId = (int) $studentId;
5150
            $userRelUserTable = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
5151
            $sql = "DELETE FROM $userRelUserTable 
5152
                    WHERE user_id = $studentId AND relation_type = ".USER_RELATION_TYPE_BOSS;
5153
            Database::query($sql);
5154
5155
            foreach ($bossList as $bossId) {
5156
                $bossId = (int) $bossId;
5157
                $sql = "INSERT IGNORE INTO $userRelUserTable (user_id, friend_user_id, relation_type)
5158
                        VALUES ($studentId, $bossId, ".USER_RELATION_TYPE_BOSS.")";
5159
5160
                Database::query($sql);
5161
            }
5162
        }
5163
    }
5164
5165
    /**
5166
     * Get users followed by student boss
5167
     * @param int $userId
5168
     * @param int $userStatus (STUDENT, COURSEMANAGER, etc)
5169
     * @param bool $getOnlyUserId
5170
     * @param bool $getSql
5171
     * @param bool $getCount
5172
     * @param int $from
5173
     * @param int $numberItems
5174
     * @param int $column
5175
     * @param string $direction
5176
     * @param int $active
5177
     * @param string $lastConnectionDate
5178
     * @return array     users
5179
     */
5180 View Code Duplication
    public static function getUsersFollowedByStudentBoss(
5181
        $userId,
5182
        $userStatus = 0,
5183
        $getOnlyUserId = false,
5184
        $getSql = false,
5185
        $getCount = false,
5186
        $from = null,
5187
        $numberItems = null,
5188
        $column = null,
5189
        $direction = null,
5190
        $active = null,
5191
        $lastConnectionDate = null
5192
    ){
5193
        return self::getUsersFollowedByUser(
5194
            $userId,
5195
            $userStatus,
5196
            $getOnlyUserId,
5197
            $getSql,
5198
            $getCount,
5199
            $from,
5200
            $numberItems,
5201
            $column,
5202
            $direction,
5203
            $active,
5204
            $lastConnectionDate,
5205
            STUDENT_BOSS
5206
        );
5207
    }
5208
5209
    /**
5210
     * Get the teacher (users with COURSEMANGER status) list
5211
     * @return array The list
5212
     */
5213
    public static function getTeachersList()
5214
    {
5215
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
5216
5217
        $resultData = Database::select('user_id, lastname, firstname, username', $userTable, array(
5218
            'where' => array(
5219
                'status = ?' => COURSEMANAGER
5220
            )
5221
        ));
5222
5223
        foreach ($resultData as &$teacherData) {
5224
            $teacherData['completeName'] = api_get_person_name($teacherData['firstname'], $teacherData['lastname']);
5225
        }
5226
5227
        return $resultData;
5228
    }
5229
5230
    /**
5231
     * @return array
5232
     */
5233 View Code Duplication
    public static function getOfficialCodeGrouped()
5234
    {
5235
        $user = Database::get_main_table(TABLE_MAIN_USER);
5236
        $sql = "SELECT DISTINCT official_code
5237
                FROM $user
5238
                GROUP BY official_code";
5239
        $result = Database::query($sql);
5240
5241
        $values = Database::store_result($result, 'ASSOC');
5242
5243
        $result = array();
5244
        foreach ($values as $value) {
5245
            $result[$value['official_code']] = $value['official_code'];
5246
        }
5247
        return $result;
5248
    }
5249
5250
    /**
5251
     * @param string $officialCode
5252
     * @return array
5253
     */
5254
    public static function getUsersByOfficialCode($officialCode)
5255
    {
5256
        $user = Database::get_main_table(TABLE_MAIN_USER);
5257
        $officialCode = Database::escape_string($officialCode);
5258
5259
        $sql = "SELECT DISTINCT id
5260
                FROM $user
5261
                WHERE official_code = '$officialCode'
5262
                ";
5263
        $result = Database::query($sql);
5264
5265
        $users = array();
5266
        while ($row = Database::fetch_array($result)) {
5267
            $users[] = $row['id'];
5268
        }
5269
        return $users;
5270
    }
5271
5272
    /**
5273
     * Calc the expended time (in seconds) by a user in a course
5274
     * @param int $userId The user id
5275
     * @param int $courseId The course id
5276
     * @param int $sessionId Optional. The session id
5277
     * @param string $from Optional. From date
5278
     * @param string $until Optional. Until date
5279
     * @return int The time
5280
     */
5281
    public static function getTimeSpentInCourses($userId, $courseId, $sessionId = 0, $from = '', $until = '')
5282
    {
5283
        $userId = intval($userId);
5284
        $sessionId = intval($sessionId);
5285
5286
        $trackCourseAccessTable = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5287
5288
        $whereConditions = array(
5289
            'user_id = ? ' => $userId,
5290
            'AND c_id = ? ' => $courseId,
5291
            'AND session_id = ? ' => $sessionId
5292
        );
5293
5294 View Code Duplication
        if (!empty($from) && !empty($until)) {
5295
            $whereConditions["AND (login_course_date >= '?' "] = $from;
5296
            $whereConditions["AND logout_course_date <= DATE_ADD('?', INTERVAL 1 DAY)) "] = $until;
5297
        }
5298
5299
        $trackResult = Database::select(
5300
            'SUM(UNIX_TIMESTAMP(logout_course_date) - UNIX_TIMESTAMP(login_course_date)) as total_time',
5301
            $trackCourseAccessTable,
5302
            array(
5303
                'where' => $whereConditions
5304
            ), 'first'
5305
        );
5306
5307
        if ($trackResult != false) {
5308
            return $trackResult['total_time'] ? $trackResult['total_time'] : 0;
5309
        }
5310
5311
        return 0;
5312
    }
5313
5314
    /**
5315
     * Get the boss user ID from a followed user id
5316
     * @param $userId
5317
     * @return bool
5318
     */
5319 View Code Duplication
    public static function getFirstStudentBoss($userId)
5320
    {
5321
        $userId = intval($userId);
5322
        if ($userId > 0) {
5323
            $userRelTable = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
5324
            $row = Database::select(
5325
                'DISTINCT friend_user_id AS boss_id',
5326
                $userRelTable,
5327
                array(
5328
                    'where' => array(
5329
                        'user_id = ? AND relation_type = ? LIMIT 1' => array(
5330
                            $userId,
5331
                            USER_RELATION_TYPE_BOSS,
5332
                        )
5333
                    )
5334
                )
5335
            );
5336
            if (!empty($row)) {
5337
5338
                return $row[0]['boss_id'];
5339
            }
5340
        }
5341
5342
        return false;
5343
    }
5344
5345
    /**
5346
     * Get the boss user ID from a followed user id
5347
     * @param $userId
5348
     * @return bool
5349
     */
5350 View Code Duplication
    public static function getStudentBossList($userId)
5351
    {
5352
        $userId = intval($userId);
5353
        if ($userId > 0) {
5354
            $userRelTable = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
5355
            $result = Database::select(
5356
                'DISTINCT friend_user_id AS boss_id',
5357
                $userRelTable,
5358
                array(
5359
                    'where' => array(
5360
                        'user_id = ? AND relation_type = ? ' => array(
5361
                            $userId,
5362
                            USER_RELATION_TYPE_BOSS,
5363
                        )
5364
                    )
5365
                ),
5366
                'all'
5367
            );
5368
5369
            return $result;
5370
        }
5371
5372
        return false;
5373
    }
5374
5375
    /**
5376
     * @param int $bossId
5377
     * @param int $studentId
5378
     *
5379
     * @return bool
5380
     */
5381
    public static function userIsBossOfStudent($bossId, $studentId)
5382
    {
5383
        $result = false;
5384
        $bossList = UserManager::getStudentBossList($studentId);
5385
        if ($bossList) {
5386
            $bossList = array_column($bossList, 'boss_id');
5387
            if (in_array($bossId, $bossList)) {
5388
                $result = true;
5389
            }
5390
        }
5391
5392
        return $result;
5393
    }
5394
5395
    /**
5396
     * Get either a Gravatar URL or complete image tag for a specified email address.
5397
     *
5398
     * @param string $email The email address
5399
     * @param string $s Size in pixels, defaults to 80px [ 1 - 2048 ]
5400
     * @param string $d Default imageset to use [ 404 | mm | identicon | monsterid | wavatar ]
5401
     * @param string $r Maximum rating (inclusive) [ g | pg | r | x ]
5402
     * @param boole $img True to return a complete IMG tag False for just the URL
5403
     * @param array $atts Optional, additional key/value attributes to include in the IMG tag
5404
     * @return String containing either just a URL or a complete image tag
5405
     * @source http://gravatar.com/site/implement/images/php/
5406
     */
5407
    private static function getGravatar(
5408
        $email,
5409
        $s = 80,
5410
        $d = 'mm',
5411
        $r = 'g',
5412
        $img = false,
5413
        $atts = array()
5414
    ) {
5415
        $url = 'http://www.gravatar.com/avatar/';
5416
        if (!empty($_SERVER['HTTPS'])) {
5417
            $url = 'https://secure.gravatar.com/avatar/';
5418
        }
5419
        $url .= md5( strtolower( trim( $email ) ) );
5420
        $url .= "?s=$s&d=$d&r=$r";
5421
        if ( $img ) {
5422
            $url = '<img src="' . $url . '"';
5423
            foreach ( $atts as $key => $val )
5424
                $url .= ' ' . $key . '="' . $val . '"';
5425
            $url .= ' />';
5426
        }
5427
        return $url;
5428
    }
5429
5430
    /**
5431
     * Displays the name of the user and makes the link to the user profile
5432
     * @param array $userInfo
5433
     *
5434
     * @return string
5435
     */
5436
    public static function getUserProfileLink($userInfo)
5437
    {
5438
        if (isset($userInfo) && isset($userInfo['user_id'])) {
5439
            return Display::url(
5440
                $userInfo['complete_name_with_username'],
5441
                $userInfo['profile_url']
5442
            );
5443
        } else {
5444
            return get_lang('Anonymous');
5445
        }
5446
    }
5447
5448
    /**
5449
     * Displays the name of the user and makes the link to the user profile
5450
     *
5451
     * @param $userInfo
5452
     *
5453
     * @return string
5454
     */
5455
    public static function getUserProfileLinkWithPicture($userInfo)
5456
    {
5457
        return Display::url(Display::img($userInfo['avatar']), $userInfo['profile_url']);
5458
    }
5459
5460
    /**
5461
     * Get users whose name matches $firstname and $lastname
5462
     * @param string $firstname Firstname to search
5463
     * @param string $lastname Lastname to search
5464
     * @return array The user list
5465
     */
5466 View Code Duplication
    public static function getUserByName($firstname, $lastname)
5467
    {
5468
        $firstname = Database::escape_string($firstname);
5469
        $lastname = Database::escape_string($lastname);
5470
5471
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
5472
5473
        $sql = <<<SQL
5474
            SELECT id, username, lastname, firstname
5475
            FROM $userTable
5476
            WHERE 
5477
                firstname LIKE '$firstname%' AND
5478
                lastname LIKE '$lastname%'
5479
SQL;
5480
5481
        $result = Database::query($sql);
5482
5483
        $users = [];
5484
        while ($resultData = Database::fetch_object($result)) {
5485
            $users[] = $resultData;
5486
        }
5487
5488
        return $users;
5489
    }
5490
5491
    /**
5492
     * @param int $optionSelected
5493
     * @return string
5494
     */
5495
    public static function getUserSubscriptionTab($optionSelected = 1)
5496
    {
5497
        $allowAdmin = api_get_setting('allow_user_course_subscription_by_course_admin');
5498
        if (($allowAdmin === 'true' && api_is_allowed_to_edit()) ||
5499
            api_is_platform_admin()
5500
        ) {
5501
            $userPath = api_get_path(WEB_CODE_PATH).'user/';
5502
5503
            $headers = [
5504
                [
5505
                    'url' => $userPath.'user.php?'.api_get_cidreq().'&type='.STUDENT,
5506
                    'content' => get_lang('Students'),
5507
                ],
5508
                [
5509
                    'url' => $userPath.'user.php?'.api_get_cidreq().'&type='.COURSEMANAGER,
5510
                    'content' => get_lang('Teachers'),
5511
                ],
5512
                /*[
5513
                    'url' => $userPath.'subscribe_user.php?'.api_get_cidreq(),
5514
                    'content' => get_lang('Students'),
5515
                ],
5516
                [
5517
                    'url' => $userPath.'subscribe_user.php?type=teacher&'.api_get_cidreq(),
5518
                    'content' => get_lang('Teachers'),
5519
                ],*/
5520
                [
5521
                    'url' => api_get_path(WEB_CODE_PATH).'group/group.php?'.api_get_cidreq(),
5522
                    'content' => get_lang('Groups'),
5523
                ],
5524
                [
5525
                    'url' => $userPath.'class.php?'.api_get_cidreq(),
5526
                    'content' => get_lang('Classes'),
5527
                ]
5528
            ];
5529
5530
            return Display::tabsOnlyLink($headers, $optionSelected);
5531
        }
5532
    }
5533
5534
5535
    /**
5536
     * @param int $user_id
5537
     * @return bool
5538
     */
5539 View Code Duplication
    public static function user_is_online($user_id)
5540
    {
5541
        $track_online_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE);
5542
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
5543
5544
        $access_url_id = api_get_current_access_url_id();
5545
        $time_limit = api_get_setting('display.time_limit_whosonline');
5546
5547
        $online_time = time() - $time_limit*60;
5548
        $limit_date = api_get_utc_datetime($online_time);
5549
        $user_id = intval($user_id);
5550
5551
        $query = " SELECT login_user_id,login_date
5552
               FROM $track_online_table track
5553
               INNER JOIN $table_user u ON (u.id=track.login_user_id)
5554
               WHERE
5555
                    track.access_url_id =  $access_url_id AND
5556
                    login_date >= '".$limit_date."'  AND
5557
                    u.id =  $user_id
5558
               LIMIT 1 ";
5559
5560
        $result = Database::query($query);
5561
        if (Database::num_rows($result)) {
5562
5563
            return true;
5564
        }
5565
5566
        return false;
5567
    }
5568
5569
    /**
5570
     * @param int $time_limit seconds
5571
     * @param bool $friends show friends (true) or all users (false)
5572
     * @return bool
5573
     */
5574
    public static function whoIsOnlineCount(
5575
        $time_limit = 0,
5576
        $friends = false
5577
    ) {
5578
        if (empty($time_limit)) {
5579
            $time_limit = api_get_setting('display.time_limit_whosonline');
5580
        } else {
5581
            $time_limit = intval($time_limit);
5582
        }
5583
        $track_online_table = Database::get_main_table(
5584
            TABLE_STATISTIC_TRACK_E_ONLINE
5585
        );
5586
        $friend_user_table = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
5587
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
5588
        $online_time = time() - $time_limit * 60;
5589
        $current_date = api_get_utc_datetime($online_time);
5590
5591
        if ($friends) {
5592
            // 	who friends from social network is online
5593
            $query = "SELECT DISTINCT count(login_user_id) as count
5594
				  FROM $track_online_table INNER JOIN $friend_user_table
5595
                  ON (friend_user_id = login_user_id)
5596
				  WHERE
5597
				        login_date >= '$current_date' AND
5598
				        friend_user_id <> '".api_get_user_id()."' AND
5599
				        relation_type='".USER_RELATION_TYPE_FRIEND."' AND
5600
				        user_id = '".api_get_user_id()."' ";
5601
        } else {
5602
            // All users online
5603
            $query = "SELECT count(login_id) as count
5604
                  FROM $track_online_table track INNER JOIN $table_user u
5605
                  ON (u.id=track.login_user_id)
5606
                  WHERE u.status != ".ANONYMOUS." AND login_date >= '$current_date'  ";
5607
        }
5608
5609
        if (api_get_multiple_access_url()) {
5610
            $access_url_id = api_get_current_access_url_id();
5611
            if ($access_url_id != -1) {
5612
                if ($friends) {
5613
                    // 	friends from social network is online
5614
                    $query = "SELECT DISTINCT count(login_user_id) as count
5615
							FROM $track_online_table track
5616
							INNER JOIN $friend_user_table ON (friend_user_id = login_user_id)
5617
							WHERE
5618
							    track.access_url_id = $access_url_id AND
5619
							    login_date >= '".$current_date."' AND
5620
							    friend_user_id <> '".api_get_user_id()."' AND
5621
							    relation_type='".USER_RELATION_TYPE_FRIEND."'  ";
5622
                } else {
5623
                    // all users online
5624
                    $query = "SELECT count(login_id) as count FROM $track_online_table  track
5625
                          INNER JOIN $table_user u ON (u.id=track.login_user_id)
5626
						  WHERE
5627
						    u.status != ".ANONYMOUS." AND
5628
						    track.access_url_id =  $access_url_id AND
5629
						    login_date >= '$current_date' ";
5630
                }
5631
            }
5632
        }
5633
5634
        // Dev purposes show all users online
5635
        /*$table_user = Database::get_main_table(TABLE_MAIN_USER);
5636
        $query = "SELECT count(*)  as count FROM ".$table_user;*/
5637
5638
        $result = Database::query($query);
5639
        if (Database::num_rows($result) > 0) {
5640
            $row = Database::fetch_array($result);
5641
5642
            return $row['count'];
5643
        } else {
5644
            return false;
5645
        }
5646
    }
5647
5648
    /**
5649
     * Gives a list of people online now (and in the last $valid minutes)
5650
     *
5651
     * @param int $from
5652
     * @param int $number_of_items
5653
     * @param string $column
5654
     * @param string $direction
5655
     * @param int $time_limit in seconds
5656
     * @param bool $friends show friends (true) or all users (false)
5657
     * @return array|bool
5658
     */
5659
    public static function whoIsOnline(
5660
        $from,
5661
        $number_of_items,
5662
        $column = '',
5663
        $direction = '',
5664
        $time_limit = 0,
5665
        $friends = false
5666
    ) {
5667
        // Time limit in seconds?
5668
        if (empty($time_limit)) {
5669
            $time_limit = api_get_setting('display.time_limit_whosonline');
5670
        } else {
5671
            $time_limit = intval($time_limit);
5672
        }
5673
5674
        $from = intval($from);
5675
        $number_of_items = intval($number_of_items);
5676
5677
        if (empty($column)) {
5678
            $column = 'picture_uri';
5679
            if ($friends) {
5680
                $column = 'login_date';
5681
            }
5682
        }
5683
5684
        if (empty($direction)) {
5685
            $direction = 'DESC';
5686
        } else {
5687
            if (!in_array(strtolower($direction), array('asc', 'desc'))) {
5688
                $direction = 'DESC';
5689
            }
5690
        }
5691
5692
        $online_time = time() - $time_limit * 60;
5693
        $current_date = api_get_utc_datetime($online_time);
5694
        $track_online_table = Database::get_main_table(
5695
            TABLE_STATISTIC_TRACK_E_ONLINE
5696
        );
5697
        $friend_user_table = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
5698
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
5699
5700
        if ($friends) {
5701
            // 	who friends from social network is online
5702
            $query = "SELECT DISTINCT login_user_id, login_date
5703
				  FROM $track_online_table INNER JOIN $friend_user_table
5704
				  ON (friend_user_id = login_user_id)
5705
				  WHERE
5706
				    login_date >= '".$current_date."' AND
5707
                    friend_user_id <> '".api_get_user_id()."' AND
5708
                    relation_type='".USER_RELATION_TYPE_FRIEND."' AND
5709
                    user_id = '".api_get_user_id()."'
5710
                  ORDER BY $column $direction
5711
                  LIMIT $from, $number_of_items";
5712
        } else {
5713
            $query = "SELECT DISTINCT login_user_id, login_date
5714
                    FROM ".$track_online_table." e
5715
		            INNER JOIN ".$table_user." u ON (u.id = e.login_user_id)
5716
                  WHERE u.status != ".ANONYMOUS." AND login_date >= '".$current_date."'
5717
                  ORDER BY $column $direction
5718
                  LIMIT $from, $number_of_items";
5719
        }
5720
5721
        if (api_get_multiple_access_url()) {
5722
            $access_url_id = api_get_current_access_url_id();
5723
            if ($access_url_id != -1) {
5724
                if ($friends) {
5725
                    // 	friends from social network is online
5726
                    $query = "SELECT distinct login_user_id, login_date
5727
							FROM $track_online_table track INNER JOIN $friend_user_table
5728
							ON (friend_user_id = login_user_id)
5729
							WHERE   track.access_url_id =  $access_url_id AND
5730
                                    login_date >= '".$current_date."' AND
5731
                                    friend_user_id <> '".api_get_user_id()."' AND
5732
                                    relation_type='".USER_RELATION_TYPE_FRIEND."'
5733
                            ORDER BY $column $direction
5734
                            LIMIT $from, $number_of_items";
5735
                } else {
5736
                    // all users online
5737
                    $query = "SELECT login_user_id, login_date
5738
						  FROM ".$track_online_table." track
5739
                          INNER JOIN ".$table_user." u
5740
                          ON (u.id=track.login_user_id)
5741
						  WHERE u.status != ".ANONYMOUS." AND track.access_url_id =  $access_url_id AND
5742
                                login_date >= '".$current_date."'
5743
                          ORDER BY $column $direction
5744
                          LIMIT $from, $number_of_items";
5745
                }
5746
            }
5747
        }
5748
5749
        //This query will show all registered users. Only for dev purposes.
5750
        /*$query = "SELECT DISTINCT u.id as login_user_id, login_date FROM ".$track_online_table ."  e , $table_user u
5751
                GROUP by u.id
5752
                ORDER BY $column $direction
5753
                LIMIT $from, $number_of_items";*/
5754
5755
        $result = Database::query($query);
5756
        if ($result) {
5757
            $users_online = array();
5758
            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...
5759
                $users_online[] = $login_user_id;
5760
            }
5761
5762
            return $users_online;
5763
        } else {
5764
            return false;
5765
        }
5766
    }
5767
5768
    /**
5769
     * @param int $user_id
5770
     * @param bool $is_time_over
5771
     * @param bool $get_count
5772
     * @param bool $reverse_order
5773
     * @param int $start
5774
     * @param null $maxPerPage
5775
     * @param null $categoryFilter
5776
     * @return array
5777
     */
5778
    public static function getCategories(
5779
        $user_id,
5780
        $is_time_over = false,
5781
        $get_count = false,
5782
        $reverse_order = false,
5783
        $start = 0,
5784
        $maxPerPage = null,
5785
        $categoryFilter = null
5786
    ) {
5787
        $tableSessionCategory = Database:: get_main_table(
5788
            TABLE_MAIN_SESSION_CATEGORY
5789
        );
5790
        $tableSession = Database:: get_main_table(TABLE_MAIN_SESSION);
5791
        $tableSessionUser = Database:: get_main_table(TABLE_MAIN_SESSION_USER);
5792
        $tableSessionCourseUser = Database:: get_main_table(
5793
            TABLE_MAIN_SESSION_COURSE_USER
5794
        );
5795
5796
        $select = " DISTINCT sc.id, sc.name  ";
5797
        if ($get_count) {
5798
            $select = " COUNT(DISTINCT(sc.id)) as total";
5799
        }
5800
5801
        $sql = "SELECT $select
5802
                FROM $tableSessionCategory sc
5803
                INNER JOIN $tableSession s ON (sc.id = s.session_category_id)
5804
                INNER JOIN (
5805
                    (
5806
                        SELECT DISTINCT session_id as sessionID FROM $tableSessionUser
5807
                        WHERE user_id = $user_id AND relation_type <> ".SESSION_RELATION_TYPE_RRHH."
5808
                    )
5809
                    UNION
5810
                    (
5811
                        SELECT DISTINCT s.id
5812
                        FROM $tableSession s
5813
                        WHERE (id_coach = $user_id)
5814
                    )
5815
                    UNION
5816
                    (
5817
                        SELECT DISTINCT s.id
5818
                        FROM $tableSessionUser su INNER JOIN $tableSession s
5819
                        ON (su.session_id = s.id)
5820
                        INNER JOIN $tableSessionCourseUser scu
5821
                        ON (scu.session_id = s.id)
5822
                        WHERE (scu.user_id = $user_id)
5823
                    )
5824
                ) as t ON (t.sessionId = sc.id)
5825
        ";
5826
5827
        if ($get_count) {
5828
            $result = Database::query($sql);
5829
            $row = Database::fetch_array($result);
5830
5831
            return $row['total'];
5832
        }
5833
5834
        $order = ' ORDER BY sc.name';
5835
        if ($reverse_order) {
5836
            $order = ' ORDER BY sc.name DESC ';
5837
        }
5838
5839
        $sql .= $order;
5840
5841 View Code Duplication
        if (isset($start) && isset($maxPerPage)) {
5842
            $start = intval($start);
5843
            $maxPerPage = intval($maxPerPage);
5844
            $limitCondition = " LIMIT $start, $maxPerPage";
5845
            $sql .= $limitCondition;
5846
        }
5847
5848
        $result = Database::query($sql);
5849
        $sessionsCategories = array();
5850
        if (Database::num_rows($result)) {
5851
            while ($sessionCategory = Database::fetch_array($result, 'ASSOC')) {
5852
                $sessions = self::get_sessions_by_category(
5853
                    $user_id,
5854
                    $is_time_over,
5855
                    false,
5856
                    $reverse_order,
5857
                    null,
5858
                    null,
5859
                    $sessionCategory['id']
5860
                );
5861
                $sessionsCategories[$sessionCategory['id']] = $sessions[$sessionCategory['id']];
5862
            }
5863
        }
5864
5865
        return $sessionsCategories;
5866
    }
5867
5868
5869
}
5870