Passed
Push — master ( a6dc76...6d79cb )
by Guilherme
01:12 queued 11s
created

PhoneVerificationSubscriber::onPhoneChange()   A

Complexity

Conditions 6
Paths 8

Size

Total Lines 28
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 18
nc 8
nop 3
dl 0
loc 28
ccs 18
cts 18
cp 1
crap 6
rs 9.0444
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\PhoneVerificationBundle\Event;
12
13
use libphonenumber\PhoneNumberFormat;
14
use libphonenumber\PhoneNumberUtil;
15
use LoginCidadao\CoreBundle\Model\PersonInterface;
16
use LoginCidadao\PhoneVerificationBundle\PhoneVerificationEvents;
17
use LoginCidadao\PhoneVerificationBundle\Service\PhoneVerificationServiceInterface;
18
use Psr\Log\LoggerAwareInterface;
19
use Psr\Log\LoggerAwareTrait;
20
use Psr\Log\LoggerTrait;
21
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
22
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
23
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
24
use Symfony\Component\Security\Http\SecurityEvents;
25
26
class PhoneVerificationSubscriber implements EventSubscriberInterface, LoggerAwareInterface
27
{
28
    use LoggerAwareTrait, LoggerTrait;
29
30
    /** @var PhoneVerificationServiceInterface */
31
    private $phoneVerificationService;
32
33
    /**
34
     * PhoneVerificationSubscriber constructor.
35
     * @param PhoneVerificationServiceInterface $phoneVerificationService
36
     */
37 7
    public function __construct(PhoneVerificationServiceInterface $phoneVerificationService)
38
    {
39 7
        $this->phoneVerificationService = $phoneVerificationService;
40 7
    }
41
42
    /**
43
     * Logs with an arbitrary level.
44
     *
45
     * @param mixed $level
46
     * @param string $message
47
     * @param array $context
48
     *
49
     * @return void
50
     */
51 5
    protected function log($level, $message, array $context = array())
52
    {
53 5
        if ($this->logger) {
54 1
            $this->logger->log($level, $message, $context);
55
        }
56 5
    }
57
58
    /**
59
     * Returns an array of event names this subscriber wants to listen to.
60
     *
61
     * The array keys are event names and the value can be:
62
     *
63
     *  * The method name to call (priority defaults to 0)
64
     *  * An array composed of the method name to call and the priority
65
     *  * An array of arrays composed of the method names to call and respective
66
     *    priorities, or 0 if unset
67
     *
68
     * For instance:
69
     *
70
     *  * array('eventName' => 'methodName')
71
     *  * array('eventName' => array('methodName', $priority))
72
     *  * array('eventName' => array(array('methodName1', $priority), array('methodName2')))
73
     *
74
     * @return array The event names to listen to
75
     */
76 1
    public static function getSubscribedEvents()
77
    {
78
        return [
79 1
            PhoneVerificationEvents::PHONE_CHANGED => 'onPhoneChange',
80
            PhoneVerificationEvents::PHONE_VERIFICATION_REQUESTED => 'onVerificationRequest',
81
            PhoneVerificationEvents::PHONE_VERIFICATION_CODE_SENT => 'onCodeSent',
82
            SecurityEvents::INTERACTIVE_LOGIN => 'onLogin',
83
        ];
84
    }
85
86 3
    public function onPhoneChange(PhoneChangedEvent $event, $eventName, EventDispatcherInterface $dispatcher)
87
    {
88 3
        $person = $event->getPerson();
89 3
        $oldPhone = $event->getOldPhone();
90 3
        $newPhone = $person->getMobile();
91
92 3
        $phoneUtil = PhoneNumberUtil::getInstance();
93 3
        $this->info('Phone changed from {old} to {new} for user {id}', [
94 3
            'id' => $person->getId(),
95 3
            'old' => $oldPhone ? $phoneUtil->format($oldPhone, PhoneNumberFormat::E164) : null,
0 ignored issues
show
introduced by
$oldPhone is of type libphonenumber\PhoneNumber, thus it always evaluated to true.
Loading history...
96 3
            'new' => $newPhone ? $phoneUtil->format($newPhone, PhoneNumberFormat::E164) : null,
97
        ]);
98
99 3
        if ($oldPhone) {
0 ignored issues
show
introduced by
$oldPhone is of type libphonenumber\PhoneNumber, thus it always evaluated to true.
Loading history...
100 2
            $oldPhoneVerification = $this->phoneVerificationService->getPhoneVerification($person, $oldPhone);
101
        } else {
102 1
            $oldPhoneVerification = null;
103
        }
104
105 3
        if ($oldPhoneVerification) {
0 ignored issues
show
introduced by
$oldPhoneVerification is of type LoginCidadao\PhoneVerifi...neVerificationInterface, thus it always evaluated to true.
Loading history...
106 1
            $this->phoneVerificationService->removePhoneVerification($oldPhoneVerification);
107
        }
108
109 3
        if ($newPhone) {
110 2
            $phoneVerification = $this->phoneVerificationService->createPhoneVerification($person, $newPhone);
111
112 2
            $sendEvent = new SendPhoneVerificationEvent($phoneVerification);
113 2
            $dispatcher->dispatch(PhoneVerificationEvents::PHONE_VERIFICATION_REQUESTED, $sendEvent);
114
        }
115 3
    }
116
117 1
    public function onVerificationRequest(SendPhoneVerificationEvent $event)
118
    {
119 1
        $person = $event->getPhoneVerification()->getPerson();
120 1
        $phoneUtil = PhoneNumberUtil::getInstance();
121 1
        $this->info('Phone Verification requested for {phone} for user {user_id}', [
122 1
            'user_id' => $person->getId(),
123 1
            'phone' => $phoneUtil->format($person->getMobile(), PhoneNumberFormat::E164),
124
        ]);
125 1
    }
126
127 1
    public function onCodeSent(SendPhoneVerificationEvent $event)
128
    {
129 1
        $sentVerification = $event->getSentVerification();
130 1
        $this->phoneVerificationService->registerVerificationSent($sentVerification);
131 1
    }
132
133 2
    public function onLogin(InteractiveLoginEvent $event, $eventName, EventDispatcherInterface $dispatcher)
134
    {
135
        /** @var PersonInterface $person */
136 2
        $person = $event->getAuthenticationToken()->getUser();
137 2
        if (!$person instanceof PersonInterface || !$phone = $person->getMobile()) {
0 ignored issues
show
introduced by
$person is always a sub-type of LoginCidadao\CoreBundle\Model\PersonInterface.
Loading history...
138 1
            return;
139
        }
140
141 1
        $verification = $this->phoneVerificationService->getPhoneVerification($person, $phone);
142 1
        if (!$verification) {
0 ignored issues
show
introduced by
$verification is of type LoginCidadao\PhoneVerifi...neVerificationInterface, thus it always evaluated to true.
Loading history...
143 1
            $this->info(
144 1
                "User {user_id} has a phone but didn't verify it. Creating Phone Verification request.",
145 1
                ['user_id' => $person->getId()]
146
            );
147 1
            $verification = $this->phoneVerificationService->enforcePhoneVerification($person, $phone);
148
149 1
            $sendEvent = new SendPhoneVerificationEvent($verification);
150 1
            $dispatcher->dispatch(PhoneVerificationEvents::PHONE_VERIFICATION_REQUESTED, $sendEvent);
151
        }
152 1
    }
153
}
154