Completed
Pull Request — master (#42)
by Frederik
02:26
created

Client::__construct()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 3

Importance

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