Passed
Push — master ( 668c77...c11634 )
by Gilles
02:19
created

Content::copyUntil()   B

Complexity

Conditions 11
Paths 21

Size

Total Lines 56
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 29
CRAP Score 11.0324

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 11
eloc 31
c 1
b 0
f 0
nc 21
nop 3
dl 0
loc 56
ccs 29
cts 31
cp 0.9355
crap 11.0324
rs 7.3166

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace PHPHtmlParser;
6
7
use PHPHtmlParser\Enum\StringToken;
8
use PHPHtmlParser\Exceptions\ContentLengthException;
9
use PHPHtmlParser\Exceptions\LogicalException;
10
11
/**
12
 * Class Content.
13
 */
14
class Content
15
{
16
    /**
17
     * The content string.
18
     *
19
     * @var string
20
     */
21
    protected $content;
22
23
    /**
24
     * The size of the content.
25
     *
26
     * @var int
27
     */
28
    protected $size;
29
30
    /**
31
     * The current position we are in the content.
32
     *
33
     * @var int
34
     */
35
    protected $pos;
36
37
    /**
38
     * The following 4 strings are tags that are important to us.
39
     *
40
     * @var string
41
     */
42
    protected $blank = " \t\r\n";
43
    protected $equal = ' =/>';
44
    protected $slash = " />\r\n\t";
45
    protected $attr = ' >';
46
47
    /**
48
     * Content constructor.
49
     */
50 327
    public function __construct(string $content = '')
51
    {
52 327
        $this->content = $content;
53 327
        $this->size = \strlen($content);
54 327
        $this->pos = 0;
55 327
    }
56
57
    /**
58
     * Returns the current position of the content.
59
     */
60 75
    public function getPosition(): int
61
    {
62 75
        return $this->pos;
63
    }
64
65
    /**
66
     * Gets the current character we are at.
67
     *
68
     * @param ?int $char
69
     */
70 312
    public function char(?int $char = null): string
71
    {
72 312
        return $this->content[$char ?? $this->pos] ?? '';
73
    }
74
75
    /**
76
     * Moves the current position forward.
77
     *
78
     * @throws ContentLengthException
79
     */
80 297
    public function fastForward(int $count): Content
81
    {
82 297
        if (!$this->canFastForward($count)) {
83
            // trying to go over the content length, throw exception
84 3
            throw new ContentLengthException('Attempt to fastForward pass the length of the content.');
85
        }
86 297
        $this->pos += $count;
87
88 297
        return $this;
89
    }
90
91
    /**
92
     * Checks if we can move the position forward.
93
     */
94 297
    public function canFastForward(int $count): bool
95
    {
96 297
        return \strlen($this->content) >= $this->pos + $count;
97
    }
98
99
    /**
100
     * Moves the current position backward.
101
     */
102 27
    public function rewind(int $count): Content
103
    {
104 27
        $this->pos -= $count;
105 27
        if ($this->pos < 0) {
106 3
            $this->pos = 0;
107
        }
108
109 27
        return $this;
110
    }
111
112
    /**
113
     * Copy the content until we find the given string.
114
     */
115 303
    public function copyUntil(string $string, bool $char = false, bool $escape = false): string
116
    {
117 303
        if ($this->pos >= $this->size) {
118
            // nothing left
119 282
            return '';
120
        }
121
122 303
        if ($escape) {
123 258
            $position = $this->pos;
124 258
            $found = false;
125 258
            while (!$found) {
126 258
                $position = \strpos($this->content, $string, $position);
127 258
                if ($position === false) {
128
                    // reached the end
129 237
                    break;
130
                }
131
132 234
                if ($this->char($position - 1) == '\\') {
133
                    // this character is escaped
134 3
                    ++$position;
135 3
                    continue;
136
                }
137
138 234
                $found = true;
139
            }
140 300
        } elseif ($char) {
141 288
            $position = \strcspn($this->content, $string, $this->pos);
142 288
            $position += $this->pos;
143
        } else {
144 294
            $position = \strpos($this->content, $string, $this->pos);
145
        }
146
147 303
        if ($position === false) {
0 ignored issues
show
introduced by
The condition $position === false is always false.
Loading history...
148
            // could not find character, just return the remaining of the content
149 246
            $return = \substr($this->content, $this->pos, $this->size - $this->pos);
150 246
            if ($return === false) {
151
                throw new LogicalException('Substr returned false with position ' . $this->pos . '.');
152
            }
153 246
            $this->pos = $this->size;
154
155 246
            return $return;
156
        }
157
158 294
        if ($position == $this->pos) {
159
            // we are at the right place
160 282
            return '';
161
        }
162
163 294
        $return = \substr($this->content, $this->pos, $position - $this->pos);
164 294
        if ($return === false) {
165
            throw new LogicalException('Substr returned false with position ' . $this->pos . '.');
166
        }
167
        // set the new position
168 294
        $this->pos = $position;
169
170 294
        return $return;
171
    }
172
173
    /**
174
     * Copies the content until the string is found and return it
175
     * unless the 'unless' is found in the substring.
176
     */
177 255
    public function copyUntilUnless(string $string, string $unless): string
178
    {
179 255
        $lastPos = $this->pos;
180 255
        $this->fastForward(1);
181 255
        $foundString = $this->copyUntil($string, true, true);
182
183 255
        $position = \strcspn($foundString, $unless);
184 255
        if ($position == \strlen($foundString)) {
185 69
            return $string . $foundString;
186
        }
187
        // rewind changes and return nothing
188 255
        $this->pos = $lastPos;
189
190 255
        return '';
191
    }
192
193
    /**
194
     * Copies the content until it reaches the token string.,.
195
     *
196
     * @uses $this->copyUntil()
197
     */
198 285
    public function copyByToken(StringToken $stringToken, bool $char = false, bool $escape = false): string
199
    {
200 285
        $string = $stringToken->getValue();
201
202 285
        return $this->copyUntil($string, $char, $escape);
203
    }
204
205
    /**
206
     * Skip a given set of characters.
207
     *
208
     * @throws LogicalException
209
     */
210 291
    public function skip(string $string, bool $copy = false): string
211
    {
212 291
        $len = \strspn($this->content, $string, $this->pos);
213 291
        if ($len === false) {
214
            throw new LogicalException('Strspn returned false with position ' . $this->pos . '.');
215
        }
216 291
        $return = '';
217 291
        if ($copy) {
218 267
            $return = \substr($this->content, $this->pos, $len);
219 267
            if ($return === false) {
220
                throw new LogicalException('Substr returned false with position ' . $this->pos . '.');
221
            }
222
        }
223
224
        // update the position
225 291
        $this->pos += $len;
226
227 291
        return $return;
228
    }
229
230
    /**
231
     * Skip a given token of pre-defined characters.
232
     *
233
     * @uses $this->skip()
234
     */
235 285
    public function skipByToken(StringToken $skipToken, bool $copy = false): string
236
    {
237 285
        $string = $skipToken->getValue();
238
239 285
        return $this->skip($string, $copy);
240
    }
241
}
242