Completed
Push — master ( 8d952e...5631ee )
by Julito
34:03
created

UserManager::getUserPicturePathById()   C

Complexity

Conditions 8
Paths 15

Size

Total Lines 51
Code Lines 33

Duplication

Lines 51
Ratio 100 %

Importance

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

How to fix   Long Method   

Long Method

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

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

Commonly applied refactorings include:

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

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

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

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

// Bar.php
namespace OtherDir;

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

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

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

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

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
6
use 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
    /** Get extra user data by value
2495
     * @param string $variable the internal variable name of the field
2496
     * @param string $value the internal value of the field
2497
     * @param bool $all_visibility
2498
     *
2499
     * @return array with extra data info of a user i.e array('field_variable'=>'value');
2500
     */
2501
     public static function get_extra_user_data_by_value($variable, $value, $all_visibility = true)
2502
    {
2503
        $extraFieldValue = new ExtraFieldValue('user');
2504
        $extraField = new ExtraField('user');
2505
2506
        $info = $extraField->get_handler_field_info_by_field_variable($variable);
2507
2508
        if (false === $info) {
2509
            return [];
2510
        }
2511
2512
        $data = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
2513
            $variable,
2514
            $value,
2515
            false,
2516
            false,
2517
            true
2518
        );
2519
2520
        $result = [];
2521
        if (!empty($data)) {
2522
            foreach ($data as $item) {
2523
                $result[] = $item['item_id'];
2524
            }
2525
        }
2526
2527
        return $result;
2528
    }
2529
2530
    /**
2531
     * Get extra user data by tags value
2532
     *
2533
     * @param int $fieldId the ID of the field we want to know everything of
2534
     * @param string $tag the tag name for search
2535
     * @return array with extra data info of a user
2536
     * @author José Loguercio
2537
     * @since v1.11.0
2538
     */
2539
    public static function get_extra_user_data_by_tags($fieldId, $tag)
2540
    {
2541
        $extraField = new ExtraField('user');
2542
        $result = $extraField->getAllUserPerTag($fieldId, $tag);
2543
        $array = [];
2544
        foreach ($result as $index => $user) {
2545
            $array[] = $user['user_id'];
2546
        }
2547
        return $array;
2548
    }
2549
2550
    /**
2551
     * Get extra user data by field variable
2552
     * @param string    field variable
2553
     * @return array    data
2554
     */
2555
    public static function get_extra_user_data_by_field_variable($field_variable)
2556
    {
2557
        $extra_information_by_variable = self::get_extra_field_information_by_name($field_variable);
2558
        $field_id = intval($extra_information_by_variable['id']);
2559
2560
        $extraField = new ExtraFieldValue('user');
2561
        $data = $extraField->getValuesByFieldId($field_id);
2562
2563
        if (!empty($data) > 0) {
2564
            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...
2565
                $user_id = $row['item_id'];
2566
                $data[$user_id] = $row;
2567
            }
2568
        }
2569
2570
        return $data;
2571
    }
2572
2573
    /**
2574
     * Get extra user data tags by field variable
2575
     *
2576
     * @param string    field variable
2577
     * @return array    data
2578
     */
2579
    public static function get_extra_user_data_for_tags($field_variable)
2580
    {
2581
        $extra_information_by_variable = self::get_extra_field_tags_information_by_name($field_variable);
2582
2583
        return $extra_information_by_variable;
2584
    }
2585
2586
    /**
2587
     * Gives a list of [session_category][session_id] for the current user.
2588
     * @param integer $user_id
2589
     * @param boolean whether to fill the first element or not (to give space for courses out of categories)
2590
     * @param boolean  optional true if limit time from session is over, false otherwise
2591
     * @param boolean $ignoreTimeLimit ignore time start/end
2592
     * @return array  list of statuses [session_category][session_id]
2593
     *
2594
     * @todo ensure multiple access urls are managed correctly
2595
     */
