Completed
Pull Request — master (#42)
by Frederik
03:39
created

Client::__construct()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 21
c 0
b 0
f 0
ccs 0
cts 17
cp 0
rs 9.3142
cc 3
eloc 12
nc 2
nop 3
crap 12
1
<?php
2
declare(strict_types=1);
3
4
namespace Genkgo\Mail\Protocol\Imap;
5
6
use Genkgo\Mail\Protocol\AppendCrlfConnection;
7
use Genkgo\Mail\Protocol\ConnectionInterface;
8
use Genkgo\Mail\Protocol\Imap\Negotiation\ReceiveWelcomeNegotiation;
9
use Genkgo\Mail\Protocol\Imap\Response\AggregateResponse;
10
11
/**
12
 * Class Client
13
 * @package Genkgo\Mail\Protocol\Imap
14
 */
15
final class Client
16
{
17
    /**
18
     *
19
     */
20
    public CONST AUTH_NONE = 0;
21
    /**
22
     *
23
     */
24
    public CONST AUTH_PLAIN = 1;
25
    /**
26
     *
27
     */
28
    public CONST AUTH_AUTO = 3;
29
    /**
30
     * @var ConnectionInterface
31
     */
32
    private $connection;
33
    /**
34
     * @var NegotiationInterface[]
35
     */
36
    private $negotiators = [];
37
    /**
38
     * @var TagFactoryInterface
39
     */
40
    private $tagFactory;
41
42
    /**
43
     * Client constructor.
44
     * @param ConnectionInterface $connection
45
     * @param TagFactoryInterface $tagFactory
46
     * @param iterable $negotiators
47
     */
48
    public function __construct(
49
        ConnectionInterface $connection,
50
        TagFactoryInterface $tagFactory,
51
        iterable $negotiators = []
52
    ) {
53
        $this->connection = new AppendCrlfConnection($connection);
54
55
        $this->addNegotiator(new ReceiveWelcomeNegotiation($this->connection));
56
57
        foreach ($negotiators as $negotiator) {
58
            $this->addNegotiator($negotiator);
59
        }
60
61
        $this->connection->addListener('connect', function () {
62
            foreach ($this->negotiators as $negotiator) {
63
                $negotiator->negotiate($this);
64
            }
65
        });
66
67
        $this->tagFactory = $tagFactory;
68
    }
69
70
    /**
71
     * @param NegotiationInterface $negotiation
72
     */
73
    private function addNegotiator(NegotiationInterface $negotiation)
74
    {
75
        $this->negotiators[] = $negotiation;
76
    }
77
78
    /**
79
     * @param RequestInterface $request
80
     * @return AggregateResponse
81
     */
82
    public function emit(RequestInterface $request): AggregateResponse
83
    {
84
        $stream = $request->toStream();
85
        $stream->rewind();
86
87
        $bytes = '';
88
        while (!$stream->eof()) {
89
            $bytes .= $stream->read(1000);
90
91
            $index = 0;
92
            while (isset($bytes[$index])) {
93
                if ($bytes[$index] === "\r" && isset($bytes[$index + 1]) && $bytes[$index + 1] === "\n") {
94
                    $line = substr($bytes, 0, $index);
95
                    $bytes = substr($bytes, $index + 2);
96
                    $index = -1;
97
98
                    $this->connection->send($line);
99
                }
100
101
                $index++;
102
            }
103
        }
104
105
        $this->connection->send($bytes);
106
107
        $response = new AggregateResponse($request);
108
109
        while (!$response->hasCompleted()) {
110
            $response = $response->withLine($this->connection->receive());
111
        }
112
113
        return $response;
114
    }
115
116
    /**
117
     * @return Tag
118
     */
119
    public function newTag(): Tag
120
    {
121
        return $this->tagFactory->newTag();
122
    }
123
124
125
}