Completed
Push — master ( f867ee...b2d0fe )
by Adrien
09:16 queued 04:47
created

UserRepository::getAllToQueueBalanceMessage()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 28
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 22
nc 2
nop 1
dl 0
loc 28
ccs 23
cts 23
cp 1
crap 2
rs 9.568
c 0
b 0
f 0
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 Cake\Chronos\Chronos;
10
use Doctrine\DBAL\Connection;
11
12
class UserRepository extends AbstractRepository implements LimitedAccessSubQueryInterface
13
{
14
    /**
15
     * Returns pure SQL to get ID of all objects that are accessible to given user.
16
     *
17
     * @param null|User $user
18
     *
19
     * @return string
20
     */
21 17
    public function getAccessibleSubQuery(?User $user): string
22
    {
23 17
        if (!$user) {
24 4
            return '-1';
25
        }
26
27 13
        return $this->getAllIdsQuery();
28
    }
29
30
    /**
31
     * Returns the user authenticated by its email and password
32
     *
33
     * @param string $login
34
     * @param string $password
35
     *
36
     * @return null|User
37
     */
38 2
    public function getOneByLoginPassword(string $login, string $password): ?User
39
    {
40
        /** @var User $user */
41 2
        $user = $this->getOneByLogin($login);
42
43 2
        if (!$user) {
44 1
            return null;
45
        }
46
47
        // Check user status
48 2
        if (!in_array($user->getStatus(), [User::STATUS_ACTIVE, User::STATUS_INACTIVE], true)) {
49
            return null;
50
        }
51
52 2
        $hashFromDb = $user->getPassword();
53 2
        $isMd5 = mb_strlen($hashFromDb) === 32 && ctype_xdigit($hashFromDb);
54
55
        // If we found a user and he has a correct MD5 or correct new hash, then return the user
56 2
        if (($isMd5 && md5($password) === $hashFromDb) || password_verify($password, $hashFromDb)) {
57
58
            // Update the hash in DB, if we are still MD5, or if PHP default options changed
59 2
            if ($isMd5 || password_needs_rehash($hashFromDb, PASSWORD_DEFAULT)) {
60 2
                $user->setPassword($password);
61
            }
62 2
            $user->setLastLogin(new Chronos());
63 2
            _em()->flush();
64
65 2
            return $user;
66
        }
67
68 1
        return null;
69
    }
70
71
    /**
72
     * Unsecured way to get a user from its ID.
73
     *
74
     * This should only be used in tests or controlled environment.
75
     *
76
     * @param int $id
77
     *
78
     * @return null|User
79
     */
80 11
    public function getOneById(int $id): ?User
81
    {
82 11
        $this->getAclFilter()->setEnabled(false);
83 11
        $user = $this->findOneById($id);
84 11
        $this->getAclFilter()->setEnabled(true);
85
86 11
        return $user;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $user could return the type Application\Model\AbstractModel which includes types incompatible with the type-hinted return Application\Model\User|null. Consider adding an additional type-check to rule them out.
Loading history...
87
    }
88
89
    /**
90
     * Unsecured way to get a user from its login.
91
     *
92
     * This should only be used in tests or controlled environment.
93
     *
94
     * @param null|string $login
95
     *
96
     * @return null|User
97
     */
98 83
    public function getOneByLogin(?string $login): ?User
99
    {
100 83
        $this->getAclFilter()->setEnabled(false);
101 83
        $user = $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

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