2596
    public static function get_sessions_by_category(
2597
        $user_id,
2598
        $is_time_over = true,
2599
        $ignore_visibility_for_admins = false,
2600
        $ignoreTimeLimit = false
2601
    ) {
2602
        if ($user_id != strval(intval($user_id))) {
2603
            return array();
2604
        }
2605
2606
        // Get the list of sessions per user
2607
        $now = new DateTime('now', new DateTimeZone('UTC'));
2608
2609
        $dql = "SELECT DISTINCT
2610
                    s.id,
2611
                    s.name,
2612
                    s.accessStartDate AS access_start_date,
2613
                    s.accessEndDate AS access_end_date,
2614
                    sc.id AS session_category_id,
2615
                    sc.name AS session_category_name,
2616
                    sc.dateStart AS session_category_date_start,
2617
                    sc.dateEnd AS session_category_date_end,
2618
                    s.coachAccessStartDate AS coach_access_start_date,
2619
                    s.coachAccessEndDate AS coach_access_end_date
2620
                FROM ChamiloCoreBundle:Session AS s
2621
                LEFT JOIN ChamiloCoreBundle:SessionCategory AS sc WITH s.category = sc
2622
                LEFT JOIN ChamiloCoreBundle:SessionRelCourseRelUser AS scu WITH scu.session = s
2623
                WHERE scu.user = :user OR s.generalCoach = :user
2624
                ORDER BY sc.name, s.name";
2625
2626
        $dql = Database::getManager()
2627
            ->createQuery($dql)
2628
            ->setParameters(['user' => $user_id])
2629
        ;
2630
2631
        $sessionData = $dql->getResult();
2632
        $categories = [];
2633
2634
        foreach ($sessionData as $row) {
2635
            // User portal filters:
2636
            if ($ignoreTimeLimit === false) {
2637
                if ($is_time_over) {
2638
                    // History
2639
                    if (empty($row['access_end_date'])) {
2640
                        continue;
2641
                    }
2642
2643
                    if (!empty($row['access_end_date'])) {
2644
                        if ($row['access_end_date'] > $now) {
2645
                            continue;
2646
                        }
2647
2648
                    }
2649
                } else {
2650
                    // Current user portal
2651
                    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...
2652
                        // Teachers can access the session depending in the access_coach date
2653
                    } else {
2654
                        if (isset($row['access_end_date']) &&
2655
                            !empty($row['access_end_date'])
2656
                        ) {
2657
                            if ($row['access_end_date'] <= $now) {
2658
                                continue;
2659
                            }
2660
                        }
2661
                    }
2662
                }
2663
            }
2664
2665
            $categories[$row['session_category_id']]['session_category'] = array(
2666
                'id' => $row['session_category_id'],
2667
                'name' => $row['session_category_name'],
2668
                'date_start' => $row['session_category_date_start'] ? $row['session_category_date_start']->format('Y-m-d H:i:s') : null,
2669
                'date_end' => $row['session_category_date_end'] ? $row['session_category_date_end']->format('Y-m-d H:i:s') : null
2670
            );
2671
2672
            $session_id = $row['id'];
2673
            $courseList = UserManager::get_courses_list_by_session(
2674
                $user_id,
2675
                $session_id
2676
            );
2677
2678
            $visibility = api_get_session_visibility(
2679
                $session_id,
2680
                null,
2681
                $ignore_visibility_for_admins
2682
            );
2683
2684 View Code Duplication
            if ($visibility != SESSION_VISIBLE) {
2685
                // Course Coach session visibility.
2686
                $blockedCourseCount = 0;
2687
                $closedVisibilityList = array(
2688
                    COURSE_VISIBILITY_CLOSED,
2689
                    COURSE_VISIBILITY_HIDDEN
2690
                );
2691
2692
                foreach ($courseList as $course) {
2693
                    // Checking session visibility
2694
                    $sessionCourseVisibility = api_get_session_visibility(
2695
                        $session_id,
2696
                        $course['real_id'],
2697
                        $ignore_visibility_for_admins
2698
                    );
2699
2700
                    $courseIsVisible = !in_array(
2701
                        $course['visibility'],
2702
                        $closedVisibilityList
2703
                    );
2704
                    if ($courseIsVisible === false || $sessionCourseVisibility == SESSION_INVISIBLE) {
2705
                        $blockedCourseCount++;
2706
                    }
2707
                }
2708
2709
                // If all courses are blocked then no show in the list.
2710
                if ($blockedCourseCount === count($courseList)) {
2711
                    $visibility = SESSION_INVISIBLE;
2712
                } else {
2713
                    $visibility = SESSION_VISIBLE;
2714
                }
2715
            }
2716
2717
            switch ($visibility) {
2718
                case SESSION_VISIBLE_READ_ONLY:
2719
                case SESSION_VISIBLE:
2720
                case SESSION_AVAILABLE:
2721
                    break;
2722
                case SESSION_INVISIBLE:
2723
                    if ($ignore_visibility_for_admins === false) {
2724
                        continue 2;
2725
                    }
2726
            }
2727
2728
            $categories[$row['session_category_id']]['sessions'][$row['id']] = array(
2729
                'session_name' => $row['name'],
2730
                'session_id' => $row['id'],
2731
                'access_start_date' => $row['access_start_date'] ? $row['access_start_date']->format('Y-m-d H:i:s') : null,
2732
                'access_end_date' => $row['access_end_date'] ? $row['access_end_date']->format('Y-m-d H:i:s') : null,
2733
                'coach_access_start_date' => $row['coach_access_start_date'] ? $row['coach_access_start_date']->format('Y-m-d H:i:s') : null,
2734
                'coach_access_end_date' => $row['coach_access_end_date'] ? $row['coach_access_end_date']->format('Y-m-d H:i:s') : null,
2735
                'courses' => $courseList
2736
            );
2737
        }
