DummyResult   A
last analyzed

Complexity

Total Complexity 34

Size/Duplication

Total Lines 253
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 34
eloc 65
dl 0
loc 253
rs 9.68
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A fetchValue() 0 9 3
A fetchRow() 0 7 3
A numRows() 0 7 2
A getFieldNames() 0 7 2
A seek() 0 9 2
A __construct() 0 5 2
A getFieldsMeta() 0 12 3
A fetchAllKeyPair() 0 10 2
A fetchAssoc() 0 17 4
A fetchAllColumn() 0 14 3
A getIterator() 0 9 3
A numFields() 0 7 2
A fetchAllAssoc() 0 15 3
1
<?php
2
/**
3
 * Extension independent database result
4
 */
5
6
declare(strict_types=1);
7
8
namespace PhpMyAdmin\Tests\Stubs;
9
10
use Generator;
11
use PhpMyAdmin\Dbal\ResultInterface;
12
use PhpMyAdmin\FieldMetadata;
13
use PhpMyAdmin\Tests\FieldHelper;
14
15
use function array_column;
16
use function array_key_exists;
17
use function count;
18
use function is_string;
19
20
use const MYSQLI_TYPE_STRING;
21
22
/**
23
 * Extension independent database result
24
 */
25
class DummyResult implements ResultInterface
26
{
27
    /**
28
     * The result identifier produced by the DBiExtension
29
     *
30
     * @var mixed[][]|null
31
     * @psalm-var list<non-empty-list<string|null>>
32
     */
33
    private array|null $result;
34
35
    /**
36
     * @var string[]
37
     * @psalm-var list<non-empty-string>
38
     */
39
    private array $columns;
40
41
    /**
42
     * @var FieldMetadata[]
43
     * @psalm-var list<FieldMetadata>
44
     */
45
    private array $metadata;
46
47
    private int $pos = 0;
48
49
    /**
50
     * @psalm-param array{
51
     *     query: string,
52
     *     result: list<non-empty-list<string|null>>|true,
53
     *     columns?: list<non-empty-string>,
54
     *     metadata?: list<FieldMetadata>,
55
     * } $query
56
     */
57
    public function __construct(array $query)
58
    {
59
        $this->columns = $query['columns'] ?? [];
60
        $this->metadata = $query['metadata'] ?? [];
61
        $this->result = $query['result'] === true ? null : $query['result'];
62
    }
63
64
    /**
65
     * Returns a generator that traverses through the whole result set
66
     * and returns each row as an associative array
67
     *
68
     * @psalm-return Generator<int, array<array-key, string|null>, mixed, void>
69
     */
70
    public function getIterator(): Generator
71
    {
72
        if ($this->result === null) {
73
            return;
74
        }
75
76
        $this->seek(0);
77
        while ($row = $this->fetchAssoc()) {
78
            yield $row;
79
        }
80
    }
81
82
    /**
83
     * Returns the next row of the result with associative keys
84
     *
85
     * @return array<string|null>
86
     */
87
    public function fetchAssoc(): array
88
    {
89
        if ($this->result === null) {
90
            return [];
91
        }
92
93
        $row = $this->result[$this->pos++] ?? [];
94
        if ($this->columns === []) {
95
            return $row;
96
        }
97
98
        $ret = [];
99
        foreach ($row as $key => $val) {
100
            $ret[$this->columns[$key]] = $val;
101
        }
102
103
        return $ret;
104
    }
105
106
    /**
107
     * Returns the next row of the result with numeric keys
108
     *
109
     * @return array<int,string|null>
110
     * @psalm-return list<string|null>
111
     */
112
    public function fetchRow(): array
113
    {
114
        if ($this->result === null || $this->pos >= count($this->result)) {
115
            return [];
116
        }
117
118
        return $this->result[$this->pos++];
119
    }
120
121
    /**
122
     * Returns a single value from the given result; false on error
123
     */
124
    public function fetchValue(int|string $field = 0): string|false|null
125
    {
126
        $row = is_string($field) ? $this->fetchAssoc() : $this->fetchRow();
127
128
        if (! array_key_exists($field, $row)) {
129
            return false;
130
        }
131
132
        return $row[$field] ?? null;
133
    }
134
135
    /**
136
     * Returns all rows of the result
137
     *
138
     * @return array<array<string|null>>
139
     * @psalm-return list<array<string|null>>
140
     */
141
    public function fetchAllAssoc(): array
142
    {
143
        if ($this->result === null) {
144
            return [];
145
        }
146
147
        // This function should return all rows, not only the remaining rows
148
        $this->seek(0);
149
150
        $rows = [];
151
        while ($row = $this->fetchAssoc()) {
152
            $rows[] = $row;
153
        }
154
155
        return $rows;
156
    }
157
158
    /**
159
     * Returns values from the selected column of each row
160
     *
161
     * @return array<int, string|null>
162
     * @psalm-return list<string|null>
163
     */
164
    public function fetchAllColumn(int|string $column = 0): array
165
    {
166
        if ($this->result === null) {
167
            return [];
168
        }
169
170
        // This function should return all rows, not only the remaining rows
171
        $this->seek(0);
172
173
        if (is_string($column)) {
174
            return array_column($this->fetchAllAssoc(), $column);
175
        }
176
177
        return array_column($this->result, $column);
178
    }
179
180
    /**
181
     * Returns values as single dimensional array where the key is the first column
182
     * and the value is the second column, e.g.
183
     * SELECT id, name FROM users
184
     * produces: ['123' => 'John', '124' => 'Jane']
185
     *
186
     * @return array<string|null>
187
     * @psalm-return array<array-key, string|null>
188
     */
189
    public function fetchAllKeyPair(): array
190
    {
191
        if ($this->result === null) {
192
            return [];
193
        }
194
195
        // This function should return all rows, not only the remaining rows
196
        $this->seek(0);
197
198
        return array_column($this->result, 1, 0);
199
    }
200
201
    /**
202
     * Returns the number of fields in the result
203
     */
204
    public function numFields(): int
205
    {
206
        if ($this->result === null) {
207
            return 0;
208
        }
209
210
        return count($this->columns);
211
    }
212
213
    /**
214
     * Returns the number of rows in the result
215
     *
216
     * @psalm-return int
217
     */
218
    public function numRows(): int
219
    {
220
        if ($this->result === null) {
221
            return 0;
222
        }
223
224
        return count($this->result);
225
    }
226
227
    /**
228
     * Adjusts the result pointer to an arbitrary row in the result
229
     *
230
     * @param int $offset offset to seek
231
     *
232
     * @return bool True if the offset exists, false otherwise
233
     */
234
    public function seek(int $offset): bool
235
    {
236
        if ($this->result === null) {
237
            return false;
238
        }
239
240
        $this->pos = $offset;
241
242
        return $offset < count($this->result);
243
    }
244
245
    /**
246
     * returns meta info for fields in $result
247
     *
248
     * @return array<int, FieldMetadata> meta info for fields in $result
249
     * @psalm-return list<FieldMetadata>
250
     */
251
    public function getFieldsMeta(): array
252
    {
253
        $metadata = $this->metadata;
254
        foreach ($this->columns as $i => $column) {
255
            if (isset($metadata[$i])) {
256
                $metadata[$i]->name = $column;
257
            } else {
258
                $metadata[] = FieldHelper::fromArray(['type' => MYSQLI_TYPE_STRING, 'name' => $column]);
259
            }
260
        }
261
262
        return $metadata;
263
    }
264
265
    /**
266
     * Returns the names of the fields in the result
267
     *
268
     * @return array<int, string> Fields names
269
     * @psalm-return list<non-empty-string>
270
     */
271
    public function getFieldNames(): array
272
    {
273
        if ($this->result === null) {
274
            return [];
275
        }
276
277
        return array_column($this->getFieldsMeta(), 'name');
278
    }
279
}
280