Completed
Push — master ( 799be6...89deed )
by Dmitry
04:25
created

EmailReceiveCheck::performCheck()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 11
c 0
b 0
f 0
ccs 7
cts 7
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 PhpImap\Mailbox;
7
use TonicHealthCheck\Check\Email\AbstractEmailCheck;
8
use TonicHealthCheck\Check\Email\Entity\EmailSendReceive;
9
use PhpImap\Exception as ImapException;
10
use TonicHealthCheck\Check\Email\Entity\EmailSendReceiveCollection;
11
use TonicHealthCheck\Check\Email\Persist\PersistCollectionInterface;
12
13
/**
14
 * Class EmailReceiveCheck.
15
 */
16
class EmailReceiveCheck extends AbstractEmailCheck
17
{
18
    const CHECK = 'email-receive-check';
19
    const RECEIVE_MAX_TIME = 300;
20
21
    const COLLECTION_KEEP_TIME = 3600;
22
23
    /**
24
     * @var int
25
     */
26
    private $receiveMaxTime;
27
28
    /**
29
     * @var Mailbox;
30
     */
31
    private $mailbox;
32
33
    /**
34
     * @var PersistCollectionInterface
35
     */
36
    private $persistCollection;
37
38
    /**
39
     * @var EmailSendReceiveCollection
40
     */
41
    private $emailSendReceiveCollection;
42
43
    /**
44
     * @param string                     $checkNode
45
     * @param Mailbox                    $mailbox
46
     * @param PersistCollectionInterface $persistCollection
47
     * @param int                        $receiveMaxTime
48
     */
49 8
    public function __construct(
50
        $checkNode,
51
        Mailbox $mailbox,
52
        PersistCollectionInterface $persistCollection,
53
        $receiveMaxTime = self::RECEIVE_MAX_TIME
54
    ) {
55 8
        parent::__construct($checkNode);
56
57 8
        $this->setMailbox($mailbox);
58 8
        $this->setPersistCollection($persistCollection);
59 8
        $this->setReceiveMaxTime($receiveMaxTime);
60 8
    }
61
62
    /**
63
     * Check email can send and receive messages.
64
     *
65
     * @return void
66
     *
67
     * @throws EmailReceiveCheckException
68
     */
69 6
    public function performCheck()
70
    {
71 6
        $this->setEmailSendReceiveColl($this->getPersistCollection()->load());
72
73
        /** @var EmailSendReceive $emailSendCheckI */
74 6
        foreach ($this->getEmailSendReceiveColl()->findAll($this->findEmailForReceiveCheckCallback()) as $emailSendCheckI) {
75 5
            $this->performReceive($emailSendCheckI);
76
        }
77 3
        $this->removeOldItems();
78 3
        $this->getPersistCollection()->flush();
79 3
    }
80
81
    /**
82
     * @return Mailbox
83
     */
84 5
    public function getMailbox()
85
    {
86 5
        return $this->mailbox;
87
    }
88
89
    /**
90
     * @return PersistCollectionInterface
91
     */
92 6
    public function getPersistCollection()
93
    {
94 6
        return $this->persistCollection;
95
    }
96
97
    /**
98
     * @return int
99
     */
100 3
    public function getReceiveMaxTime()
101
    {
102 3
        return $this->receiveMaxTime;
103
    }
104
105
    /**
106
     * @return EmailSendReceiveCollection
107
     */
108 6
    public function getEmailSendReceiveColl()
109
    {
110 6
        return $this->emailSendReceiveCollection;
111
    }
112
113
    /**
114
     * @param Mailbox $mailbox
115
     */
116 8
    protected function setMailbox(Mailbox $mailbox)
117
    {
118 8
        $this->mailbox = $mailbox;
119 8
    }
120
121
    /**
122
     * @param PersistCollectionInterface $persistCollection
123
     */
124 8
    protected function setPersistCollection(PersistCollectionInterface $persistCollection)
125
    {
126 8
        $this->persistCollection = $persistCollection;
127 8
    }
128
129
    /**
130
     * @param int $receiveMaxTime
131
     */
132 8
    protected function setReceiveMaxTime($receiveMaxTime)
133
    {
134 8
        $this->receiveMaxTime = $receiveMaxTime;
135 8
    }
136
137
    /**
138
     * @param EmailSendReceiveCollection $emailSendReceiveC
139
     */
140 6
    protected function setEmailSendReceiveColl(EmailSendReceiveCollection $emailSendReceiveC)
141
    {
142 6
        $this->emailSendReceiveCollection = $emailSendReceiveC;
143 6
    }
144
145
    /**
146
     * @param EmailSendReceive $emailSendCheckI
147
     *
148
     * @throws EmailReceiveCheckException
149
     */
150 2
    protected function timeReceiveCheck(EmailSendReceive $emailSendCheckI)
151
    {
152 2
        $timeLeft = time() - $emailSendCheckI->getSentAt()->getTimestamp();
153 2
        if ($timeLeft > $this->getReceiveMaxTime()) {
154 1
            $emailSendCheckI->setStatus(EmailSendReceive::STATUS_EXPIRED);
155 1
            $emailSendCheckI->setReceivedAt(new DateTime());
156 1
            throw EmailReceiveCheckException::receivingMaxTimeExpire(
157 1
                $emailSendCheckI->getSubject(),
158
                $timeLeft,
159 1
                $this->getReceiveMaxTime()
160
            );
161
        }
162 2
    }
163
164
    /**
165
     * @param $mails
166
     * @param EmailSendReceive $emailSendCheckI
167
     */
168 2
    private function deleteReceivedEmails($mails, EmailSendReceive $emailSendCheckI)
169
    {
170 2
        foreach ($mails as $mailId) {
171 2
            $this->getMailbox()->deleteMail($mailId);
172
        }
173 2
        $emailSendCheckI->setStatus(EmailSendReceive::STATUS_RECEIVED);
174 2
    }
175
176
    /**
177
     * @param EmailSendReceive $emailSendCheckI
178
     *
179
     * @throws EmailReceiveCheckException
180
     */
181 5
    private function performReceive(EmailSendReceive $emailSendCheckI)
182
    {
183
        try {
184 5
            $mails = $this->getMailbox()->searchMailbox(
185 5
                    sprintf('FROM %s SUBJECT "%s"', $emailSendCheckI->getFrom(), $emailSendCheckI->getSubject())
186
                );
187
188 2
            $this->timeReceiveCheck($emailSendCheckI);
189
190 2
            if (count($mails) > 0) {
191 2
                $this->deleteReceivedEmails($mails, $emailSendCheckI);
192
            }
193 4
        } catch (ImapException $e) {
194 2
            $emailSendCheckI->setStatus(EmailSendReceive::STATUS_RECEIVED_ERROR);
195 2
            throw EmailReceiveCheckException::internalProblem($e);
196
        }
197 2
    }
198
199
    /**
200
     * remove old items.
201
     */
202 3
    private function removeOldItems()
203
    {
204
        $emailSendReceiveOld = $this
205 3
            ->getEmailSendReceiveColl()
206 3
            ->findAll($this->findOldEmailReceiveOldCallback());
207
        /** @var EmailSendReceive $emailSendCheckI */
208 3
        foreach ($emailSendReceiveOld as $emailSendCheckI) {
209
            $this->getEmailSendReceiveColl()->remove(
210
                $this->findSameItemCallback($emailSendCheckI)
211
            );
212
        }
213 3
    }
214
215
    /**
216
     * @param EmailSendReceive $emailSendCheckI
217
     *
218
     * @return \Closure
219
     */
220
    private function findSameItemCallback(EmailSendReceive $emailSendCheckI)
221
    {
222
        return function (EmailSendReceive $emailSendCheckItem) use ($emailSendCheckI) {
223
            return $emailSendCheckItem === $emailSendCheckI;
224
        };
225
    }
226
227
    /**
228
     * @return \Closure
229
     */
230 3
    private function findOldEmailReceiveOldCallback()
231
    {
232
        return function (EmailSendReceive $emailSendCheckItem) {
233 3
            return $emailSendCheckItem->getSentAt()->getTimestamp() + $this->getReceiveMaxTime() + self::COLLECTION_KEEP_TIME - time() <= 0;
234 3
        };
235
    }
236
237
    /**
238
     * @return \Closure
239
     */
240
    private function findEmailForReceiveCheckCallback()
241
    {
242 6
        return function (EmailSendReceive $emailSendCheckItem) {
243 6
            return $emailSendCheckItem->getStatus() == EmailSendReceive::STATUS_SANDED
244 6
            || $emailSendCheckItem->getStatus() == EmailSendReceive::STATUS_RECEIVED_ERROR;
245 6
        };
246
    }
247
}
248