2738
2739
        return $categories;
2740
    }
2741
2742
    /**
2743
     * Gives a list of [session_id-course_code] => [status] for the current user.
2744
     * @param integer $user_id
2745
     * @param int $sessionLimit
2746
     * @return array  list of statuses (session_id-course_code => status)
2747
     */
2748
    public static function get_personal_session_course_list($user_id, $sessionLimit = null)
2749
    {
2750
        // Database Table Definitions
2751
        $tbl_course = Database :: get_main_table(TABLE_MAIN_COURSE);
2752
        $tbl_user = Database :: get_main_table(TABLE_MAIN_USER);
2753
        $tbl_session = Database :: get_main_table(TABLE_MAIN_SESSION);
2754
        $tbl_session_user = Database :: get_main_table(TABLE_MAIN_SESSION_USER);
2755
        $tbl_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
2756
        $tbl_session_course_user = Database :: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2757
2758
        if ($user_id != strval(intval($user_id))) {
2759
            return array();
2760
        }
2761
2762
        // We filter the courses from the URL
2763
        $join_access_url = $where_access_url = '';
2764
2765 View Code Duplication
        if (api_get_multiple_access_url()) {
2766
            $access_url_id = api_get_current_access_url_id();
2767
            if ($access_url_id != -1) {
2768
                $tbl_url_course = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2769
                $join_access_url = "LEFT JOIN $tbl_url_course url_rel_course ON url_rel_course.c_id = course.id";
2770
                $where_access_url = " AND access_url_id = $access_url_id ";
2771
            }
2772
        }
2773
2774
        // Courses in which we subscribed out of any session
2775
        $tbl_user_course_category = Database :: get_main_table(TABLE_USER_COURSE_CATEGORY);
2776
2777
        $sql = "SELECT
2778
                    course.code,
2779
                    course_rel_user.status course_rel_status,
2780
                    course_rel_user.sort sort,
2781
                    course_rel_user.user_course_cat user_course_cat
2782
                 FROM $tbl_course_user course_rel_user
2783
                 LEFT JOIN $tbl_course course
2784
                 ON course.id = course_rel_user.c_id
2785
                 LEFT JOIN $tbl_user_course_category user_course_category
2786
                 ON course_rel_user.user_course_cat = user_course_category.id
2787
                 $join_access_url
2788
                 WHERE
2789
                    course_rel_user.user_id = '".$user_id."' AND
2790
                    course_rel_user.relation_type <> ".COURSE_RELATION_TYPE_RRHH."
2791
                    $where_access_url
2792
                 ORDER BY user_course_category.sort, course_rel_user.sort, course.title ASC";
2793
2794
        $course_list_sql_result = Database::query($sql);
2795
2796
        $personal_course_list = array();
2797
        if (Database::num_rows($course_list_sql_result) > 0) {
2798
            while ($result_row = Database::fetch_array($course_list_sql_result, 'ASSOC')) {
2799
                $course_info = api_get_course_info($result_row['code']);
2800
                $result_row['course_info'] = $course_info;
2801
                $personal_course_list[] = $result_row;
2802
            }
2803
        }
2804
2805
        $coachCourseConditions = null;
2806
2807
        // Getting sessions that are related to a coach in the session_rel_course_rel_user table
2808
2809
        if (api_is_allowed_to_create_course()) {
2810
            $sessionListFromCourseCoach = array();
2811
            $sql =" SELECT DISTINCT session_id
2812
                    FROM $tbl_session_course_user
2813
                    WHERE user_id = $user_id AND status = 2 ";
2814
2815
            $result = Database::query($sql);
2816
            if (Database::num_rows($result)) {
2817
                $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...
2818
                foreach ($result as $session) {
2819
                    $sessionListFromCourseCoach[]= $session['session_id'];
2820
                }
2821
            }
2822
            if (!empty($sessionListFromCourseCoach)) {
2823
                $condition = implode("','", $sessionListFromCourseCoach);
2824
                $coachCourseConditions = " OR ( s.id IN ('$condition'))";
2825
            }
2826
        }
2827
2828
        // Get the list of sessions where the user is subscribed
2829
        // This is divided into two different queries
2830
        $sessions = array();
2831
2832
        $sessionLimitRestriction = '';
2833
        if (!empty($sessionLimit)) {
2834
            $sessionLimit = (int) $sessionLimit;
2835
            $sessionLimitRestriction = "LIMIT $sessionLimit";
2836
        }
2837
2838
        $sql = "SELECT DISTINCT s.id, name, access_start_date, access_end_date
2839
                FROM $tbl_session_user su INNER JOIN $tbl_session s
2840
                ON (s.id = su.session_id)
2841
                WHERE (
2842
                    su.user_id = $user_id AND
2843
                    su.relation_type <> ".SESSION_RELATION_TYPE_RRHH."
2844
                )
2845
                $coachCourseConditions
2846
                ORDER BY access_start_date, access_end_date, name
2847
                $sessionLimitRestriction
2848
        ";
2849
2850
        $result = Database::query($sql);
2851
        if (Database::num_rows($result)>0) {
2852
            while ($row = Database::fetch_assoc($result)) {
2853
                $sessions[$row['id']] = $row;
2854
            }
2855
        }
2856
2857
        $sql = "SELECT DISTINCT
2858
                id, name, access_start_date, access_end_date
2859
                FROM $tbl_session s
2860
                WHERE (
2861
                    id_coach = $user_id
2862
                )
2863
                $coachCourseConditions
2864
                ORDER BY access_start_date, access_end_date, name";
2865
2866
        $result = Database::query($sql);
2867
        if (Database::num_rows($result)>0) {
2868
            while ($row = Database::fetch_assoc($result)) {
2869
                if (empty($sessions[$row['id']])) {
2870
                    $sessions[$row['id']] = $row;
2871
                }
2872
            }
2873
        }
2874
2875
        if (api_is_allowed_to_create_course()) {
2876
            foreach ($sessions as $enreg) {
2877
                $session_id = $enreg['id'];
2878
                $session_visibility = api_get_session_visibility($session_id);
2879
2880
                if ($session_visibility == SESSION_INVISIBLE) {
2881
                    continue;
2882
                }
2883
2884
                // This query is horribly slow when more than a few thousand
2885
                // users and just a few sessions to which they are subscribed
2886
                $sql = "SELECT DISTINCT
2887
                        course.code code,
2888
                        course.title i,
2889
                        ".(api_is_western_name_order() ? "CONCAT(user.firstname,' ',user.lastname)" : "CONCAT(user.lastname,' ',user.firstname)")." t,
2890
                        email, course.course_language l,
2891
                        1 sort,
2892
                        category_code user_course_cat,
2893
                        access_start_date,
2894
                        access_end_date,
2895
                        session.id as session_id,
2896
                        session.name as session_name
2897
                    FROM $tbl_session_course_user as session_course_user
2898
                        INNER JOIN $tbl_course AS course
2899
                            ON course.id = session_course_user.c_id
2900
                        INNER JOIN $tbl_session as session
2901
                            ON session.id = session_course_user.session_id
2902
                        LEFT JOIN $tbl_user as user
2903
                            ON user.id = session_course_user.user_id OR session.id_coach = user.id
2904
                    WHERE
2905
                        session_course_user.session_id = $session_id AND (
2906
                            (session_course_user.user_id = $user_id AND session_course_user.status = 2)
2907
                            OR session.id_coach = $user_id
2908
                        )
2909
                    ORDER BY i";
2910
                $course_list_sql_result = Database::query($sql);
2911 View Code Duplication
                while ($result_row = Database::fetch_array($course_list_sql_result, 'ASSOC')) {
2912
                    $result_row['course_info'] = api_get_course_info($result_row['code']);
2913
                    $key = $result_row['session_id'].' - '.$result_row['code'];
2914
                    $personal_course_list[$key] = $result_row;
2915
                }
2916
            }
2917
        }
2918
2919
        foreach ($sessions as $enreg) {
2920
            $session_id = $enreg['id'];
2921
            $session_visibility = api_get_session_visibility($session_id);
2922
            if ($session_visibility == SESSION_INVISIBLE) {
2923
                continue;
2924
            }
2925
2926
            /* This query is very similar to the above query,
2927
               but it will check the session_rel_course_user table if there are courses registered to our user or not */
2928
            $sql = "SELECT DISTINCT
2929
                course.code code,
2930
                course.title i, CONCAT(user.lastname,' ',user.firstname) t,
2931
                email,
2932
                course.course_language l,
2933
                1 sort,
2934
                category_code user_course_cat,
2935
                access_start_date,
2936
                access_end_date,
2937
                session.id as session_id,
2938
                session.name as session_name,
2939
                IF((session_course_user.user_id = 3 AND session_course_user.status=2),'2', '5')
2940
            FROM $tbl_session_course_user as session_course_user
2941
            INNER JOIN $tbl_course AS course
2942
            ON course.id = session_course_user.c_id AND session_course_user.session_id = $session_id
2943
            INNER JOIN $tbl_session as session 
2944
            ON session_course_user.session_id = session.id
2945
            LEFT JOIN $tbl_user as user ON user.id = session_course_user.user_id
2946
            WHERE session_course_user.user_id = $user_id
2947
            ORDER BY i";
2948
2949
            $course_list_sql_result = Database::query($sql);
2950 View Code Duplication
            while ($result_row = Database::fetch_array($course_list_sql_result, 'ASSOC')) {
2951
                $result_row['course_info'] = api_get_course_info($result_row['code']);
2952
                $key = $result_row['session_id'].' - '.$result_row['code'];
2953
                if (!isset($personal_course_list[$key])) {
2954
                    $personal_course_list[$key] = $result_row;
2955
                }
2956
            }
2957
        }
2958
2959
        return $personal_course_list;
2960
    }
