Passed
Push — master ( 750782...7d3f93 )
by Sam
01:54
created

Normaliser::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Badcow\DNS\Parser;
4
5
class Normaliser
6
{
7
    /**
8
     * @var StringIterator
9
     */
10
    private $string;
11
12
    /**
13
     * @var string
14
     */
15
    private $normalisedString = '';
16
17
    /**
18
     * Normaliser constructor.
19
     *
20
     * @param string $zone
21
     */
22 12
    public function __construct(string $zone)
23
    {
24
        //Remove Windows line feeds and tabs
25 12
        $zone = str_replace([Tokens::CARRIAGE_RETURN, Tokens::TAB], ['', Tokens::SPACE], $zone);
26
27 12
        $this->string = new StringIterator($zone);
28 12
    }
29
30
    /**
31
     * @param string $zone
32
     *
33
     * @return string
34
     *
35
     * @throws ParseException
36
     */
37 12
    public static function normalise(string $zone): string
38
    {
39 12
        $normaliser = new self($zone);
40
41 12
        return $normaliser->process();
42
    }
43
44
    /**
45
     * @return string
46
     *
47
     * @throws ParseException
48
     */
49 12
    public function process(): string
50
    {
51 12
        while ($this->string->valid()) {
52 12
            switch ($this->string->current()) {
53 12
                case Tokens::DOUBLE_QUOTES:
54 7
                    $this->handleTxt();
55 5
                    break;
56 12
                case Tokens::SEMICOLON:
57 7
                    $this->handleComment();
58 7
                    break;
59 12
                case Tokens::OPEN_BRACKET:
60 6
                    $this->handleMultiline();
61 5
                    break;
62
            }
63
64 12
            $this->append();
65
        }
66
67 9
        $this->removeWhitespace();
68
69 9
        return $this->normalisedString;
70
    }
71
72
    /**
73
     * Ignores the comment section.
74
     */
75 8
    private function handleComment(): void
76
    {
77 8
        while ($this->string->isNot(Tokens::LINE_FEED) && $this->string->valid()) {
78 8
            $this->string->next();
79
        }
80 8
    }
81
82
    /**
83
     * Handle text inside of double quotations. When this function is called, the String pointer MUST be at the
84
     * double quotation mark.
85
     *
86
     * @throws ParseException
87
     */
88 7
    private function handleTxt(): void
89
    {
90 7
        $this->append();
91
92 7
        while ($this->string->isNot(Tokens::DOUBLE_QUOTES)) {
93 7
            if (!$this->string->valid()) {
94 1
                throw new ParseException('Unbalanced double quotation marks. End of file reached.');
95
            }
96
97
            //If escape character
98 7
            if ($this->string->is(Tokens::BACKSLASH)) {
99 5
                $this->append();
100
            }
101
102 7
            if ($this->string->is(Tokens::LINE_FEED)) {
103 1
                throw new ParseException('Line Feed found within double quotation marks context.', $this->string);
104
            }
105
106 7
            $this->append();
107
        }
108 5
    }
109
110
    /**
111
     * Move multi-line records onto single line.
112
     *
113
     * @throws ParseException
114
     */
115 6
    private function handleMultiline(): void
116
    {
117 6
        $openBracket = true;
118 6
        $this->string->next();
119 6
        while ($openBracket && $this->string->valid()) {
120 6
            switch ($this->string->current()) {
121 6
                case Tokens::DOUBLE_QUOTES:
122 1
                    $this->handleTxt();
123 1
                    $this->append();
124 1
                    break;
125 6
                case Tokens::SEMICOLON:
126 6
                    $this->handleComment();
127 6
                    break;
128 6
                case Tokens::LINE_FEED:
129 6
                    $this->string->next();
130 6
                    break;
131 6
                case Tokens::CLOSE_BRACKET:
132 5
                    $openBracket = false;
133 5
                    $this->string->next();
134 5
                    break;
135
                default:
136 6
                    $this->append();
137
            }
138
        }
139
140 6
        if ($openBracket) {
141 1
            throw new ParseException('End of file reached. Unclosed bracket.');
142
        }
143 5
    }
144
145
    /**
146
     * Remove superfluous whitespace characters from string.
147
     */
148 9
    private function removeWhitespace(): void
149
    {
150 9
        $string = preg_replace('/ {2,}/', Tokens::SPACE, $this->normalisedString);
151 9
        $lines = [];
152
153 9
        foreach (explode(Tokens::LINE_FEED, $string) as $line) {
154 9
            if ('' !== $line = trim($line)) {
155 9
                $lines[] = $line;
156
            }
157
        }
158 9
        $this->normalisedString = implode(Tokens::LINE_FEED, $lines);
159 9
    }
160
161
    /**
162
     * Add current entry to normalisedString and moves iterator to next entry.
163
     */
164 12
    private function append()
165
    {
166 12
        $this->normalisedString .= $this->string->current();
167 12
        $this->string->next();
168 12
    }
169
}
170