Completed
Pull Request — master (#64)
by Frederik
03:38 queued 01:09
created

EnvelopeFactory::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Genkgo\Mail\Transport;
5
6
use Genkgo\Mail\AddressList;
7
use Genkgo\Mail\EmailAddress;
8
use Genkgo\Mail\Exception\EnvelopeException;
9
use Genkgo\Mail\MessageInterface;
10
11
final class EnvelopeFactory
12
{
13
    /**
14
     * @var \Closure
15
     */
16
    private $callback;
17
18
    /**
19
     * @var EmailAddress
20
     */
21
    private $fallback;
22
    
23 15
    private function __construct()
24
    {
25 15
    }
26
27
    /**
28
     * @param EmailAddress $emailAddress
29
     * @return EnvelopeFactory
30
     */
31 3
    public function withFallback(EmailAddress $emailAddress): EnvelopeFactory
32
    {
33 3
        $clone = clone $this;
34 3
        $clone->fallback = $emailAddress;
35 3
        return $clone;
36
    }
37
38
    /**
39
     * @param MessageInterface $message
40
     * @return EmailAddress
41
     * @throws EnvelopeException
42
     */
43 13
    public function make(MessageInterface $message): EmailAddress
44
    {
45
        try {
46 13
            return $this->callback->call($this, $message);
47 4
        } catch (EnvelopeException $e) {
48 3
            if ($this->fallback === null) {
49 1
                throw $e;
50
            }
51
        }
52
53 2
        return $this->fallback;
54
    }
55
56
    /**
57
     * @param MessageInterface $message
58
     * @return EmailAddress
59
     * @throws EnvelopeException
60
     */
61 9
    private function extractHeader(MessageInterface $message): EmailAddress
62
    {
63 9
        foreach (['sender', 'from'] as $header) {
64 9
            if ($message->hasHeader($header)) {
65
                try {
66 7
                    return $this->extractFromAddressListHeader($message, $header);
67 1
                } catch (\OutOfRangeException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
68
                }
69
            }
70
        }
71
72 2
        throw new EnvelopeException('Cannot extract envelope from headers');
73
    }
74
75
    /**
76
     * @param MessageInterface $message
77
     * @param string $headerName
78
     * @return EmailAddress
79
     */
80 7
    private function extractFromAddressListHeader(MessageInterface $message, string $headerName): EmailAddress
81
    {
82 7
        $headers = $message->getHeader($headerName);
83 7
        if (!\is_array($headers)) {
84
            $headers = \iterator_to_array($headers);
85
        }
86
87 7
        if (isset($headers[0])) {
88 7
            return AddressList::fromString((string)$headers[0]->getValue()->getRaw())->first()->getAddress();
89
        }
90
91
        throw new \UnexpectedValueException('Expecting at least one from address in header ' . $headerName);
92
    }
93
94
    /**
95
     * @return EnvelopeFactory
96
     */
97 11
    public static function useExtractedHeader(): EnvelopeFactory
98
    {
99 11
        $options = new self();
100 11
        $options->callback = \Closure::fromCallable([$options, 'extractHeader']);
101 11
        return $options;
102
    }
103
104
    /**
105
     * @param EmailAddress $fixedAddress
106
     * @return EnvelopeFactory
107
     */
108 1
    public static function useFixed(EmailAddress $fixedAddress): EnvelopeFactory
109
    {
110 1
        $options = new self();
111
        $options->callback = function () use ($fixedAddress) {
112 1
            return $fixedAddress;
113
        };
114 1
        return $options;
115
    }
116
117
    /**
118
     * @param \Closure $callback
119
     * @return EnvelopeFactory
120
     */
121 3
    public static function useCallback(\Closure $callback): EnvelopeFactory
122
    {
123 3
        $options = new self();
124 3
        $options->callback = $callback;
125 3
        return $options;
126
    }
127
}
128