JsonFileSystemResolver::saveZone()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 0
c 1
b 0
f 1
nc 1
nop 1
dl 0
loc 2
ccs 0
cts 1
cp 0
crap 2
rs 10
1
<?php
2
3
/*
4
 * This file is part of PHP DNS Server.
5
 *
6
 * (c) Yif Swery <[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 yswery\DNS\Resolver;
13
14
use yswery\DNS\ClassEnum;
15
use yswery\DNS\Exception\ZoneFileNotFoundException;
16
use yswery\DNS\Filesystem\FilesystemManager;
17
use yswery\DNS\RecordTypeEnum;
18
use yswery\DNS\ResourceRecord;
19
use yswery\DNS\UnsupportedTypeException;
20
21
class JsonFileSystemResolver extends AbstractResolver
22
{
23
    /**
24
     * @var int
25
     */
26
    protected $defaultClass = ClassEnum::INTERNET;
27
28
    /**
29
     * @var FilesystemManager
30
     */
31
    protected $filesystemManager;
32
33
    /**
34
     * @var int
35
     */
36
    protected $defaultTtl;
37
38
    /**
39
     * JsonResolver constructor.
40
     *
41
     * @param FilesystemManager $filesystemManager
42
     * @param int               $defaultTtl
43
     *
44
     * @throws UnsupportedTypeException
45
     */
46
    public function __construct(FilesystemManager $filesystemManager, $defaultTtl = 300)
47
    {
48
        $this->isAuthoritative = true;
49
        $this->allowRecursion = false;
50
        $this->filesystemManager = $filesystemManager;
51
        $this->defaultTtl = $defaultTtl;
52
53
        $zones = glob($filesystemManager->zonePath().'/*.json');
54
        foreach ($zones as $file) {
55
            $zone = json_decode(file_get_contents($file), true);
56
            $resourceRecords = $this->isLegacyFormat($zone) ? $this->processLegacyZone($zone) : $this->processZone($zone);
57
            $this->addZone($resourceRecords);
58
        }
59
    }
60
61
    /**
62
     * Load a zone file.
63
     *
64
     * @param string $file
65
     *
66
     * @throws UnsupportedTypeException
67
     * @throws ZoneFileNotFoundException
68
     */
69
    public function loadZone($file)
70
    {
71
        if (file_exists($file)) {
72
            $zone = json_decode(file_get_contents($file), true);
73
            $resourceRecords = $this->isLegacyFormat($zone) ? $this->processLegacyZone($zone) : $this->processZone($zone);
74
            $this->addZone($resourceRecords);
75
        } else {
76
            throw new ZoneFileNotFoundException('The zone file could not be found');
77
        }
78
    }
79
80
    /**
81
     * Saves the zone to a .json file.
82
     *
83
     * @param string $zone
84
     */
85
    public function saveZone($zone)
0 ignored issues
show
Unused Code introduced by
The parameter $zone is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

85
    public function saveZone(/** @scrutinizer ignore-unused */ $zone)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
86
    {
87
    }
88
89
    /**
90
     * @param array $zone
91
     *
92
     * @return ResourceRecord[]
93
     *
94
     * @throws UnsupportedTypeException
95
     */
96
    protected function processZone(array $zone): array
97
    {
98
        $parent = rtrim($zone['domain'], '.').'.';
99
        $defaultTtl = $zone['default-ttl'];
100
        $rrs = $zone['resource-records'];
101
        $resourceRecords = [];
102
103
        foreach ($rrs as $rr) {
104
            $name = $rr['name'] ?? $parent;
105
            $class = isset($rr['class']) ? ClassEnum::getClassFromName($rr['class']) : $this->defaultClass;
106
107
            $resourceRecords[] = (new ResourceRecord())
108
                ->setName($this->handleName($name, $parent))
109
                ->setClass($class)
110
                ->setType($type = RecordTypeEnum::getTypeFromName($rr['type']))
111
                ->setTtl($rr['ttl'] ?? $defaultTtl)
112
                ->setRdata($this->extractRdata($rr, $type, $parent));
113
        }
114
115
        return $resourceRecords;
116
    }
117
118
    /**
119
     * Determine if a $zone is in the legacy format.
120
     *
121
     * @param array $zone
122
     *
123
     * @return bool
124
     */
125
    protected function isLegacyFormat(array $zone): bool
126
    {
127
        $keys = array_map(function ($value) {
128
            return strtolower($value);
129
        }, array_keys($zone));
130
131
        return
132
            (false === array_search('domain', $keys, true)) ||
133
            (false === array_search('resource-records', $keys, true));
134
    }
135
136
    /**
137
     * @param array $zones
138
     *
139
     * @return array
140
     */
141
    protected function processLegacyZone(array $zones): array
142
    {
143
        $resourceRecords = [];
144
        foreach ($zones as $domain => $types) {
145
            $domain = rtrim($domain, '.').'.';
146
            foreach ($types as $type => $data) {
147
                $data = (array) $data;
148
                $type = RecordTypeEnum::getTypeFromName($type);
149
                foreach ($data as $rdata) {
150
                    $resourceRecords[] = (new ResourceRecord())
151
                        ->setName($domain)
152
                        ->setType($type)
153
                        ->setClass($this->defaultClass)
154
                        ->setTtl($this->defaultTtl)
155
                        ->setRdata($rdata);
156
                }
157
            }
158
        }
159
160
        return $resourceRecords;
161
    }
162
}
163