Completed
Branch monolith (e7771f)
by Sam
01:35
created

RdataHandlers   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 164
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 20
lcom 1
cbo 6
dl 0
loc 164
ccs 56
cts 56
cp 1
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A getHandlers() 0 4 1
A dmsToDecimal() 0 6 3
A handleLocRdata() 0 14 1
A handleAplRdata() 0 17 3
A handleTxtRdata() 0 12 2
A catchAll() 0 8 2
A handleTxt() 0 17 5
A pop() 0 7 1
A getAllRemaining() 0 10 2
1
<?php
2
3
/*
4
 * This file is part of Badcow DNS Library.
5
 *
6
 * (c) Samuel Williams <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Badcow\DNS\Parser;
13
14
use Badcow\DNS\Rdata;
15
16
class RdataHandlers
17
{
18
    private static $handlers = [
19
        Rdata\LOC::TYPE => __CLASS__.'::handleLocRdata',
20
        Rdata\TXT::TYPE => __CLASS__.'::handleTxtRdata',
21
        Rdata\APL::TYPE => __CLASS__.'::handleAplRdata',
22
    ];
23
24 7
    public static function getHandlers(): array
25
    {
26 7
        return self::$handlers;
27
    }
28
29
    /**
30
     * Transform a DMS string to a decimal representation. Used for LOC records.
31
     *
32
     * @param int    $deg        Degrees
33
     * @param int    $min        Minutes
34
     * @param float  $sec        Seconds
35
     * @param string $hemisphere Either 'N', 'S', 'E', or 'W'
36
     *
37
     * @return float
38
     */
39 1
    public static function dmsToDecimal(int $deg, int $min, float $sec, string $hemisphere): float
40
    {
41 1
        $multiplier = ('S' === $hemisphere || 'W' === $hemisphere) ? -1 : 1;
42
43 1
        return $multiplier * ($deg + ($min / 60) + ($sec / 3600));
44
    }
45
46
    /**
47
     * @param \ArrayIterator $iterator
48
     *
49
     * @return Rdata\LOC
50
     */
51 1
    public static function handleLocRdata(\ArrayIterator $iterator): Rdata\LOC
52
    {
53 1
        $lat = self::dmsToDecimal((int) self::pop($iterator), (int) self::pop($iterator), (float) self::pop($iterator), self::pop($iterator));
54 1
        $lon = self::dmsToDecimal((int) self::pop($iterator), (int) self::pop($iterator), (float) self::pop($iterator), self::pop($iterator));
55
56 1
        return Rdata\Factory::Loc(
57 1
            $lat,
58 1
            $lon,
59 1
            (float) self::pop($iterator),
60 1
            (float) self::pop($iterator),
61 1
            (float) self::pop($iterator),
62 1
            (float) self::pop($iterator)
63
        );
64
    }
65
66
    /**
67
     * @param \ArrayIterator $iterator
68
     *
69
     * @return Rdata\APL
70
     *
71
     * @throws ParseException
72
     */
73 4
    public static function handleAplRdata(\ArrayIterator $iterator): Rdata\APL
74
    {
75 4
        $rdata = new Rdata\APL();
76
77 4
        while ($iterator->valid()) {
78 4
            $matches = [];
79 4
            if (1 !== preg_match('/^(?<negate>!)?[1-2]:(?<block>.+)$/i', $iterator->current(), $matches)) {
80 2
                throw new ParseException(sprintf('"%s" is not a valid IP range.', $iterator->current()));
81
            }
82
83 2
            $ipBlock = \IPBlock::create($matches['block']);
84 2
            $rdata->addAddressRange($ipBlock, '!' !== $matches['negate']);
85 2
            $iterator->next();
86
        }
87
88 2
        return $rdata;
89
    }
90
91
    /**
92
     * @param \ArrayIterator $iterator
93
     *
94
     * @return Rdata\TXT
95
     */
96 3
    public static function handleTxtRdata(\ArrayIterator $iterator): Rdata\TXT
97
    {
98 3
        $string = new StringIterator(implode(Tokens::SPACE, self::getAllRemaining($iterator)));
99 3
        $txt = new StringIterator();
100
101 3
        while ($string->valid()) {
102 3
            self::handleTxt($string, $txt);
103 3
            $string->next();
104
        }
105
106 3
        return Rdata\Factory::txt((string) $txt);
107
    }
108
109
    /**
110
     * Returns RData instances for types that do not have explicitly declared handler methods.
111
     *
112
     * @param string $type
113
     * @param \ArrayIterator $iterator
114
     * @return Rdata\RdataInterface
115
     */
116 5
    public static function catchAll(string $type, \ArrayIterator $iterator): Rdata\RdataInterface
117
    {
118 5
        if (!Rdata\Factory::isTypeImplemented($type)) {
119 1
            return new Rdata\PolymorphicRdata($type, implode(Tokens::SPACE, self::getAllRemaining($iterator)));
120
        }
121
122 4
        return call_user_func_array([Rdata\Factory::class, $type], self::getAllRemaining($iterator));
123
    }
124
125
    /**
126
     * @param StringIterator $string
127
     * @param StringIterator $txt
128
     */
129 3
    private static function handleTxt(StringIterator $string, StringIterator $txt): void
130
    {
131 3
        if ($string->isNot(Tokens::DOUBLE_QUOTES)) {
132 1
            return;
133
        }
134
135 3
        $string->next();
136
137 3
        while ($string->isNot(Tokens::DOUBLE_QUOTES) && $string->valid()) {
138 3
            if ($string->is(Tokens::BACKSLASH)) {
139 3
                $string->next();
140
            }
141
142 3
            $txt->append($string->current());
143 3
            $string->next();
144
        }
145 3
    }
146
147
    /**
148
     * Return current entry and moves the iterator to the next entry.
149
     *
150
     * @param \ArrayIterator $iterator
151
     *
152
     * @return string
153
     */
154 1
    private static function pop(\ArrayIterator $iterator): string
155
    {
156 1
        $current = $iterator->current();
157 1
        $iterator->next();
158
159 1
        return $current;
160
    }
161
162
    /**
163
     * Get all the remaining values of an iterator as an array.
164
     *
165
     * @param \ArrayIterator $iterator
166
     *
167
     * @return array
168
     */
169 5
    private static function getAllRemaining(\ArrayIterator $iterator): array
170
    {
171 5
        $values = [];
172 5
        while ($iterator->valid()) {
173 5
            $values[] = $iterator->current();
174 5
            $iterator->next();
175
        }
176
177 5
        return $values;
178
    }
179
}
180