Passed
Pull Request — feature/unit-tests (#37)
by Daniel
05:46
created

UserListener   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 105
Duplicated Lines 0 %

Test Coverage

Coverage 36.84%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 19
eloc 53
dl 0
loc 105
ccs 21
cts 57
cp 0.3684
rs 10
c 1
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A recomputeUserChangeSet() 0 3 1
A __construct() 0 14 1
A preUpdate() 0 22 4
A prePersist() 0 8 3
A postPersist() 0 3 1
B postUpdate() 0 16 7
A encodePassword() 0 13 2
1
<?php
2
3
/*
4
 * This file is part of the Silverback API Component Bundle Project
5
 *
6
 * (c) Daniel West <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Silverback\ApiComponentBundle\EventListener\Doctrine;
15
16
use Doctrine\ORM\Event\LifecycleEventArgs;
17
use Doctrine\ORM\Mapping\ClassMetadata;
18
use Doctrine\ORM\UnitOfWork;
19
use Silverback\ApiComponentBundle\Entity\User\AbstractUser;
20
use Silverback\ApiComponentBundle\Mailer\UserMailer;
21
use Silverback\ApiComponentBundle\Security\TokenGenerator;
22
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
23
24
/**
25
 * @author Daniel West <[email protected]>
26
 */
27
class UserListener
28
{
29
    private UserPasswordEncoderInterface $passwordEncoder;
30
    private UserMailer $userMailer;
31
    private TokenGenerator $tokenGenerator;
32
    private bool $initialEmailVerifiedState;
33
    private bool $verifyEmailOnRegister;
34
    private bool $verifyEmailOnChange;
35
    private array $changeSet = [];
36
37 5
    public function __construct(
38
        UserPasswordEncoderInterface $passwordEncoder,
39
        UserMailer $userMailer,
40
        TokenGenerator $tokenGenerator,
41
        bool $initialEmailVerifiedState,
42
        bool $verifyEmailOnRegister,
43
        bool $verifyEmailOnChange
44
    ) {
45 5
        $this->passwordEncoder = $passwordEncoder;
46 5
        $this->userMailer = $userMailer;
47 5
        $this->tokenGenerator = $tokenGenerator;
48 5
        $this->initialEmailVerifiedState = $initialEmailVerifiedState;
49 5
        $this->verifyEmailOnRegister = $verifyEmailOnRegister;
50 5
        $this->verifyEmailOnChange = $verifyEmailOnChange;
51 5
    }
52
53 5
    public function prePersist(AbstractUser $user): void
54
    {
55 5
        $this->encodePassword($user);
56 5
        $user->setEmailAddressVerified($this->initialEmailVerifiedState);
57 5
        if (!$this->initialEmailVerifiedState) {
58 5
            $user->setNewEmailAddress($user->getEmailAddress());
59 5
            if (!$this->verifyEmailOnRegister) {
60
                $user->setNewEmailVerificationToken($confirmationToken = $this->tokenGenerator->generateToken());
61
            }
62
        }
63 5
    }
64
65 5
    public function postPersist(AbstractUser $user): void
66
    {
67 5
        $this->userMailer->sendWelcomeEmail($user);
68 5
    }
69
70
    public function preUpdate(AbstractUser $user, LifecycleEventArgs $args): void
71
    {
72
        $manager = $args->getEntityManager();
73
        $uow = $manager->getUnitOfWork();
74
        $userClassMetadata = $manager->getClassMetadata(AbstractUser::class);
75
76
        $passwordEncoded = $this->encodePassword($user);
77
        if ($passwordEncoded) {
78
            $this->recomputeUserChangeSet($uow, $userClassMetadata, $user);
79
        }
80
81
        $this->changeSet = $uow->getEntityChangeSet($user);
82
83
        if (isset($this->changeSet['newEmailAddress'])) {
84
            if (false === $this->verifyEmailOnChange) {
85
                $user->setEmailAddress($user->getNewEmailAddress());
86
                $user->setNewEmailAddress(null);
87
            } else {
88
                $user->setNewEmailVerificationToken($confirmationToken = $this->tokenGenerator->generateToken());
89
            }
90
            $this->recomputeUserChangeSet($uow, $userClassMetadata, $user);
91
            $this->changeSet = $uow->getEntityChangeSet($user);
92
        }
93
    }
94
95
    public function postUpdate(AbstractUser $user): void
96
    {
97
        if (isset($this->changeSet['enabled']) && !$this->changeSet['enabled'][0] && $user->isEnabled()) {
98
            $this->userMailer->sendUserEnabledEmail($user);
99
        }
100
101
        if (isset($this->changeSet['username'])) {
102
            $this->userMailer->sendUsernameChangedEmail($user);
103
        }
104
105
        if (isset($this->changeSet['password'])) {
106
            $this->userMailer->sendPasswordChangedEmail($user);
107
        }
108
109
        if (isset($this->changeSet['newEmailAddress'])) {
110
            $this->userMailer->sendChangeEmailVerificationEmail($user);
111
        }
112
    }
113
114
    private function recomputeUserChangeSet(UnitOfWork $uow, ClassMetadata $userClassMetadata, AbstractUser $user): void
115
    {
116
        $uow->recomputeSingleEntityChangeSet($userClassMetadata, $user);
117
    }
118
119 5
    private function encodePassword(AbstractUser $entity): bool
120
    {
121 5
        if (!$entity->getPlainPassword()) {
122 5
            return false;
123
        }
124
        $encoded = $this->passwordEncoder->encodePassword(
125
            $entity,
126
            $entity->getPlainPassword()
127
        );
128
        $entity->setPassword($encoded);
129
        $entity->eraseCredentials();
130
131
        return true;
132
    }
133
}
134