Passed
Push — master ( 57c539...d81008 )
by Esteban De La Fuente
14:52
created

AbstractMailboxStrategy::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 0
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 2
ccs 0
cts 1
cp 0
crap 2
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Derafu: Biblioteca PHP (Núcleo).
7
 * Copyright (C) Derafu <https://www.derafu.org>
8
 *
9
 * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10
 * bajo los términos de la Licencia Pública General Affero de GNU publicada por
11
 * la Fundación para el Software Libre, ya sea la versión 3 de la Licencia, o
12
 * (a su elección) cualquier versión posterior de la misma.
13
 *
14
 * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15
 * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16
 * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la Licencia Pública
17
 * General Affero de GNU para obtener una información más detallada.
18
 *
19
 * Debería haber recibido una copia de la Licencia Pública General Affero de GNU
20
 * junto a este programa.
21
 *
22
 * En caso contrario, consulte <http://www.gnu.org/licenses/agpl.html>.
23
 */
24
25
namespace Derafu\Lib\Core\Package\Prime\Component\Mail\Abstract;
26
27
use Derafu\Lib\Core\Foundation\Abstract\AbstractStrategy;
28
use Derafu\Lib\Core\Package\Prime\Component\Mail\Contract\PostmanInterface;
29
use Derafu\Lib\Core\Package\Prime\Component\Mail\Contract\ReceiverStrategyInterface;
30
use Derafu\Lib\Core\Package\Prime\Component\Mail\Exception\MailException;
31
use Derafu\Lib\Core\Package\Prime\Component\Mail\Factory\EnvelopeFactory;
32
use Derafu\Lib\Core\Package\Prime\Component\Mail\Support\Mailbox;
33
use Derafu\Lib\Core\Support\Store\Contract\DataContainerInterface;
34
use Exception;
35
36
/**
37
 * Estrategia base para la recepción de correos electrónicos usando un Mailbox.
38
 */
39
abstract class AbstractMailboxStrategy extends AbstractStrategy implements ReceiverStrategyInterface
40
{
41
    /**
42
     * Constructor de la estrategia con sus dependencias.
43
     *
44
     * @param EnvelopeFactory $envelopeFactory
45
     */
46
    public function __construct(protected EnvelopeFactory $envelopeFactory)
47
    {
48
    }
49
50
    /**
51
     * {@inheritDoc}
52
     */
53
    public function receive(PostmanInterface $postman): array
54
    {
55
        $options = $this->resolveOptions($postman->getOptions()->all());
56
57
        $mailbox = $this->createMailbox($options);
58
59
        $criteria = $options->get('transport.search.criteria');
60
        $markAsSeen = $options->get('transport.search.markAsSeen');
61
        $attachmentFilters = $options->get('transport.search.attachmentFilters');
62
63
        try {
64
            // Obtener los ID de los correos según el criterio de búsqueda.
65
            $mailsIds = $mailbox->searchMailbox($criteria);
66
67
            // Obtener cada correo mediante su ID y armar el sobre para el
68
            // cartero. Los correos nunca se marcan acá como leídos. Se procesan
69
            // todos antes de marcarlos como leídos por si algo falla al
70
            // procesar.
71
            foreach ($mailsIds as $mailId) {
72
                $mail = $mailbox->getMail($mailId, markAsSeen: false);
73
                $envelope = $this->envelopeFactory->createFromIncomingMail(
74
                    $mail,
75
                    $attachmentFilters
76
                );
77
                $postman->addEnvelope($envelope);
78
            }
79
80
            // Marcar los mensajes como leídos si así se solicitó.
81
            if ($markAsSeen) {
82
                $mailbox->markMailsAsRead($mailsIds);
83
            }
84
        } catch (Exception $e) {
85
            throw new MailException(
86
                message: sprintf(
87
                    'Ocurrió un error al recibir los correos: %s',
88
                    $e->getMessage()
89
                ),
90
                previous: $e
91
            );
92
        }
93
94
        return $postman->getEnvelopes();
95
    }
96
97
    /**
98
     * Crea una casilla de correo.
99
     *
100
     * @param DataContainerInterface $options Opciones de la casilla de correo.
101
     * @return Mailbox
102
     */
103
    protected function createMailbox(DataContainerInterface $options): Mailbox
104
    {
105
        $dsn = $this->resolveDsn($options);
106
        $username = $options->get('transport.username');
107
        $password = $options->get('transport.password');
108
109
        $mailbox = new Mailbox($dsn, $username, $password);
110
111
        $this->resolveEndpoint($options);
112
113
        return $mailbox;
114
    }
115
116
    /**
117
     * Resuelve el DSN para la casilla de correo.
118
     *
119
     * @param DataContainerInterface $options Opciones de la casilla de correo.
120
     * @return string DSN.
121
     */
122
    protected function resolveDsn(DataContainerInterface $options): string
123
    {
124
        $transportOptions = $options->get('transport');
125
126
        if (empty($transportOptions['dsn'])) {
127
            throw new MailException('No está definido el DSN para el Mailbox.');
128
        }
129
130
        return $transportOptions['dsn'];
131
    }
132
133
    /**
134
     * Resuelve el endpoint personalizado.
135
     *
136
     * @param DataContainerInterface $options Opciones de la casilla de correo.
137
     * @return string Endpoint personalizado.
138
     */
139
    protected function resolveEndpoint(DataContainerInterface $options): string
140
    {
141
        $transportOptions = $options->get('transport');
142
143
        if (!empty($transportOptions['endpoint'])) {
144
            return $transportOptions['endpoint'];
145
        }
146
147
        $endpoint = $this->resolveDsn($options);
148
149
        $options->set('transport.endpoint', $endpoint);
150
151
        return $endpoint;
152
    }
153
}
154