Completed
Pull Request — master (#64)
by Frederik
03:02
created

EnvelopeFactory   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 113
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 97.14%

Importance

Changes 0
Metric Value
wmc 14
lcom 1
cbo 4
dl 0
loc 113
ccs 34
cts 35
cp 0.9714
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A withFallback() 0 6 1
A make() 0 12 3
A extractHeader() 0 13 4
A extractFromAddressListHeader() 0 9 2
A useExtractedHeader() 0 6 1
A useFixed() 0 8 1
A useCallback() 0 6 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 (isset($headers[0])) {
84 7
            return AddressList::fromString((string)$headers[0]->getValue()->getRaw())->first()->getAddress();
85
        }
86
87
        throw new \UnexpectedValueException('Expecting at least one from address in header ' . $headerName);
88
    }
89
90
    /**
91
     * @return EnvelopeFactory
92
     */
93 11
    public static function useExtractedHeader(): EnvelopeFactory
94
    {
95 11
        $options = new self();
96 11
        $options->callback = \Closure::fromCallable([$options, 'extractHeader']);
97 11
        return $options;
98
    }
99
100
    /**
101
     * @param EmailAddress $fixedAddress
102
     * @return EnvelopeFactory
103
     */
104 1
    public static function useFixed(EmailAddress $fixedAddress): EnvelopeFactory
105
    {
106 1
        $options = new self();
107
        $options->callback = function () use ($fixedAddress) {
108 1
            return $fixedAddress;
109
        };
110 1
        return $options;
111
    }
112
113
    /**
114
     * @param \Closure $callback
115
     * @return EnvelopeFactory
116
     */
117 3
    public static function useCallback(\Closure $callback): EnvelopeFactory
118
    {
119 3
        $options = new self();
120 3
        $options->callback = $callback;
121 3
        return $options;
122
    }
123
}
124