Passed
Pull Request — master (#40)
by Christian
07:29
created

DNSRecordCollection   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 157
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 40
dl 0
loc 157
c 1
b 0
f 0
rs 10
wmc 27

22 Methods

Rating   Name   Duplication   Size   Complexity  
A withUniqueValues() 0 5 1
A valid() 0 3 1
A serialize() 0 3 1
A toArray() 0 3 1
A isEmpty() 0 3 1
A filteredByType() 0 4 1
A current() 0 3 1
A next() 0 3 1
A rewind() 0 3 1
A offsetGet() 0 3 1
A offsetExists() 0 3 1
A offsetSet() 0 7 2
A has() 0 9 3
A pickFirst() 0 5 1
A jsonSerialize() 0 3 1
A withUniqueValuesExcluded() 0 7 1
A offsetUnset() 0 3 1
A __construct() 0 3 1
A key() 0 3 1
A filterValues() 0 13 3
A unserialize() 0 3 1
A count() 0 3 1
1
<?php
2
3
namespace RemotelyLiving\PHPDNS\Entities;
4
5
use ArrayAccess;
6
use ArrayIterator;
7
use Countable;
8
use Iterator;
9
use RemotelyLiving\PHPDNS\Entities\Interfaces\Arrayable;
10
use RemotelyLiving\PHPDNS\Entities\Interfaces\DNSRecordInterface;
11
use RemotelyLiving\PHPDNS\Entities\Interfaces\Serializable;
12
use RemotelyLiving\PHPDNS\Exceptions\InvalidArgumentException;
13
14
use function array_filter;
15
use function array_shift;
16
use function serialize;
17
use function unserialize;
18
19
final class DNSRecordCollection extends EntityAbstract implements
20
    ArrayAccess,
21
    Iterator,
22
    Countable,
23
    Arrayable,
24
    Serializable
25
{
26
    private ArrayIterator $records;
27
28
    public function __construct(DNSRecordInterface ...$records)
29
    {
30
        $this->records = new ArrayIterator($records);
31
    }
32
33
    public function toArray(): array
34
    {
35
        return $this->records->getArrayCopy();
36
    }
37
38
    public function pickFirst(): ?DNSRecordInterface
39
    {
40
        $copy = $this->records->getArrayCopy();
41
42
        return array_shift($copy);
43
    }
44
45
    public function filteredByType(DNSRecordType $type): self
46
    {
47
        $fn = fn(DNSRecordInterface $record) => $record->getType()->equals($type);
48
        return new self(...array_filter($this->records->getArrayCopy(), $fn));
49
    }
50
51
    public function has(DNSRecordInterface $lookupRecord): bool
52
    {
53
        foreach ($this->records->getArrayCopy() as $record) {
54
            if ($lookupRecord->equals($record)) {
55
                return true;
56
            }
57
        }
58
59
        return false;
60
    }
61
62
    public function current(): ?DNSRecordInterface
63
    {
64
        return $this->records->current();
65
    }
66
67
    public function next(): void
68
    {
69
        $this->records->next();
70
    }
71
72
    /**
73
     * @return int|string|bool
74
     */
75
    public function key()
76
    {
77
        return $this->records->key();
78
    }
79
80
    public function valid(): bool
81
    {
82
        return $this->records->valid();
83
    }
84
85
    public function rewind(): void
86
    {
87
        $this->records->rewind();
88
    }
89
90
    public function offsetExists($offset): bool
91
    {
92
        return $this->records->offsetExists($offset);
93
    }
94
95
    public function offsetGet($offset): DNSRecordInterface
96
    {
97
        return $this->records->offsetGet($offset);
98
    }
99
100
    /**
101
     * @throws \RemotelyLiving\PHPDNS\Exceptions\InvalidArgumentException
102
     */
103
    public function offsetSet($offset, $value): void
104
    {
105
        if (!$value instanceof DNSRecordInterface) {
106
            throw new InvalidArgumentException('Invalid value');
107
        }
108
109
        $this->records->offsetSet($offset, /** @scrutinizer ignore-type */ $value);
110
    }
111
112
    public function offsetUnset($offset): void
113
    {
114
        $this->records->offsetUnset($offset);
115
    }
116
117
    public function count(): int
118
    {
119
        return $this->records->count();
120
    }
121
122
    public function isEmpty(): bool
123
    {
124
        return $this->count() === 0;
125
    }
126
127
    public function serialize(): string
128
    {
129
        return serialize($this->records->getArrayCopy());
130
    }
131
132
    /**
133
     * @param string $serialized
134
     */
135
    public function unserialize($serialized): void
136
    {
137
        $this->records = new ArrayIterator(unserialize($serialized));
138
    }
139
140
    public function jsonSerialize(): array
141
    {
142
        return $this->toArray();
143
    }
144
145
    public function withUniqueValuesExcluded(): self
146
    {
147
        return $this->filterValues(
148
            fn(DNSRecordInterface $candidateRecord, DNSRecordCollection $remaining): bool => $remaining->has(
149
                $candidateRecord
150
            )
151
        )->withUniqueValues();
152
    }
153
154
    public function withUniqueValues(): self
155
    {
156
        return $this->filterValues(
157
            fn(DNSRecordInterface $candidateRecord, DNSRecordCollection $remaining): bool => !$remaining->has(
158
                $candidateRecord
159
            )
160
        );
161
    }
162
163
    private function filterValues(callable $eval): self
164
    {
165
        $filtered = new self();
166
        $records = $this->records->getArrayCopy();
167
168
        /** @var \RemotelyLiving\PHPDNS\Entities\Interfaces\DNSRecordInterface $record */
169
        while ($record = array_shift($records)) {
170
            if ($eval($record, new self(...$records))) {
171
                $filtered[] = $record;
172
            }
173
        }
174
175
        return $filtered;
176
    }
177
}
178