2961
2962
    /**
2963
     * Gives a list of courses for the given user in the given session
2964
     * @param integer $user_id
2965
     * @param integer $session_id
2966
     * @return array  list of statuses (session_id-course_code => status)
2967
     */
2968
    public static function get_courses_list_by_session($user_id, $session_id)
2969
    {
2970
        // Database Table Definitions
2971
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2972
        $tableCourse = Database::get_main_table(TABLE_MAIN_COURSE);
2973
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2974
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2975
2976
        $user_id = intval($user_id);
2977
        $session_id = intval($session_id);
2978
        //we filter the courses from the URL
2979
        $join_access_url = $where_access_url = '';
2980
2981 View Code Duplication
        if (api_get_multiple_access_url()) {
2982
            $urlId = api_get_current_access_url_id();
2983
            if ($urlId != -1) {
2984
                $tbl_url_session = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
2985
                $join_access_url = " ,  $tbl_url_session url_rel_session ";
2986
                $where_access_url = " AND access_url_id = $urlId AND url_rel_session.session_id = $session_id ";
2987
            }
2988
        }
2989
2990
        /* This query is very similar to the query below, but it will check the
2991
        session_rel_course_user table if there are courses registered
2992
        to our user or not */
2993
2994
        $sql = "SELECT DISTINCT
2995
                    c.visibility,
2996
                    c.id as real_id,                    
2997
                    sc.position
2998
                FROM $tbl_session_course_user as scu
2999
                INNER JOIN $tbl_session_course sc
3000
                ON (scu.session_id = sc.session_id AND scu.c_id = sc.c_id)
3001
                INNER JOIN $tableCourse as c
3002
                ON (scu.c_id = c.id)
3003
                $join_access_url
3004
                WHERE
3005
                    scu.user_id = $user_id AND
3006
                    scu.session_id = $session_id
3007
                    $where_access_url
3008
                ORDER BY sc.position ASC";
3009
3010
        $personal_course_list = array();
3011
        $courses = array();
3012
3013
        $result = Database::query($sql);
3014 View Code Duplication
        if (Database::num_rows($result) > 0) {
3015
            while ($result_row = Database::fetch_array($result, 'ASSOC')) {
3016
                $result_row['status'] = 5;
3017
                if (!in_array($result_row['real_id'], $courses)) {
3018
                    $personal_course_list[] = $result_row;
3019
                    $courses[] = $result_row['real_id'];
3020
                }
3021
            }
3022
        }
3023
3024
        if (api_is_allowed_to_create_course()) {
3025
            $sql = "SELECT DISTINCT
3026
                        c.visibility, 
3027
                        c.id as real_id,
3028
                        sc.position
3029
                    FROM $tbl_session_course_user as scu
3030
                    INNER JOIN $tbl_session as s
3031
                    ON (scu.session_id = s.id)
3032
                    INNER JOIN $tbl_session_course sc
3033
                    ON (scu.session_id = sc.session_id AND scu.c_id = sc.c_id)
3034
                    INNER JOIN $tableCourse as c
3035
                    ON (scu.c_id = c.id)
3036
                    $join_access_url
3037
                    WHERE
3038
                      s.id = $session_id AND
3039
                      (
3040
                        (scu.user_id = $user_id AND scu.status=2) OR
3041
                        s.id_coach = $user_id
3042
                      )
3043
                    $where_access_url
3044
                    ORDER BY sc.position ASC";
3045
            $result = Database::query($sql);
3046
3047 View Code Duplication
            if (Database::num_rows($result) > 0) {
3048
                while ($result_row = Database::fetch_array($result, 'ASSOC')) {
3049
                    $result_row['status'] = 2;
3050
                    if (!in_array($result_row['real_id'], $courses)) {
3051
                        $personal_course_list[] = $result_row;
3052
                        $courses[] = $result_row['real_id'];
3053
                    }
3054
                }
3055
            }
3056
        }
3057
3058
        if (api_is_drh()) {
3059
            $session_list = SessionManager::get_sessions_followed_by_drh($user_id);
3060
            $session_list = array_keys($session_list);
3061
            if (in_array($session_id, $session_list)) {
3062
                $course_list = SessionManager::get_course_list_by_session_id($session_id);
3063 View Code Duplication
                if (!empty($course_list)) {
3064
                    foreach ($course_list as $course) {
0 ignored issues
show
Bug introduced by
The expression $course_list of type integer|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

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

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

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

Loading history...
3065
                        if (!in_array($course['id'], $courses)) {
3066
                            $personal_course_list[] = $course;
3067
                        }
3068
                    }
3069
                }
3070
            }
3071
        } else {
3072
            //check if user is general coach for this session
3073
            $sessionInfo = api_get_session_info($session_id);
3074
            if ($sessionInfo['id_coach'] == $user_id) {
3075
                $course_list = SessionManager::get_course_list_by_session_id($session_id);
3076 View Code Duplication
                if (!empty($course_list)) {
3077
                    foreach ($course_list as $course) {
0 ignored issues
show
Bug introduced by
The expression $course_list of type integer|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

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

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

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

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