Completed
Push — master ( b425fd...816779 )
by Frederik
02:01
created

ClientFactory::newClient()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 27
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 27
rs 8.8571
ccs 16
cts 16
cp 1
cc 2
eloc 17
nc 2
nop 0
crap 2
1
<?php
2
declare(strict_types=1);
3
4
namespace Genkgo\Mail\Protocol\Smtp;
5
6
use Genkgo\Mail\Protocol\ConnectionInterface;
7
use Genkgo\Mail\Protocol\PlainTcpConnection;
8
use Genkgo\Mail\Protocol\AutomaticConnection;
9
use Genkgo\Mail\Protocol\SecureConnectionOptions;
10
use Genkgo\Mail\Protocol\Smtp\Negotiation\AuthNegotiation;
11
use Genkgo\Mail\Protocol\Smtp\Negotiation\ConnectionNegotiation;
12
use Genkgo\Mail\Protocol\SslConnection;
13
use Genkgo\Mail\Protocol\TlsConnection;
14
15
/**
16
 * Class ClientFactory
17
 * @package Genkgo\Mail\Protocol\Smtp
18
 */
19
final class ClientFactory
20
{
21
    /**
22
     *
23
     */
24
    private CONST AUTH_ENUM = [Client::AUTH_NONE, Client::AUTH_PLAIN, Client::AUTH_LOGIN, Client::AUTH_AUTO];
25
    /**
26
     * @var ConnectionInterface
27
     */
28
    private $connection;
29
    /**
30
     * @var string
31
     */
32
    private $password = '';
33
    /**
34
     * @var float
35
     */
36
    private $timeout = 1;
37
    /**
38
     * @var string
39
     */
40
    private $username = '';
41
    /**
42
     * @var string
43
     */
44
    private $ehlo = '127.0.0.1';
45
    /**
46
     * @var int
47
     */
48
    private $authMethod = Client::AUTH_NONE;
49
    /**
50
     * @var bool
51
     */
52
    private $insecureAllowed = false;
53
    /**
54
     * @var string
55
     */
56
    private $reconnectAfter = 'PT300S';
57
58
    /**
59
     * ClientFactory constructor.
60
     * @param ConnectionInterface $connection
61
     */
62 8
    public function __construct(ConnectionInterface $connection)
63
    {
64 8
        $this->connection = $connection;
65 8
    }
66
67
    /**
68
     * @param float $connectionTimeout
69
     * @return ClientFactory
70
     */
71 1
    public function withTimeout(float $connectionTimeout): ClientFactory
72
    {
73 1
        $clone = clone $this;
74 1
        $clone->timeout = $connectionTimeout;
75 1
        return $clone;
76
    }
77
78
    /**
79
     * @param int $method
80
     * @param string $password
81
     * @param string $username
82
     * @return ClientFactory
83
     */
84 3
    public function withAuthentication(int $method, string $username, string $password): ClientFactory
85
    {
86 3
        if (!in_array($method, self::AUTH_ENUM)) {
87 1
            throw new \InvalidArgumentException('Invalid authentication method');
88
        }
89
90 2
        $clone = clone $this;
91 2
        $clone->authMethod = $method;
92 2
        $clone->username = $username;
93 2
        $clone->password = $password;
94 2
        return $clone;
95
    }
96
97
    /**
98
     * @param string $ehlo
99
     * @return ClientFactory
100
     */
101 3
    public function withEhlo(string $ehlo): ClientFactory
102
    {
103 3
        $clone = clone $this;
104 3
        $clone->ehlo = $ehlo;
105 3
        return $clone;
106
    }
107
108
    /**
109
     * @return ClientFactory
110
     */
111
    public function withAllowInsecure(): ClientFactory
112
    {
113
        $clone = clone $this;
114
        $clone->insecureAllowed = true;
115
        return $clone;
116
    }
117
118
    /**
119
     * @return Client
120
     */
121 6
    public function newClient(): Client
122
    {
123
        $negotiators = [
124 6
            new ConnectionNegotiation(
125 6
                $this->connection,
126 6
                $this->ehlo,
127 6
                $this->insecureAllowed
128
            )
129
        ];
130
131 6
        if ($this->authMethod !== Client::AUTH_NONE) {
132 2
            $negotiators[] = new AuthNegotiation(
133 2
                $this->ehlo,
134 2
                $this->authMethod,
135 2
                $this->username,
136 2
                $this->password
137
            );
138
        }
139
140 6
        return new Client(
141 6
            new AutomaticConnection(
142 6
                $this->connection,
143 6
                new \DateInterval($this->reconnectAfter)
144
            ),
145 6
            $negotiators
146
        );
147
    }
148
149
    /**
150
     * @param string $dataSourceName
151
     * @return ClientFactory
152
     */
153 6
    public static function fromString(string $dataSourceName):ClientFactory
154
    {
155 6
        $components = parse_url($dataSourceName);
156 6
        if (!isset($components['scheme']) || !isset($components['host'])) {
157 1
            throw new \InvalidArgumentException('Scheme and host are required');
158
        }
159
160 5
        $allowInsecure = false;
161 5
        switch ($components['scheme']) {
162 5
            case 'smtp+tls':
163 1
                $connection = new TlsConnection(
164 1
                    $components['host'],
165 1
                    $components['port'] ?? 465,
166 1
                    new SecureConnectionOptions()
167
                );
168 1
                break;
169 4
            case 'smtp+ssl':
170 1
                $connection = new SslConnection(
171 1
                    $components['host'],
172 1
                    $components['port'] ?? 465,
173 1
                    new SecureConnectionOptions()
174
                );
175 1
                break;
176 3
            case 'smtp+plain':
177 1
                $allowInsecure = true;
178 1
                $connection = new PlainTcpConnection(
179 1
                    $components['host'],
180 1
                    $components['port'] ?? 25
181
                );
182 1
                break;
183 2
            case 'smtp':
184 1
                $connection = new PlainTcpConnection(
185 1
                    $components['host'],
186 1
                    $components['port'] ?? 587
187
                );
188 1
                break;
189
            default:
190 1
                throw new \InvalidArgumentException(
191 1
                    'Use smtp:// smtp+tls:// smtp+ssl:// smtp+plain://'
192
                );
193
        }
194
195 4
        $factory = new self($connection);
196 4
        if ($allowInsecure) {
197 1
            $factory->insecureAllowed = true;
198
        }
199
200 4
        if (isset($components['user']) && isset($components['pass'])) {
201 1
            $factory->authMethod = Client::AUTH_AUTO;
202 1
            $factory->username = urldecode($components['user']);
203 1
            $factory->password = urldecode($components['pass']);
204
        }
205
206 4
        if (isset($components['query'])) {
207 1
            parse_str($components['query'], $query);
208
209 1
            if (isset($query['ehlo'])) {
210 1
                $factory->ehlo = $query['ehlo'];
211
            }
212
213 1
            if (isset($query['timeout'])) {
214 1
                $factory->timeout = (float)$query['timeout'];
215
            }
216
217 1
            if (isset($query['reconnectAfter'])) {
218 1
                $factory->reconnectAfter = $query['reconnectAfter'];
219
            }
220
        }
221
222 4
        return $factory;
223
    }
224
}
225