RdataHandlers   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 155
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 20
eloc 51
dl 0
loc 155
ccs 56
cts 56
cp 1
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A getAllRemaining() 0 9 2
A pop() 0 6 1
A handleLocRdata() 0 12 1
A catchAll() 0 7 2
A handleTxt() 0 15 5
A dmsToDecimal() 0 5 3
A handleAplRdata() 0 16 3
A getHandlers() 0 3 1
A handleTxtRdata() 0 11 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 5
    public static function catchAll(string $type, \ArrayIterator $iterator): Rdata\RdataInterface
110
    {
111 5
        if (!Rdata\Factory::isTypeImplemented($type)) {
112 1
            return new PolymorphicRdata($type, implode(Tokens::SPACE, self::getAllRemaining($iterator)));
113
        }
114
115 4
        return call_user_func_array([Rdata\Factory::class, $type], self::getAllRemaining($iterator));
116
    }
117
118
    /**
119
     * @param StringIterator $string
120
     * @param StringIterator $txt
121
     */
122 3
    private static function handleTxt(StringIterator $string, StringIterator $txt): void
123
    {
124 3
        if ($string->isNot(Tokens::DOUBLE_QUOTES)) {
125 1
            return;
126
        }
127
128 3
        $string->next();
129
130 3
        while ($string->isNot(Tokens::DOUBLE_QUOTES) && $string->valid()) {
131 3
            if ($string->is(Tokens::BACKSLASH)) {
132 3
                $string->next();
133
            }
134
135 3
            $txt->append($string->current());
136 3
            $string->next();
137
        }
138 3
    }
139
140
    /**
141
     * Return current entry and moves the iterator to the next entry.
142
     *
143
     * @param \ArrayIterator $iterator
144
     *
145
     * @return string
146
     */
147 1
    private static function pop(\ArrayIterator $iterator): string
148
    {
149 1
        $current = $iterator->current();
150 1
        $iterator->next();
151
152 1
        return $current;
153
    }
154
155
    /**
156
     * Get all the remaining values of an iterator as an array.
157
     *
158
     * @param \ArrayIterator $iterator
159
     *
160
     * @return array
161
     */
162 5
    private static function getAllRemaining(\ArrayIterator $iterator): array
163
    {
164 5
        $values = [];
165 5
        while ($iterator->valid()) {
166 5
            $values[] = $iterator->current();
167 5
            $iterator->next();
168
        }
169
170 5
        return $values;
171
    }
172
}
173