Passed
Push — master ( 0e9642...551480 )
by Dmitry
03:37
created

EmailReceiveCheck::check()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 4
Bugs 0 Features 0
Metric Value
c 4
b 0
f 0
dl 0
loc 11
ccs 8
cts 8
cp 1
rs 9.4285
cc 2
eloc 6
nc 2
nop 0
crap 2
1
<?php
2
3
namespace TonicHealthCheck\Check\Email\Receive;
4
5
use DateTime;
6
use Doctrine\ORM\EntityManager;
7
use PhpImap\Mailbox;
8
use TonicHealthCheck\Check\Email\AbstractEmailCheck;
9
use TonicHealthCheck\Check\Email\Entity\EmailSendReceive;
10
use PhpImap\Exception as ImapException;
11
12
/**
13
 * Class EmailReceiveCheck
14
 * @package TonicHealthCheck\Check\Email\Send
15
 */
16
class EmailReceiveCheck extends AbstractEmailCheck
17
{
18
    const CHECK = 'email-receive-check';
19
    const RECEIVE_MAX_TIME = 300;
20
21
    /**
22
     * @var bool
23
     */
24
    private $firstFailSkip = true;
25
26
    /**
27
     * @var int
28
     */
29
    private $receiveMaxTime;
30
31
    /**
32
     * @var Mailbox;
33
     */
34
    private $mailbox;
35
36
37
    /**
38
     * @var EntityManager
39
     */
40
    private $doctrine;
41
42
    /**
43
     * @param string        $checkNode
44
     * @param Mailbox       $mailbox
45
     * @param EntityManager $doctrine
46
     * @param int           $receiveMaxTime
47
     */
48 4
    public function __construct(
49
        $checkNode,
50
        Mailbox $mailbox,
51
        EntityManager $doctrine,
52
        $receiveMaxTime = self::RECEIVE_MAX_TIME
53
    ) {
54 4
        parent::__construct($checkNode);
55
56 4
        $this->setMailbox($mailbox);
57 4
        $this->setDoctrine($doctrine);
58 4
        $this->setReceiveMaxTime($receiveMaxTime);
59 4
    }
60
61
    /**
62
     * Check email can send and receive messages
63
     * @return bool|void
64
     * @throws EmailReceiveCheckException
65
     */
66 4
    public function check()
67
    {
68 4
        $emailSendReceiveR = $this->getDoctrine()->getRepository(EmailSendReceive::class);
69
70
        /** @var EmailSendReceive $emailSendCheckI */
71 4
        foreach ($emailSendReceiveR->findBy(
72 4
            ['status' => EmailSendReceive::STATUS_SANDED]
73 4
        ) as $emailSendCheckI) {
74 4
            $this->performReceive($emailSendCheckI);
75 2
        }
76 2
    }
77
78
    /**
79
     * @return Mailbox
80
     */
81 4
    public function getMailbox()
82
    {
83 4
        return $this->mailbox;
84
    }
85
86
    /**
87
     * @return EntityManager
88
     */
89 4
    public function getDoctrine()
90
    {
91 4
        return $this->doctrine;
92
    }
93
94
    /**
95
     * @return int
96
     */
97 2
    public function getReceiveMaxTime()
98
    {
99 2
        return $this->receiveMaxTime;
100
    }
101
102
    /**
103
     * @return boolean
104
     */
105 2
    public function isFirstFailSkip()
106
    {
107 2
        return $this->firstFailSkip;
108
    }
109
110
    /**
111
     * @param Mailbox $mailbox
112
     */
113 4
    protected function setMailbox(Mailbox $mailbox)
114
    {
115 4
        $this->mailbox = $mailbox;
116 4
    }
117
118
    /**
119
     * @param EntityManager $doctrine
120
     */
121 4
    protected function setDoctrine(EntityManager $doctrine)
122
    {
123 4
        $this->doctrine = $doctrine;
124 4
    }
125
126
    /**
127
     * @param int $receiveMaxTime
128
     */
129 4
    protected function setReceiveMaxTime($receiveMaxTime)
130
    {
131 4
        $this->receiveMaxTime = $receiveMaxTime;
132 4
    }
133
134
    /**
135
     * @param boolean $firstFailSkip
136
     */
137 2
    protected function setFirstFailSkip($firstFailSkip)
138
    {
139 2
        $this->firstFailSkip = $firstFailSkip;
140 2
    }
141
142
    /**
143
     * @param EmailSendReceive $emailSendCheckI
144
     * @throws EmailReceiveCheckException
145
     */
146 2
    protected function timeReceiveCheck(EmailSendReceive $emailSendCheckI)
147
    {
148 2
        $timeLeft = time() - $emailSendCheckI->getSentAt()->getTimestamp();
149 2
        if ($timeLeft > $this->getReceiveMaxTime()) {
150
151 2
            $emailSendCheckI->setStatus(EmailSendReceive::STATUS_EXPIRED);
152 2
            $emailSendCheckI->setReceivedAt(new DateTime());
153 2
            $this->saveEmailSendReceive($emailSendCheckI);
154
155 2
            if (!$this->isFirstFailSkip()) {
156 1
                throw EmailReceiveCheckException::receivingMaxTimeExpire(
157 1
                    $emailSendCheckI->getSubject(),
158 1
                    $timeLeft,
159 1
                    $this->getReceiveMaxTime()
160 1
                );
161
            } else {
162
163 2
                $this->setFirstFailSkip(false);
164
            }
165 2
        }
166 2
    }
167
168
    /**
169
     * @param EmailSendReceive $emailSendCheckI
170
     */
171 3
    private function saveEmailSendReceive(EmailSendReceive $emailSendCheckI)
172
    {
173 3
        $this->getDoctrine()->persist($emailSendCheckI);
174 3
        $this->getDoctrine()->flush();
175 3
    }
176
177
    /**
178
     * @param $mails
179
     * @param EmailSendReceive $emailSendCheckI
180
     */
181 2
    private function deleteReceivedEmails($mails, EmailSendReceive $emailSendCheckI)
182
    {
183 2
        foreach ($mails as $mailId) {
184 2
            $this->getMailbox()->deleteMail($mailId);
185 2
            $emailSendCheckI->setStatus(EmailSendReceive::STATUS_RECEIVED);
186 2
            $this->saveEmailSendReceive($emailSendCheckI);
187 2
        }
188 2
    }
189
190
    /**
191
     * @param EmailSendReceive $emailSendCheckI
192
     * @throws EmailReceiveCheckException
193
     */
194 4
    private function performReceive(EmailSendReceive $emailSendCheckI)
195
    {
196
        try {
197 4
            $mails = $this->getMailbox()->searchMailbox(
198 4
                'FROM '.$emailSendCheckI->getFrom().' SUBJECT '.$emailSendCheckI->getSubject()
199 4
            );
200 2
            if (count($mails) > 0) {
201 2
                $this->deleteReceivedEmails($mails, $emailSendCheckI);
202 2
                $this->timeReceiveCheck($emailSendCheckI);
203 2
            }
204 4
        } catch (ImapException $e) {
205 1
            $emailSendCheckI->setStatus(EmailSendReceive::STATUS_RECEIVED_ERROR);
206 1
            $this->saveEmailSendReceive($emailSendCheckI);
207 1
            throw EmailReceiveCheckException::internalProblem($e);
208
        }
209 2
    }
210
}
211