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

AggregateResponse   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 130
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 17
lcom 1
cbo 5
dl 0
loc 130
c 0
b 0
f 0
ccs 0
cts 77
cp 0
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getIterator() 0 4 1
A first() 0 8 2
A last() 0 8 2
A at() 0 8 2
A hasCompleted() 0 21 4
B withLine() 0 34 5
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\RequestInterface;
8
use Genkgo\Mail\Protocol\Imap\ResponseInterface;
9
10
/**
11
 * Class Response
12
 * @package Genkgo\Mail\Protocol\Smtp
13
 */
14
final class AggregateResponse implements \IteratorAggregate
15
{
16
    /**
17
     * @var array|ResponseInterface[]
18
     */
19
    private $lines = [];
20
21
    /**
22
     * @var RequestInterface
23
     */
24
    private $request;
25
26
    /**
27
     * Reply constructor.
28
     * @param RequestInterface $request
29
     */
30
    public function __construct(RequestInterface $request)
31
    {
32
        $this->request = $request;
33
    }
34
35
    /**
36
     * @return \Iterator|ResponseInterface[]
37
     */
38
    public function getIterator(): \Iterator
39
    {
40
        return new \ArrayIterator($this->lines);
41
    }
42
43
    /**
44
     * @return ResponseInterface
45
     */
46
    public function first(): ResponseInterface
47
    {
48
        if (empty($this->lines)) {
49
            throw new \UnexpectedValueException('Cannot return item of empty response');
50
        }
51
52
        return reset($this->lines);
53
    }
54
55
    /**
56
     * @return ResponseInterface
57
     */
58
    public function last(): ResponseInterface
59
    {
60
        if (empty($this->lines)) {
61
            throw new \UnexpectedValueException('Cannot return item of empty response');
62
        }
63
64
        return end($this->lines);
65
    }
66
67
    /**
68
     * @param int $index
69
     * @return ResponseInterface
70
     */
71
    public function at(int $index): ResponseInterface
72
    {
73
        if (!isset($this->lines[$index])) {
74
            throw new \UnexpectedValueException('Item not in response');
75
        }
76
77
        return $this->lines[$index];
78
    }
79
80
    /**
81
     * @return bool
82
     */
83
    public function hasCompleted(): bool
84
    {
85
        if (empty($this->lines)) {
86
            return false;
87
        }
88
89
        $lastCommand = end($this->lines);
90
        try {
91
            $lastCommand->assertTagged();
92
            return true;
93
        } catch (AssertionFailedException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
94
        }
95
96
        try {
97
            $lastCommand->assertContinuation();
98
            return true;
99
        } catch (AssertionFailedException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
100
        }
101
102
        return false;
103
    }
104
105
    /**
106
     * @param string $line
107
     * @return AggregateResponse
108
     */
109
    public function withLine(string $line): AggregateResponse
110
    {
111
        $clone = clone $this;
112
113
        if (!isset($line[0])) {
114
            throw new \InvalidArgumentException('Empty line');
115
        }
116
117
        switch (substr($line, 0, 2)) {
118
            case '+ ':
119
                $clone->lines[] = new CommandContinuationRequestResponse(
120
                    substr($line, 2)
121
                );
122
                break;
123
            case '* ':
124
                $clone->lines[] = new UntaggedResponse(
125
                    substr($line, 2)
126
                );
127
                break;
128
            default:
129
                try {
130
                    $tag = $this->request->getTag();
131
                    $clone->lines[] = new TaggedResponse($tag, $tag->extractBodyFromLine($line));
132
                } catch (\InvalidArgumentException | \BadMethodCallException $e) {
133
                    $keys = array_keys($clone->lines);
134
                    $lastKey = end($keys);
135
                    $clone->lines[$lastKey] = $clone->lines[$lastKey]->withBody($line);
136
                }
137
                break;
138
139
        }
140
141
        return $clone;
142
    }
143
}
144