Completed
Push — master ( 5840b0...fcc03f )
by Frederik
04:51
created

Server::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 13
ccs 9
cts 9
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 8
nc 1
nop 3
crap 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Genkgo\Mail\Protocol\Smtp;
5
6
use Genkgo\Mail\Exception\ConnectionTimeoutException;
7
use Genkgo\Mail\Exception\UnknownSmtpCommandException;
8
use Genkgo\Mail\Protocol\AppendCrlfConnection;
9
use Genkgo\Mail\Protocol\ConnectionInterface;
10
use Genkgo\Mail\Protocol\ConnectionListenerInterface;
11
use Genkgo\Mail\Protocol\Smtp\Capability\EhloCapability;
12
use Genkgo\Mail\Protocol\Smtp\Capability\QuitCapability;
13
use Genkgo\Mail\Protocol\Smtp\Capability\ResetCapability;
14
use Genkgo\Mail\Protocol\TrimCrlfConnection;
15
16
final class Server
17
{
18
    /**
19
     * @var ConnectionListenerInterface
20
     */
21
    private $listener;
22
    /**
23
     * @var CapabilityInterface[]
24
     */
25
    private $capabilities = [];
26
    /**
27
     * @var string
28
     */
29
    private $serverName;
30
31
    /**
32
     * Client constructor.
33
     * @param ConnectionListenerInterface $connection
34
     * @param array $capabilities
35
     * @param string $serverName
36
     */
37 3
    public function __construct(ConnectionListenerInterface $connection, array $capabilities, string $serverName) {
38 3
        $this->listener = $connection;
39 3
        $this->serverName = $serverName;
40
41 3
        $this->capabilities = array_merge(
0 ignored issues
show
Documentation Bug introduced by
It seems like array_merge($capabilitie...ity\ResetCapability())) of type array is incompatible with the declared type array<integer,object<Gen...p\CapabilityInterface>> of property $capabilities.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
42 3
            $capabilities,
43
            [
44 3
                new EhloCapability($this->serverName, $capabilities),
45 3
                new QuitCapability(),
46 3
                new ResetCapability()
47
            ]
48
        );
49 3
    }
50
51
    /**
52
     *
53
     */
54 3
    public function start(): void
55
    {
56 3
        while ($connection = $this->listener->listen()) {
57 3
            $connection = new TrimCrlfConnection(new AppendCrlfConnection($connection));
58 3
            $connection->send('220 Welcome to Genkgo Mail Server');
59
60
            try {
61 3
                $session = new Session();
62
63 3
                while ($session = $session->withCommand($connection->receive())) {
64
                    try {
65 2
                        $session = $this->handleCommand($connection, $session);
66 1
                    } catch (UnknownSmtpCommandException $e) {
67 1
                        $connection->send('500 unrecognized command');
68
                    }
69
70 2
                    if ($session->getState() === Session::STATE_DISCONNECT) {
71 2
                        break;
72
                    }
73
                }
74 1
            } catch (ConnectionTimeoutException $e) {
75 1
                $connection->send('421 command timeout - closing connection');
76 1
                $connection->disconnect();
77
            }
78
        }
79
    }
80
81
    /**
82
     * @param ConnectionInterface $connection
83
     * @param Session $session
84
     * @return Session
85
     * @throws UnknownSmtpCommandException
86
     */
87 2
    private function handleCommand(ConnectionInterface $connection, Session $session): Session
88
    {
89 2
        $command = $session->getCommand();
90
91 2
        foreach ($this->capabilities as $capability) {
92 2
            $advertised = $capability->advertise();
93 2
            if (substr($command, 0, strlen($advertised)) === $advertised) {
94 2
                return $capability->manifest($connection, $session);
95
            }
96
        }
97
98 1
        throw new UnknownSmtpCommandException('Cannot handle command');
99
    }
100
}