Passed
Pull Request — master (#504)
by
unknown
10:45
created

TokensList::buildFromArray()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 8
ccs 1
cts 1
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpMyAdmin\SqlParser;
6
7
use ArrayAccess;
8
9
use function count;
10
use function in_array;
11
use function is_array;
12
13
/**
14
 * Defines an array of tokens and utility functions to iterate through it.
15
 *
16
 * A structure representing a list of tokens.
17
 *
18
 * @implements ArrayAccess<int, Token>
19
 */
20
class TokensList implements ArrayAccess
21
{
22
    /**
23
     * The count of tokens.
24
     *
25
     * @var int
26
     */
27
    public $count = 0;
28
29
    /**
30
     * The index of the next token to be returned.
31
     *
32
     * @var int
33
     */
34
    public $idx = 0;
35
36
    /**
37
     * @param Token[] $tokens The array of tokens.
38
     */
39
    public function __construct(public array $tokens = [])
40
    {
41
        $this->count = count($tokens);
42
    }
43
44
    /**
45
     * Builds an array of tokens by merging their raw value.
46
     */
47
    public function build(): string
48 1440
    {
49
        return static::buildFromArray($this->tokens);
50 1440
    }
51 1426
52
    /**
53
     * Builds an array of tokens by merging their raw value.
54 72
     *
55 72
     * @param Token[] $list the tokens to be built
56
     */
57
    public static function buildFromArray(array $list): string
58
    {
59
        $ret = '';
60
        foreach ($list as $token) {
61
            $ret .= $token->token;
62
        }
63 40
64
        return $ret;
65 40
    }
66 2
67
    /**
68
     * Adds a new token.
69 38
     *
70 2
     * @param Token $token token to be added in list
71
     */
72
    public function add(Token $token): void
73 38
    {
74 38
        $this->tokens[$this->count++] = $token;
75 38
    }
76 24
77
    /**
78
     * Gets the next token. Skips any irrelevant token (whitespaces and
79
     * comments).
80 38
     */
81
    public function getNext(): Token|null
82
    {
83
        for (; $this->idx < $this->count; ++$this->idx) {
84
            if (
85
                ($this->tokens[$this->idx]->type !== Token::TYPE_WHITESPACE)
86
                && ($this->tokens[$this->idx]->type !== Token::TYPE_COMMENT)
87
            ) {
88 2
                return $this->tokens[$this->idx++];
89
            }
90 2
        }
91
92
        return null;
93
    }
94
95
    /**
96
     * Gets the previous token. Skips any irrelevant token (whitespaces and
97 510
     * comments).
98
     */
99 510
    public function getPrevious(): Token|null
100
    {
101 510
        for (; $this->idx >= 0; --$this->idx) {
102 510
            if (
103
                ($this->tokens[$this->idx]->type !== Token::TYPE_WHITESPACE)
104 510
                && ($this->tokens[$this->idx]->type !== Token::TYPE_COMMENT)
105
            ) {
106
                return $this->tokens[$this->idx--];
107
            }
108 2
        }
109
110
        return null;
111
    }
112
113
    /**
114
     * Gets the previous token.
115 500
     *
116
     * @param int|int[] $type the type
117 500
     */
118
    public function getPreviousOfType($type): Token|null
119 500
    {
120 500
        if (! is_array($type)) {
121
            $type = [$type];
122 500
        }
123
124
        for (; $this->idx >= 0; --$this->idx) {
125
            if (in_array($this->tokens[$this->idx]->type, $type, true)) {
126 14
                return $this->tokens[$this->idx--];
127
            }
128
        }
129
130
        return null;
131
    }
132
133
    /**
134 2
     * Gets the next token.
135
     *
136 2
     * @param int|int[] $type the type
137 2
     */
138
    public function getNextOfType($type): Token|null
139
    {
140 2
        if (! is_array($type)) {
141 2
            $type = [$type];
142 2
        }
143
144
        for (; $this->idx < $this->count; ++$this->idx) {
145
            if (in_array($this->tokens[$this->idx]->type, $type, true)) {
146 2
                return $this->tokens[$this->idx++];
147
            }
148
        }
149
150
        return null;
151
    }
152
153
    /**
154 184
     * Gets the next token.
155
     *
156 184
     * @param int    $type  the type of the token
157 184
     * @param string $value the value of the token
158
     */
159
    public function getNextOfTypeAndValue($type, $value): Token|null
160 184
    {
161 184
        for (; $this->idx < $this->count; ++$this->idx) {
162 166
            if (($this->tokens[$this->idx]->type === $type) && ($this->tokens[$this->idx]->value === $value)) {
163
                return $this->tokens[$this->idx++];
164
            }
165
        }
166 30
167
        return null;
168
    }
169
170
    /**
171
     * Gets the next token.
172
     *
173
     * @param int $type the type of the token
174
     * @param int $flag the flag of the token
175 1420
     */
176
    public function getNextOfTypeAndFlag(int $type, int $flag): Token|null
177 1420
    {
178 1420
        for (; $this->idx < $this->count; ++$this->idx) {
179 244
            if (($this->tokens[$this->idx]->type === $type) && ($this->tokens[$this->idx]->flags === $flag)) {
180
                return $this->tokens[$this->idx++];
181
            }
182
        }
183 1420
184
        return null;
185
    }
186
187
    /**
188
     * Sets an value inside the container.
189
     *
190
     * @param int|null $offset the offset to be set
191
     * @param Token    $value  the token to be saved
192 1420
     */
193
    public function offsetSet($offset, $value): void
194 1420
    {
195 1420
        if ($offset === null) {
196 216
            $this->tokens[$this->count++] = $value;
197
        } else {
198
            $this->tokens[$offset] = $value;
199
        }
200 1420
    }
201
202
    /**
203
     * Gets a value from the container.
204
     *
205
     * @param int $offset the offset to be returned
206
     */
207
    public function offsetGet($offset): Token|null
208
    {
209 2
        return $offset < $this->count ? $this->tokens[$offset] : null;
210
    }
211 2
212 2
    /**
213
     * Checks if an offset was previously set.
214 2
     *
215
     * @param int $offset the offset to be checked
216
     */
217
    public function offsetExists($offset): bool
218
    {
219
        return $offset < $this->count;
220
    }
221
222
    /**
223 2
     * Unsets the value of an offset.
224
     *
225 2
     * @param int $offset the offset to be unset
226
     */
227
    public function offsetUnset($offset): void
228
    {
229
        unset($this->tokens[$offset]);
230
        --$this->count;
231
        for ($i = $offset; $i < $this->count; ++$i) {
232
            $this->tokens[$i] = $this->tokens[$i + 1];
233 2
        }
234
235 2
        unset($this->tokens[$this->count]);
236
    }
237
}
238