Failed Conditions
Push — master ( 32d930...704890 )
by Adrien
08:40
created

UserRepository   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 144
Duplicated Lines 0 %

Test Coverage

Coverage 98.31%

Importance

Changes 0
Metric Value
eloc 54
dl 0
loc 144
ccs 58
cts 59
cp 0.9831
rs 10
c 0
b 0
f 0
wmc 16

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getAccessibleSubQuery() 0 7 2
B getOneByLoginPassword() 0 31 9
A getAllToQueueBalanceMessage() 0 28 2
A getOneById() 0 7 1
A getOneByLogin() 0 7 1
A getAllAdministratorsToNotify() 0 14 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Application\Repository;
6
7
use Application\DBAL\Types\BookingTypeType;
8
use Application\Model\User;
9
use Doctrine\DBAL\Connection;
10
11
class UserRepository extends AbstractRepository implements LimitedAccessSubQueryInterface
12
{
13
    /**
14
     * Returns pure SQL to get ID of all objects that are accessible to given user.
15
     *
16
     * @param null|User $user
17
     *
18
     * @return string
19
     */
20 18
    public function getAccessibleSubQuery(?User $user): string
21
    {
22 18
        if (!$user) {
23 6
            return '-1';
24
        }
25
26 12
        return $this->getAllIdsQuery();
27
    }
28
29
    /**
30
     * Returns the user authenticated by its email and password
31
     *
32
     * @param string $login
33
     * @param string $password
34
     *
35
     * @return null|User
36
     */
37 2
    public function getOneByLoginPassword(string $login, string $password): ?User
38
    {
39
        /** @var User $user */
40 2
        $user = $this->getOneByLogin($login);
41
42 2
        if (!$user) {
43 1
            return null;
44
        }
45
46
        // Check user status
47 2
        if (!in_array($user->getStatus(), [User::STATUS_ACTIVE, User::STATUS_INACTIVE, User::STATUS_NEW], true)) {
48
            return null;
49
        }
50
51 2
        $hashFromDb = $user->getPassword();
52 2
        $isMd5 = mb_strlen($hashFromDb) === 32 && ctype_xdigit($hashFromDb);
53
54
        // If we found a user and he has a correct MD5 or correct new hash, then return the user
55 2
        if (($isMd5 && md5($password) === $hashFromDb) || password_verify($password, $hashFromDb)) {
56
57
            // Update the hash in DB, if we are still MD5, or if PHP default options changed
58 2
            if ($isMd5 || password_needs_rehash($hashFromDb, PASSWORD_DEFAULT)) {
59 2
                $user->setPassword($password);
60
            }
61 2
            $user->revokeToken();
62 2
            _em()->flush();
63
64 2
            return $user;
65
        }
66
67 1
        return null;
68
    }
69
70
    /**
71
     * Unsecured way to get a user from its ID.
72
     *
73
     * This should only be used in tests or controlled environment.
74
     *
75
     * @param int $id
76
     *
77
     * @return null|User
78
     */
79 16
    public function getOneById(int $id): ?User
80
    {
81
        $user = $this->getAclFilter()->runWithoutAcl(function () use ($id) {
82 16
            return $this->findOneById($id);
83 16
        });
84
85 16
        return $user;
86
    }
87
88
    /**
89
     * Unsecured way to get a user from its login.
90
     *
91
     * This should only be used in tests or controlled environment.
92
     *
93
     * @param null|string $login
94
     *
95
     * @return null|User
96
     */
97 86
    public function getOneByLogin(?string $login): ?User
98
    {
99
        $user = $this->getAclFilter()->runWithoutAcl(function () use ($login) {
100 86
            return $this->findOneByLogin($login);
1 ignored issue
show
Bug introduced by
The method findOneByLogin() does not exist on Application\Repository\UserRepository. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

100
            return $this->/** @scrutinizer ignore-call */ findOneByLogin($login);
Loading history...
101 86
        });
102
103 86
        return $user;
104
    }
105
106
    /**
107
     * Get all administrators to notify by email
108
     *
109
     * @return User[]
110
     */
111 2
    public function getAllAdministratorsToNotify(): array
112
    {
113 2
        $qb = $this->createQueryBuilder('user')
114 2
            ->andWhere('user.status = :status')
115 2
            ->andWhere('user.role = :role')
116 2
            ->andWhere("user.email IS NOT NULL AND user.email != ''")
117 2
            ->setParameter('status', User::STATUS_ACTIVE)
118 2
            ->setParameter('role', User::ROLE_ADMINISTRATOR);
119
120
        $result = $this->getAclFilter()->runWithoutAcl(function () use ($qb) {
121 2
            return $qb->getQuery()->getResult();
122 2
        });
123
124 2
        return $result;
125
    }
126
127 4
    public function getAllToQueueBalanceMessage(bool $onlyNegativeBalance = false): array
128
    {
129 4
        $qb = $this->createQueryBuilder('user')
130 4
            ->addSelect('account')
131 4
            ->addSelect('booking')
132 4
            ->addSelect('bookable')
133 4
            ->join('user.accounts', 'account')
134 4
            ->join('user.bookings', 'booking')
135 4
            ->join('booking.bookable', 'bookable')
136 4
            ->andWhere('user.status != :status')
137 4
            ->andWhere("user.email IS NOT NULL AND user.email != ''")
138 4
            ->andWhere('bookable.bookingType IN (:bookingType)')
139 4
            ->andWhere('bookable.isActive = true')
140 4
            ->andWhere('bookable.periodicPrice != 0')
141 4
            ->setParameter('bookingType', [BookingTypeType::MANDATORY, BookingTypeType::ADMIN_ONLY], Connection::PARAM_STR_ARRAY)
142 4
            ->setParameter('status', User::STATUS_ARCHIVED)
143 4
            ->addOrderBy('user.id')
144 4
            ->addOrderBy('bookable.name');
145
146 4
        if ($onlyNegativeBalance) {
147 2
            $qb->andWhere('account.balance < 0');
148
        }
149
150
        $result = $this->getAclFilter()->runWithoutAcl(function () use ($qb) {
151 4
            return $qb->getQuery()->getResult();
152 4
        });
153
154 4
        return $result;
155
    }
156
}
157