Completed
Pull Request — master (#47)
by Frederik
02:58
created

AggregateResponse::__toString()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 8
cts 8
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 7
nc 1
nop 0
crap 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Genkgo\Mail\Protocol\Imap\Response;
5
6
use Genkgo\Mail\Exception\AssertionFailedException;
7
use Genkgo\Mail\Protocol\Imap\ResponseInterface;
8
use Genkgo\Mail\Protocol\Imap\Tag;
9
10
final class AggregateResponse implements \IteratorAggregate
11
{
12
    /**
13
     * @var array|ResponseInterface[]
14
     */
15
    private $lines = [];
16
17
    /**
18
     * @var Tag
19
     */
20
    private $tag;
21
22
    /**
23
     * @param Tag $tag
24
     */
25 30
    public function __construct(Tag $tag)
26
    {
27 30
        $this->tag = $tag;
28 30
    }
29
30
    /**
31
     * @return \Iterator|ResponseInterface[]
32
     */
33 1
    public function getIterator(): \Iterator
34
    {
35 1
        return new \ArrayIterator($this->lines);
36
    }
37
38
    /**
39
     * @return ResponseInterface
40
     */
41 18
    public function first(): ResponseInterface
42
    {
43 18
        if (empty($this->lines)) {
44 1
            throw new \OutOfBoundsException('Cannot return item of empty response');
45
        }
46
47 17
        return \reset($this->lines);
48
    }
49
50
    /**
51
     * @return ResponseInterface
52
     */
53 16
    public function last(): ResponseInterface
54
    {
55 16
        if (empty($this->lines)) {
56 1
            throw new \OutOfBoundsException('Cannot return item of empty response');
57
        }
58
59 15
        return \end($this->lines);
60
    }
61
62
    /**
63
     * @param int $index
64
     * @return ResponseInterface
65
     */
66 2
    public function at(int $index): ResponseInterface
67
    {
68 2
        if (!isset($this->lines[$index])) {
69 1
            throw new \OutOfBoundsException('GenericItem not in response');
70
        }
71
72 1
        return $this->lines[$index];
73
    }
74
75
    /**
76
     * @return bool
77
     */
78 14
    public function hasCompleted(): bool
79
    {
80 14
        if (empty($this->lines)) {
81 14
            return false;
82
        }
83
84 14
        $lastCommand = \end($this->lines);
85
        try {
86 14
            $lastCommand->assertTagged();
87 14
            return true;
88 12
        } catch (AssertionFailedException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
89
        }
90
91
        try {
92 12
            $lastCommand->assertContinuation();
93 5
            return true;
94 10
        } catch (AssertionFailedException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
95
        }
96
97 10
        return false;
98
    }
99
100
    /**
101
     * @param string $line
102
     * @return AggregateResponse
103
     */
104 26
    public function withLine(string $line): AggregateResponse
105
    {
106 26
        $clone = clone $this;
107
108 26
        switch (\substr($line, 0, 2)) {
109 26
            case '+ ':
110 6
                $clone->lines[] = new CommandContinuationRequestResponse(
111 6
                    \substr($line, 2)
112
                );
113 6
                break;
114 25
            case '* ':
115 19
                $clone->lines[] = new UntaggedResponse(
116 19
                    \substr($line, 2)
117
                );
118 19
                break;
119
            default:
120
                try {
121 21
                    $clone->lines[] = new TaggedResponse(
122 21
                        $this->tag,
123 21
                        $this->tag->extractBodyFromLine($line)
124
                    );
125 3
                } catch (\InvalidArgumentException $e) {
126 3
                    if (empty($clone->lines)) {
127 1
                        throw new \UnexpectedValueException(
128 1
                            'Expected line to begin with +, * or tag. Got: ' . $line
129
                        );
130
                    }
131
132 2
                    $keys = \array_keys($clone->lines);
133 2
                    $lastKey = \end($keys);
134 2
                    $clone->lines[$lastKey] = $clone->lines[$lastKey]->withAddedBody($line);
135
                }
136 20
                break;
137
138
        }
139
140 25
        return $clone;
141
    }
142
143
    /**
144
     * @return string
145
     */
146 1
    public function __toString(): string
147
    {
148 1
        return \implode(
149 1
            "\r\n",
150 1
            \array_map(
151 1
                function (ResponseInterface $response) {
152 1
                    return (string)$response;
153 1
                },
154 1
                $this->lines
155
            )
156
        );
157
    }
158
}
159