Completed
Push — master ( 789708...940c54 )
by Frederik
02:07
created

AddressList::count()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Genkgo\Mail;
5
6
/**
7
 * Class AddressList
8
 * @package Genkgo\Mail
9
 */
10
final class AddressList implements \Countable
11
{
12
    /**
13
     *
14
     */
15
    private CONST PARSE_START = 1;
16
    /**
17
     *
18
     */
19
    private CONST PARSE_QUOTE = 2;
20
21
    /**
22
     * @var array|Address[]
23
     */
24
    private $addresses = [];
25
26
    /**
27
     * To constructor.
28
     * @param array|Address[] $recipients
29
     */
30 23
    public function __construct(array $recipients = [])
31
    {
32 23
        foreach ($recipients as $recipient) {
33 22
            if ($recipient instanceof Address === false) {
34
                throw new \InvalidArgumentException('Recipient must be EmailAddressAndName object');
35
            }
36
37 22
            $this->addresses[] = $recipient;
38
        }
39 23
    }
40
41
    /**
42
     * @param Address $address
43
     * @return AddressList
44
     */
45 2
    public function withAddress(Address $address): AddressList
46
    {
47 2
        $clone = clone $this;
48 2
        $clone->addresses[] = $address;
49 2
        return $clone;
50
    }
51
52
    /**
53
     * @param Address $address
54
     * @return AddressList
55
     */
56 2
    public function withoutAddress(Address $address): AddressList
57
    {
58 2
        $clone = clone $this;
59
60 2
        foreach ($this->addresses as $key => $mayRemoveAddress) {
61 2
            if ($mayRemoveAddress->equals($address)) {
62 2
                unset($clone->addresses[$key]);
63
            }
64
        }
65
66 2
        return $clone;
67
    }
68
69
    /**
70
     * @return int
71
     */
72 8
    public function count(): int
73
    {
74 8
        return count($this->addresses);
75
    }
76
77
    /**
78
     * @return string
79
     */
80 14
    public function __toString(): string
81
    {
82 14
        return implode(
83 14
            ',',
84 14
            array_map(
85 14
                function (Address $addressAndName) {
86 13
                    return (string) $addressAndName;
87 14
                },
88 14
                $this->addresses
89
            )
90
        );
91
    }
92
93
    /**
94
     * @param string $addressListAsString
95
     * @return AddressList
96
     */
97 9
    public static function fromString(string $addressListAsString)
98
    {
99 9
        $addressListAsString = trim($addressListAsString);
100 9
        if ($addressListAsString === '') {
101 1
            return new self([]);
102
        }
103
104 8
        $addresses = [];
105 8
        $length = strlen($addressListAsString) - 1;
106 8
        $n = -1;
107 8
        $state = self::PARSE_START;
108 8
        $escapeNext = false;
109 8
        $sequence = '';
110
111 8
        while ($n < $length) {
112 8
            $n++;
113
114 8
            $char = $addressListAsString[$n];
115
116 8
            $sequence .= $char;
117
118 8
            if ($char === '\\') {
119 2
                $escapeNext = true;
120 2
                continue;
121
            }
122
123 8
            if ($escapeNext) {
124 2
                $escapeNext = false;
125 2
                continue;
126
            }
127
128
            switch ($state) {
129 8
                case self::PARSE_QUOTE:
130 5
                    if ($char === '"') {
131 4
                        $state = self::PARSE_START;
132
                    }
133
134 5
                    break;
135
                default:
136 8
                    if ($char === '"') {
137 5
                        $state = self::PARSE_QUOTE;
138
                    }
139
140 8
                    if ($char === ',') {
141 2
                        $addresses[] = Address::fromString(substr($sequence, 0, -1));
142 2
                        $sequence = '';
143 2
                        $state = self::PARSE_START;
144
                    }
145 8
                    break;
146
            }
147
        }
148
149 8
        $addresses[] = Address::fromString($sequence);
150
151 7
        return new self($addresses);
152
    }
153
}