Passed
Push — issue#702 ( 0b5bf0...f20c81 )
by Guilherme
06:32
created

SmsStatusService::getDelayedDeliveryTransactions()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 1
dl 0
loc 14
ccs 9
cts 9
cp 1
crap 2
rs 9.4285
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\Service;
12
13
use Doctrine\ORM\EntityManagerInterface;
14
use LoginCidadao\PhoneVerificationBundle\Entity\SentVerificationRepository;
15
use LoginCidadao\PhoneVerificationBundle\Event\UpdateStatusEvent;
16
use LoginCidadao\PhoneVerificationBundle\Model\SentVerificationInterface;
17
use LoginCidadao\PhoneVerificationBundle\Model\SmsStatusInterface;
18
use LoginCidadao\PhoneVerificationBundle\PhoneVerificationEvents;
19
use Symfony\Component\Console\Style\SymfonyStyle;
20
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
21
22
class SmsStatusService
23
{
24
    /** @var EntityManagerInterface */
25
    private $em;
26
27
    /** @var EventDispatcherInterface */
28
    private $dispatcher;
29
30
    /** @var SentVerificationRepository */
31
    private $sentVerificationRepo;
32
33
    /** @var SymfonyStyle */
34
    private $io;
35
36
    /**
37
     * SmsStatusUpdater constructor.
38
     * @param EntityManagerInterface $em
39
     * @param EventDispatcherInterface $dispatcher
40
     * @param SentVerificationRepository $sentVerificationRepo
41
     */
42 9
    public function __construct(
43
        EntityManagerInterface $em,
44
        EventDispatcherInterface $dispatcher,
45
        SentVerificationRepository $sentVerificationRepo
46
    ) {
47 9
        $this->em = $em;
48 9
        $this->dispatcher = $dispatcher;
49 9
        $this->sentVerificationRepo = $sentVerificationRepo;
50 9
    }
51
52
    /**
53
     * @param SymfonyStyle $io
54
     * @return SmsStatusService
55
     */
56 8
    public function setSymfonyStyle(SymfonyStyle $io)
57
    {
58 8
        $this->io = $io;
59
60 8
        return $this;
61
    }
62
63
    /**
64
     * @param $transactionId
65
     * @return SmsStatusInterface
66
     */
67 1
    public function getSmsStatus($transactionId)
68
    {
69 1
        $event = $this->getStatus($transactionId);
70
71 1
        return $event->getDeliveryStatus();
72
    }
73
74 5
    public function updateSentVerificationStatus($batchSize = 1)
75
    {
76 5
        $count = $this->sentVerificationRepo->countPendingUpdateSentVerification();
77
78 5
        if ($count === 0) {
79 1
            $this->comment('No messages pending update.');
80
81 1
            return [];
82
        }
83
84 4
        $query = $this->sentVerificationRepo->getPendingUpdateSentVerificationQuery();
85 4
        $sentVerifications = $query->iterate();
86
87
        //$this->em->getConnection()->getConfiguration()->setSQLLogger(null);
0 ignored issues
show
Unused Code Comprehensibility introduced by
77% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
88 4
        gc_enable();
89 4
        $this->progressStart($count);
90 4
        $transactionsUpdated = [];
91 4
        foreach ($sentVerifications as $row) {
92
            /** @var SentVerificationInterface $sentVerification */
93 3
            $sentVerification = $row[0];
94 3
            $event = $this->getStatus($sentVerification->getTransactionId());
95 3
            if (false === $event->isUpdated()) {
96 2
                $this->progressAdvance(1);
97 2
                unset($event);
98 2
                unset($sentVerification);
99 2
                gc_collect_cycles();
100 2
                continue;
101
            }
102
103 1
            $deliveredAt = $event->getDeliveredAt();
104 1
            $sentVerification->setActuallySentAt($event->getSentAt())
105 1
                ->setDeliveredAt($deliveredAt)
106 1
                ->setFinished($deliveredAt instanceof \DateTime || $event->getDeliveryStatus()->isFinal());
107 1
            $transactionsUpdated[] = $sentVerification->getTransactionId();
108 1
            unset($event);
109 1
            unset($sentVerification);
110 1
            if ((count($transactionsUpdated) % $batchSize) === 0) {
111 1
                $this->em->flush();
112 1
                $this->em->clear();
113 1
                gc_collect_cycles();
114
            }
115 1
            $this->progressAdvance(1);
116
        }
117 4
        $this->em->flush();
118 4
        $this->em->clear();
119 4
        $this->progressFinish();
120
121 4
        $countUpdated = count($transactionsUpdated);
122 4
        $this->comment("Updated {$countUpdated} transactions.");
123
124 4
        if ($countUpdated === 0) {
125 3
            $this->comment("It's possible the SMS-sending service you are using doesn't implement status updates.");
126
        }
127
128 4
        return $transactionsUpdated;
129
    }
130
131
    /**
132
     * @param $amount
133
     * @return float average delivery time in seconds (abs value)
134
     */
135 3
    public function getAverageDeliveryTime($amount)
136
    {
137
        /** @var SentVerificationInterface[] $sentVerifications */
138 3
        $sentVerifications = $this->sentVerificationRepo->getLastDeliveredVerifications($amount);
139
140 3
        if (count($sentVerifications) === 0) {
141 2
            return 0;
142
        }
143
144 1
        $times = [];
145 1
        foreach ($sentVerifications as $sentVerification) {
146 1
            $times[] = abs(
147 1
                $sentVerification->getDeliveredAt()->format('U') - $sentVerification->getSentAt()->format('U')
148
            );
149
        }
150 1
        $sum = array_sum($times);
151
152 1
        $avg = $sum / count($times);
153
154 1
        return $avg;
155
    }
156
157
    /**
158
     * @param int $maxDeliverySeconds
159
     * @return array
160
     */
161 1
    public function getDelayedDeliveryTransactions($maxDeliverySeconds = 0)
162
    {
163 1
        $date = new \DateTime("-{$maxDeliverySeconds} seconds");
164 1
        $notDelivered = $this->sentVerificationRepo->getNotDeliveredSince($date);
165
166 1
        $transactions = [];
167 1
        foreach ($notDelivered as $sentVerification) {
168 1
            $transactions[] = [
169 1
                'transaction_id' => $sentVerification->getTransactionId(),
170 1
                'sent_at' => $sentVerification->getSentAt()->format('c'),
171
            ];
172
        }
173
174 1
        return $transactions;
175
    }
176
177
    /**
178
     * @param $transactionId
179
     * @return UpdateStatusEvent
180
     */
181 4
    private function getStatus($transactionId)
182
    {
183 4
        $event = new UpdateStatusEvent($transactionId);
184 4
        $this->dispatcher->dispatch(PhoneVerificationEvents::PHONE_VERIFICATION_GET_SENT_VERIFICATION_STATUS, $event);
185
186 4
        return $event;
187
    }
188
189 5
    private function comment($message)
190
    {
191 5
        if (!$this->io) {
192 1
            return;
193
        }
194 4
        $this->io->comment($message);
195 4
    }
196
197 4
    private function progressStart($max = 0)
198
    {
199 4
        if (!$this->io) {
200 1
            return;
201
        }
202 3
        $this->io->progressStart($max);
203 3
    }
204
205 3
    private function progressAdvance($step = 1)
206
    {
207 3
        if (!$this->io) {
208 1
            return;
209
        }
210 2
        $this->io->progressAdvance($step);
211 2
    }
212
213 4
    private function progressFinish()
214
    {
215 4
        if (!$this->io) {
216 1
            return;
217
        }
218 3
        $this->io->progressFinish();
219 3
    }
220
}
221