Completed
Pull Request — master (#42)
by Frederik
04:15 queued 01:07
created

Client::addNegotiator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

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