Completed
Pull Request — master (#790)
by Guilherme
08:21 queued 04:10
created

UserManager::updateUser()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 6
ccs 0
cts 4
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file is part of the login-cidadao project or it's bundles.
4
 *
5
 * (c) Guilherme Donato <guilhermednt on github>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace LoginCidadao\CoreBundle\Security\User\Manager;
12
13
use FOS\UserBundle\Doctrine\UserManager as BaseManager;
14
use libphonenumber\PhoneNumber;
15
use LoginCidadao\CoreBundle\Model\PersonInterface;
16
use FOS\UserBundle\Model\UserInterface;
17
use LoginCidadao\ValidationBundle\Validator\Constraints\UsernameValidator;
18
19
class UserManager extends BaseManager
20
{
21
    public function createUser()
22
    {
23
        return parent::createUser();
24
    }
25
26
    /**
27
     * Updates a user.
28
     *
29
     * @param UserInterface $user
30
     * @param Boolean $andFlush Whether to flush the changes (default true)
31
     */
32
    public function updateUser(UserInterface $user, $andFlush = true)
33
    {
34
        $this->updateCanonicalFields($user);
35
        $this->enforceUsername($user);
36
37
        parent::updateUser($user, $andFlush);
38
    }
39
40
    /**
41
     * Enforces that the given user will have an username
42
     * @param \FOS\UserBundle\Model\UserInterface $user
43
     */
44
    public function enforceUsername(UserInterface $user)
45
    {
46
        $current = $user->getUsernameCanonical();
47
        if (is_null($current) || strlen($current) === 0) {
48
            $email = explode('@', $user->getEmailCanonical(), 2);
49
            $username = $email[0];
50
            if (!UsernameValidator::isUsernameValid($username)) {
51
                $username = UsernameValidator::getValidUsername();
52
            }
53
            $newUsername = $this->getNextAvailableUsername($username);
54
55
            $user->setUsername($newUsername);
56
            $this->updateCanonicalFields($user);
57
        }
58
    }
59
60
    /**
61
     * Tries to find an available username.
62
     * TODO: Yeah, this is ugly, I'm sorry, but does the job.
63
     * This is based on HWI's FOSUBRegistrationFormHandler
64
     *
65
     * @param string $username
66
     * @param int $maxIterations
67
     * @param string $default
68
     * @return string
69
     */
70
    public function getNextAvailableUsername($username, $maxIterations = 10, $default = null)
71
    {
72
        $i = 0;
73
        $testName = $username;
74
75
        do {
76
            $user = $this->findUserByUsername($testName);
77
        } while ($user !== null && $i < $maxIterations && $testName = $username.$i++);
78
79
        if (!$user) {
80
            return $testName;
81
        } else {
82
            return $default ?: "$username@".time();
83
        }
84
    }
85
86
    public function findUserByUsernameOrEmail($username)
87
    {
88
        $onlyNumbers = preg_replace('/[^0-9]/', '', $username);
89
        $looksLikeCpf = is_numeric($onlyNumbers) && strlen($onlyNumbers) == 11;
90
91
        // If it looks like a CPF we give it a try
92
        if ($looksLikeCpf) {
93
            $person = parent::findUserBy(['cpf' => $onlyNumbers]);
94
95
            if ($person !== null) {
96
                return $person;
97
            }
98
        }
99
100
        // If it doesn't look like a CPF number or if we couldn't find nobody with that CPF, fallback to this:
101
        return parent::findUserByUsernameOrEmail($username);
102
    }
103
104
    public function blockPerson(PersonInterface $person, $andFlush = true)
105
    {
106
        if (!$person->isEnabled() && !$person->isAccountNonLocked()) {
107
            return null;
108
        }
109
110
        $person
111
            ->setUpdatedAt(new \DateTime())
112
            ->setEnabled(false)
113
            ->setPassword('#BLOCKED#'.microtime());
114
        if (method_exists($person, 'setLocked')) {
115
            $person->setLocked(true);
116
        }
117
118
        $this->updateUser($person, $andFlush);
119
120
        return $person;
121
    }
122
123
    public function blockUsersByPhone(PhoneNumber $phone, $flushStrategy = null)
124
    {
125
        $andFlush = $flushStrategy === 'each' ? true : false;
126
        $once = $flushStrategy === 'once' ? true : false;
127
128
        /** @var PersonInterface[] $users */
129
        $users = parent::getRepository()->findBy(['mobile' => $phone]);
130
131
        $blockedUsers = [];
132
        foreach ($users as $user) {
133
            $user = $this->blockPerson($user, $andFlush);
134
            if ($user instanceof PersonInterface) {
135
                $blockedUsers[] = $user;
136
            }
137
            // TODO: add yield when we upgrade to PHP 7.0
138
        }
139
        if ($once) {
140
            $this->objectManager->flush();
141
        }
142
143
        return $blockedUsers;
144
    }
145
}
146