Completed
Push — master ( 6d3196...8c517a )
by Sam
02:31
created

SystemResolver   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 133
Duplicated Lines 0 %

Test Coverage

Coverage 55.17%

Importance

Changes 0
Metric Value
eloc 58
dl 0
loc 133
ccs 32
cts 58
cp 0.5517
rs 10
c 0
b 0
f 0
wmc 18

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getAnswer() 0 8 2
A getRecordsRecursively() 0 15 2
A IANA2PHP() 0 14 3
B extractPhpRdata() 0 40 10
1
<?php
2
/*
3
 * This file is part of PHP DNS Server.
4
 *
5
 * (c) Yif Swery <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace yswery\DNS\Resolver;
12
13
use yswery\DNS\UnsupportedTypeException;
14
use yswery\DNS\ResourceRecord;
15
use yswery\DNS\RecordTypeEnum;
16
17
/**
18
 * Use the host system's configured DNS.
19
 */
20
class SystemResolver extends AbstractResolver
21
{
22
    /**
23
     * SystemResolver constructor.
24
     *
25
     * @param bool $recursionAvailable
26
     * @param bool $authoritative
27
     */
28 2
    public function __construct($recursionAvailable = true, $authoritative = false)
29
    {
30 2
        $this->allowRecursion = (bool) $recursionAvailable;
31 2
        $this->isAuthoritative = (bool) $authoritative;
32 2
    }
33
34
    /**
35
     * @param ResourceRecord[] $queries
36
     *
37
     * @return ResourceRecord[]
38
     *
39
     * @throws UnsupportedTypeException
40
     */
41 2
    public function getAnswer(array $queries): array
42
    {
43 2
        $answer = [];
44 2
        foreach ($queries as $query) {
45 1
            $answer = array_merge($answer, $this->getRecordsRecursively($query));
46
        }
47
48 2
        return $answer;
49
    }
50
51
    /**
52
     * Resolve the $query using the system configured local DNS.
53
     *
54
     * @param ResourceRecord $query
55
     *
56
     * @return ResourceRecord[]
57
     *
58
     * @throws UnsupportedTypeException
59
     */
60 1
    private function getRecordsRecursively(ResourceRecord $query): array
61
    {
62 1
        $records = dns_get_record($query->getName(), $this->IANA2PHP($query->getType()));
63 1
        $result = [];
64
65 1
        foreach ($records as $record) {
66 1
            $result[] = (new ResourceRecord())
67 1
                ->setName($query->getName())
68 1
                ->setClass($query->getClass())
69 1
                ->setTtl($record['ttl'])
70 1
                ->setRdata($this->extractPhpRdata($record))
71 1
                ->setType($query->getType());
72
        }
73
74 1
        return $result;
75
    }
76
77
    /**
78
     * @param array  $resourceRecord
79
     *
80
     * @return array|string
81
     *
82
     * @throws UnsupportedTypeException
83
     */
84 1
    protected function extractPhpRdata(array $resourceRecord)
85
    {
86 1
        $type = RecordTypeEnum::getTypeFromName($resourceRecord['type']);
87
88
        switch ($type) {
89 1
            case RecordTypeEnum::TYPE_A:
90 1
                return $resourceRecord['ip'];
91 1
            case RecordTypeEnum::TYPE_AAAA:
92 1
                return $resourceRecord['ipv6'];
93
            case RecordTypeEnum::TYPE_NS:
94
            case RecordTypeEnum::TYPE_CNAME:
95
            case RecordTypeEnum::TYPE_PTR:
96
                return $resourceRecord['target'];
97
            case RecordTypeEnum::TYPE_SOA:
98
                return [
99
                        'mname' => $resourceRecord['mname'],
100
                        'rname' => $resourceRecord['rname'],
101
                        'serial' => $resourceRecord['serial'],
102
                        'refresh' => $resourceRecord['refresh'],
103
                        'retry' => $resourceRecord['retry'],
104
                        'expire' => $resourceRecord['expire'],
105
                        'minimum' => $resourceRecord['minimum-ttl'],
106
                    ];
107
            case RecordTypeEnum::TYPE_MX:
108
                return [
109
                    'preference' => $resourceRecord['pri'],
110
                    'exchange' => $resourceRecord['host'],
111
                ];
112
            case RecordTypeEnum::TYPE_TXT:
113
                return $resourceRecord['txt'];
114
            case RecordTypeEnum::TYPE_SRV:
115
                return [
116
                    'priority' => $resourceRecord['pri'],
117
                    'port' => $resourceRecord['port'],
118
                    'weight' => $resourceRecord['weight'],
119
                    'target' => $resourceRecord['target'],
120
                ];
121
            default:
122
                throw new UnsupportedTypeException(
123
                    sprintf('Record type "%s" is not a supported type.', RecordTypeEnum::getName($type))
124
                );
125
        }
126
    }
127
128
    /**
129
     * Maps an IANA Rdata type to the built-in PHP DNS constant.
130
     *
131
     * @example $this->IANA_to_PHP(5) //Returns DNS_CNAME int(16)
132
     *
133
     * @param int $type the IANA RTYPE
134
     *
135
     * @return int the built-in PHP DNS_<type> constant or `false` if the type is not defined
136
     *
137
     * @throws UnsupportedTypeException|\InvalidArgumentException
138
     */
139 1
    private function IANA2PHP(int $type): int
140
    {
141 1
        $constantName = 'DNS_'.RecordTypeEnum::getName($type);
142 1
        if (!defined($constantName)) {
143
            throw new UnsupportedTypeException(sprintf('Record type "%d" is not a supported type.', $type));
144
        }
145
146 1
        $phpType = constant($constantName);
147
148 1
        if (!is_int($phpType)) {
149
            throw new \InvalidArgumentException(sprintf('Constant "%s" is not an integer.', $constantName));
150
        }
151
152 1
        return $phpType;
153
    }
154
}
155