Failed Conditions
Push — issue#765 ( 54a2c2...25bda7 )
by Guilherme
09:33
created

UserManager::blockUsersByPhone()   B

Complexity

Conditions 6
Paths 24

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
cc 6
eloc 11
nc 24
nop 2
dl 0
loc 21
ccs 0
cts 12
cp 0
crap 42
rs 8.7624
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 Doctrine\Common\Persistence\ObjectManager;
15
use FOS\UserBundle\Util\CanonicalizerInterface;
16
use libphonenumber\PhoneNumber;
17
use LoginCidadao\CoreBundle\Model\PersonInterface;
18
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
19
use FOS\UserBundle\Model\UserInterface;
20
use LoginCidadao\ValidationBundle\Validator\Constraints\UsernameValidator;
21
22
class UserManager extends BaseManager
23
{
24
25
    public function __construct(
26
        EncoderFactoryInterface $encoderFactory,
27
        CanonicalizerInterface $usernameCanonicalizer,
28
        CanonicalizerInterface $emailCanonicalizer,
29
        ObjectManager $om,
30
        $class
31
    ) {
32
        parent::__construct($encoderFactory, $usernameCanonicalizer, $emailCanonicalizer, $om, $class);
33
    }
34
35
    public function createUser()
36
    {
37
        return parent::createUser();
38
    }
39
40
    /**
41
     * Updates a user.
42
     *
43
     * @param UserInterface $user
44
     * @param Boolean $andFlush Whether to flush the changes (default true)
45
     */
46
    public function updateUser(UserInterface $user, $andFlush = true)
47
    {
48
        $this->updateCanonicalFields($user);
49
        $this->enforceUsername($user);
50
51
        parent::updateUser($user, $andFlush);
52
    }
53
54
    /**
55
     * Enforces that the given user will have an username
56
     * @param \FOS\UserBundle\Model\UserInterface $user
57
     */
58
    public function enforceUsername(UserInterface $user)
59
    {
60
        $current = $user->getUsernameCanonical();
61
        if (is_null($current) || strlen($current) === 0) {
62
            $email = explode('@', $user->getEmailCanonical(), 2);
63
            $username = $email[0];
64
            if (!UsernameValidator::isUsernameValid($username)) {
65
                $username = UsernameValidator::getValidUsername();
66
            }
67
            $newUsername = $this->getNextAvailableUsername($username);
68
69
            $user->setUsername($newUsername);
70
            $this->updateCanonicalFields($user);
71
        }
72
    }
73
74
    /**
75
     * Tries to find an available username.
76
     * TODO: Yeah, this is ugly, I'm sorry, but does the job.
77
     * This is based on HWI's FOSUBRegistrationFormHandler
78
     *
79
     * @param string $username
80
     * @param int $maxIterations
81
     * @param string $default
82
     * @return string
83
     */
84
    public function getNextAvailableUsername($username, $maxIterations = 10, $default = null)
85
    {
86
        $i = 0;
87
        $testName = $username;
88
89
        do {
90
            $user = $this->findUserByUsername($testName);
91
        } while ($user !== null && $i < $maxIterations && $testName = $username.$i++);
92
93
        if (!$user) {
0 ignored issues
show
introduced by
$user is of type object, thus it always evaluated to true.
Loading history...
94
            return $testName;
95
        } else {
96
            return $default ?: "$username@".time();
97
        }
98
    }
99
100
    public function findUserByUsernameOrEmail($username)
101
    {
102
        $onlyNumbers = preg_replace('/[^0-9]/', '', $username);
103
        $looksLikeCpf = is_numeric($onlyNumbers) && strlen($onlyNumbers) == 11;
104
105
        // If it looks like a CPF we give it a try
106
        if ($looksLikeCpf) {
107
            $person = parent::findUserBy(['cpf' => $onlyNumbers]);
108
109
            if ($person !== null) {
110
                return $person;
111
            }
112
        }
113
114
        // If it doesn't look like a CPF number or if we couldn't find nobody with that CPF, fallback to this:
115
        return parent::findUserByUsernameOrEmail($username);
116
    }
117
118
    public function blockPerson(PersonInterface $person, $andFlush = true)
119
    {
120
        if (!$person->isEnabled() && !$person->isAccountNonLocked()) {
121
            return null;
122
        }
123
124
        $person
125
            ->setUpdatedAt(new \DateTime())
126
            ->setEnabled(false)
127
            ->setLocked(true)
128
            ->setPassword('#BLOCKED#'.microtime());
129
130
        $this->updateUser($person, $andFlush);
131
132
        return $person;
133
    }
134
135
    public function blockUsersByPhone(PhoneNumber $phone, $flushStrategy = null)
136
    {
137
        $andFlush = $flushStrategy === 'each' ? true : false;
138
        $once = $flushStrategy === 'once' ? true : false;
139
140
        /** @var PersonInterface[] $users */
141
        $users = $this->repository->findBy(['mobile' => $phone]);
142
143
        $blockedUsers = [];
144
        foreach ($users as $user) {
145
            $user = $this->blockPerson($user, $andFlush);
146
            if ($user instanceof PersonInterface) {
147
                $blockedUsers[] = $user;
148
            }
149
            // TODO: add yield when we upgrade to PHP 7.0
150
        }
151
        if ($once) {
152
            $this->objectManager->flush();
153
        }
154
155
        return $blockedUsers;
156
    }
157
}
158