Completed
Push — master ( fafa6b...d42f0d )
by Frederik
03:02
created

ClientFactory::fromString()   C

Complexity

Conditions 13
Paths 195

Size

Total Lines 70
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 44
CRAP Score 13

Importance

Changes 0
Metric Value
dl 0
loc 70
ccs 44
cts 44
cp 1
rs 5.1836
c 0
b 0
f 0
cc 13
eloc 46
nc 195
nop 1
crap 13

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\CryptoConstant;
8
use Genkgo\Mail\Protocol\PlainTcpConnection;
9
use Genkgo\Mail\Protocol\AutomaticConnection;
10
use Genkgo\Mail\Protocol\SecureConnectionOptions;
11
use Genkgo\Mail\Protocol\Smtp\Negotiation\AuthNegotiation;
12
use Genkgo\Mail\Protocol\Smtp\Negotiation\ForceTlsUpgradeNegotiation;
13
use Genkgo\Mail\Protocol\Smtp\Negotiation\TryTlsUpgradeNegotiation;
14
use Genkgo\Mail\Protocol\SecureConnection;
15
16
/**
17
 * Class ClientFactory
18
 * @package Genkgo\Mail\Protocol\Smtp
19
 */
20
final class ClientFactory
21
{
22
    /**
23
     *
24
     */
25
    private CONST AUTH_ENUM = [Client::AUTH_NONE, Client::AUTH_PLAIN, Client::AUTH_LOGIN, Client::AUTH_AUTO];
26
    /**
27
     * @var ConnectionInterface
28
     */
29
    private $connection;
30
    /**
31
     * @var string
32
     */
33
    private $password = '';
34
    /**
35
     * @var float
36
     */
37
    private $timeout = 1;
38
    /**
39
     * @var string
40
     */
41
    private $username = '';
42
    /**
43
     * @var string
44
     */
45
    private $ehlo = '127.0.0.1';
46
    /**
47
     * @var int
48
     */
49
    private $authMethod = Client::AUTH_NONE;
50
    /**
51
     * @var bool
52
     */
53
    private $insecureConnectionAllowed = false;
54
    /**
55
     * @var string
56
     */
57
    private $reconnectAfter = 'PT300S';
58
    /**
59
     * @var int
60
     */
61
    private $startTls;
62
63
    /**
64
     * ClientFactory constructor.
65
     * @param ConnectionInterface $connection
66
     */
67 9
    public function __construct(ConnectionInterface $connection)
68
    {
69 9
        $this->connection = $connection;
70 9
        $this->startTls = CryptoConstant::getDefaultMethod(PHP_VERSION);
71 9
    }
72
73
    /**
74
     * @param float $connectionTimeout
75
     * @return ClientFactory
76
     */
77 1
    public function withTimeout(float $connectionTimeout): ClientFactory
78
    {
79 1
        $clone = clone $this;
80 1
        $clone->timeout = $connectionTimeout;
81 1
        return $clone;
82
    }
83
84
    /**
85
     * @param int $method
86
     * @param string $password
87
     * @param string $username
88
     * @return ClientFactory
89
     */
90 3
    public function withAuthentication(int $method, string $username, string $password): ClientFactory
91
    {
92 3
        if (!in_array($method, self::AUTH_ENUM)) {
93 1
            throw new \InvalidArgumentException('Invalid authentication method');
94
        }
95
96 2
        $clone = clone $this;
97 2
        $clone->authMethod = $method;
98 2
        $clone->username = $username;
99 2
        $clone->password = $password;
100 2
        return $clone;
101
    }
102
103
    /**
104
     * @param string $ehlo
105
     * @return ClientFactory
106
     */
107 4
    public function withEhlo(string $ehlo): ClientFactory
108
    {
109 4
        $clone = clone $this;
110 4
        $clone->ehlo = $ehlo;
111 4
        return $clone;
112
    }
113
114
    /**
115
     * @return ClientFactory
116
     */
117 2
    public function withInsecureConnectionAllowed(): ClientFactory
118
    {
119 2
        $clone = clone $this;
120 2
        $clone->insecureConnectionAllowed = true;
121 2
        return $clone;
122
    }
123
124
    /**
125
     * @param int $crypto
126
     * @return ClientFactory
127
     */
128
    public function withStartTls(int $crypto): ClientFactory
129
    {
130
        $clone = clone $this;
131
        $clone->startTls = $crypto;
132
        return $clone;
133
    }
134
135
    /**
136
     * @return ClientFactory
137
     */
138 1
    public function withoutStartTls(): ClientFactory
139
    {
140 1
        $clone = clone $this;
141 1
        $clone->startTls = 0;
142 1
        return $clone;
143
    }
144
145
    /**
146
     * @return Client
147
     */
148 7
    public function newClient(): Client
149
    {
150 7
        $negotiators = [];
151
152 7
        if ($this->startTls !== 0) {
153 6
            if ($this->insecureConnectionAllowed) {
154 1
                $negotiators[] = new TryTlsUpgradeNegotiation(
155 1
                    $this->connection,
156 1
                    $this->ehlo,
157 1
                    $this->startTls
158
                );
159
            } else {
160 5
                $negotiators[] = new ForceTlsUpgradeNegotiation(
161 5
                    $this->connection,
162 5
                    $this->ehlo,
163 5
                    $this->startTls
164
                );
165
            }
166
        }
167
168 7
        if ($this->authMethod !== Client::AUTH_NONE) {
169 2
            $negotiators[] = new AuthNegotiation(
170 2
                $this->ehlo,
171 2
                $this->authMethod,
172 2
                $this->username,
173 2
                $this->password
174
            );
175
        }
176
177 7
        return new Client(
178 7
            new AutomaticConnection(
179 7
                $this->connection,
180 7
                new \DateInterval($this->reconnectAfter)
181
            ),
182 7
            $negotiators
183
        );
184
    }
185
186
    /**
187
     * @param string $dataSourceName
188
     * @return ClientFactory
189
     */
190 6
    public static function fromString(string $dataSourceName):ClientFactory
191
    {
192 6
        $components = parse_url($dataSourceName);
193 6
        if (!isset($components['scheme']) || !isset($components['host'])) {
194 1
            throw new \InvalidArgumentException('Scheme and host are required');
195
        }
196
197 5
        if (isset($components['query'])) {
198 2
            parse_str($components['query'], $query);
199
        } else {
200 3
            $query = [];
201
        }
202
203 5
        $insecureConnectionAllowed = false;
204 5
        switch ($components['scheme']) {
205 5
            case 'smtp':
206 1
                $connection = new PlainTcpConnection(
207 1
                    $components['host'],
208 1
                    $components['port'] ?? 587
209
                );
210 1
                break;
211 4
            case 'smtps':
212 2
                $connection = new SecureConnection(
213 2
                    $components['host'],
214 2
                    $components['port'] ?? 465,
215 2
                    new SecureConnectionOptions(
216 2
                        (int)($query['crypto'] ?? CryptoConstant::getDefaultMethod(PHP_VERSION))
217
                    )
218
                );
219 2
                break;
220 2
            case 'smtp-starttls':
221 1
                $insecureConnectionAllowed = true;
222 1
                $connection = new PlainTcpConnection(
223 1
                    $components['host'],
224 1
                    $components['port'] ?? 25
225
                );
226 1
                break;
227
            default:
228 1
                throw new \InvalidArgumentException(
229 1
                    'Use smtp:// smtps:// or smtp-starttls://'
230
                );
231
        }
232
233 4
        $factory = new self($connection);
234 4
        $factory->insecureConnectionAllowed = $insecureConnectionAllowed;
235
236 4
        if (isset($components['user']) && isset($components['pass'])) {
237 1
            $factory->authMethod = Client::AUTH_AUTO;
238 1
            $factory->username = urldecode($components['user']);
239 1
            $factory->password = urldecode($components['pass']);
240
        }
241
242 4
        if (isset($query['ehlo'])) {
243 1
            $factory->ehlo = $query['ehlo'];
244
        }
245
246 4
        if (isset($query['timeout'])) {
247 1
            $factory->timeout = (float)$query['timeout'];
248
        }
249
250 4
        if (isset($query['reconnectAfter'])) {
251 1
            $factory->reconnectAfter = $query['reconnectAfter'];
252
        }
253
254 4
        if (isset($query['crypto'])) {
255 1
            $factory->startTls = (int)$query['crypto'];
256
        }
257
258 4
        return $factory;
259
    }
260
}
261