SelectResult::getRowValues()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 5
nc 3
nop 2
dl 0
loc 9
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace Lagdo\DbAdmin\Db\Page\Dql;
4
5
use Lagdo\DbAdmin\Db\Page\AppPage;
6
use Lagdo\DbAdmin\Driver\DriverInterface;
7
use Lagdo\DbAdmin\Driver\Entity\TableFieldEntity;
8
use Lagdo\DbAdmin\Driver\Utils\Utils;
9
10
use function array_map;
11
use function compact;
12
use function current;
13
use function is_string;
14
use function key;
15
use function md5;
16
use function next;
17
use function preg_match;
18
use function strlen;
19
use function strpos;
20
use function trim;
21
22
class SelectResult
23
{
24
    /**
25
     * The constructor
26
     *
27
     * @param AppPage $page
28
     * @param DriverInterface $driver
29
     * @param Utils $utils
30
     */
31
    public function __construct(private AppPage $page,
32
        private DriverInterface $driver, private Utils $utils)
33
    {}
34
35
    /**
36
     * @param SelectEntity $selectEntity
37
     * @param string $key
38
     * @param int $rank
39
     *
40
     * @return array
41
     */
42
    private function getResultHeaderItem(SelectEntity $selectEntity, string $key, int $rank): array
43
    {
44
        $valueKey = key($selectEntity->select);
45
        $value = $selectEntity->queryOptions["columns"][$valueKey] ?? [];
46
47
        $fun = $value["fun"] ?? '';
48
        $fieldKey = !$selectEntity->select ? $key :
49
            ($value["col"] ?? current($selectEntity->select));
50
        $field = $selectEntity->fields[$fieldKey];
51
        $name = !$field ? ($fun ? "*" : $key) :
52
            $this->page->fieldName($field, $rank);
53
54
        return [$fun, $name, $field];
55
    }
56
57
    /**
58
     * @param SelectEntity $selectEntity
59
     * @param string $key
60
     * @param mixed $value
61
     * @param int $rank
62
     *
63
     * @return array
64
     */
65
    private function getResultHeader(SelectEntity $selectEntity, string $key, $value, int $rank): array
0 ignored issues
show
Unused Code introduced by
The parameter $value 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

65
    private function getResultHeader(SelectEntity $selectEntity, string $key, /** @scrutinizer ignore-unused */ $value, int $rank): array

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...
66
    {
67
        if (isset($selectEntity->unselected[$key])) {
68
            return [];
69
        }
70
71
        [$fun, $name, $field] = $this->getResultHeaderItem($selectEntity, $key, $rank);
72
        $header = compact('field', 'name');
73
        if ($name != "") {
74
            $selectEntity->names[$key] = $name;
75
            // $href = remove_from_uri('(order|desc)[^=]*|page') . '&order%5B0%5D=' . urlencode($key);
76
            // $desc = "&desc%5B0%5D=1";
77
            $header['column'] = $this->driver->escapeId($key);
78
            // $header['key'] = $this->utils->str
79
            //     ->html($this->driver->bracketEscape($key));
80
            //! columns looking like functions
81
            $header['title'] = $this->page->applySqlFunction($fun, $name);
82
        }
83
        // $functions[$key] = $fun;
84
        next($selectEntity->select);
85
86
        return $header;
87
    }
88
89
    /**
90
     * Get the result headers from the first result row
91
     * @return void
92
     */
93
    public function setResultHeaders(SelectEntity $selectEntity): void
94
    {
95
        // Results headers
96
        $selectEntity->headers = [
97
            '', // !$group && $select ? '' : lang('Modify');
98
        ];
99
        $selectEntity->names = [];
100
        // $selectEntity->functions = [];
101
        reset($selectEntity->select);
102
103
        $rank = 1;
104
        $firstResultRow = $selectEntity->rows[0];
105
        foreach ($firstResultRow as $key => $value) {
106
            $header = $this->getResultHeader($selectEntity, $key, $value, $rank);
107
            if ($header['name'] ?? '' !== '') {
108
                $rank++;
109
            }
110
            $selectEntity->headers[] = $header;
111
        }
112
    }
113
114
    /**
115
     * @param array $rows
116
     * @param array $queryOptions
117
     *
118
     * @return array
119
     */
120
    /*private function getValuesLengths(array $rows, array $queryOptions): array
121
    {
122
        $lengths = [];
123
        if($queryOptions["modify"])
124
        {
125
            foreach($rows as $row)
126
            {
127
                foreach($row as $key => $value)
128
                {
129
                    $lengths[$key] = \max($lengths[$key], \min(40, strlen(\utf8_decode($value))));
130
                }
131
            }
132
        }
133
        return $lengths;
134
    }*/
135
136
    /**
137
     * @param SelectEntity $selectEntity
138
     * @param array $row
139
     *
140
     * @return array
141
     */
142
    private function getUniqueIds(SelectEntity $selectEntity, array $row): array
143
    {
144
        $uniqueIds = $this->utils->uniqueIds($row, $selectEntity->indexes);
145
        if (empty($uniqueIds)) {
146
            $pattern = '~^(COUNT\((\*|(DISTINCT )?`(?:[^`]|``)+`)\)' .
147
                '|(AVG|GROUP_CONCAT|MAX|MIN|SUM)\(`(?:[^`]|``)+`\))$~';
148
            foreach ($row as $key => $value) {
149
                if (!preg_match($pattern, $key)) {
150
                    //! columns looking like functions
151
                    $uniqueIds[$key] = $value;
152
                }
153
            }
154
        }
155
        return $uniqueIds;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $uniqueIds could return the type null which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
156
    }
157
158
    /**
159
     * @param string $type
160
     * @param mixed $value
161
     *
162
     * @return bool
163
     */
164
    private function shouldEncodeRowId(string $type, $value): bool
165
    {
166
        $jush = $this->driver->jush();
167
        return ($jush === "sql" || $jush === "pgsql") &&
168
            is_string($value) && strlen($value) > 64 &&
169
            preg_match('~char|text|enum|set~', $type);
170
    }
171
172
    /**
173
     * @param string $key
174
     * @param string $collation
175
     *
176
     * @return string
177
     */
178
    private function getRowIdMd5Key(string $key, string $collation): string
179
    {
180
        return $this->driver->jush() !== 'sql' ||
181
            preg_match("~^utf8~", $collation) ? $key :
182
                "CONVERT($key USING " . $this->driver->charset() . ")";
183
    }
184
185
    /**
186
     * @param SelectEntity $selectEntity
187
     * @param string $key
188
     * @param mixed $value
189
     *
190
     * @return array
191
     */
192
    private function getRowIdValue(SelectEntity $selectEntity, string $key, $value): array
193
    {
194
        $key = trim($key);
195
        $type = '';
196
        $collation = '';
197
        if (isset($selectEntity->fields[$key])) {
198
            $type = $selectEntity->fields[$key]->type;
199
            $collation = $selectEntity->fields[$key]->collation;
200
        }
201
        if ($this->shouldEncodeRowId($type, $value)) {
202
            if (!strpos($key, '(')) {
203
                //! columns looking like functions
204
                $key = $this->driver->escapeId($key);
205
            }
206
            $key = "MD5(" . $this->getRowIdMd5Key($key, $collation) . ")";
207
            $value = md5($value);
208
        }
209
        return [$key, $value];
210
    }
211
212
    /**
213
     * @param SelectEntity $selectEntity
214
     * @param array $row
215
     *
216
     * @return array
217
     */
218
    public function getRowIds(SelectEntity $selectEntity, array $row): array
219
    {
220
        $uniqueIds = $this->getUniqueIds($selectEntity, $row);
221
        // Unique identifier to edit returned data.
222
        // $unique_idf = "";
223
        $rowIds = ['where' => [], 'null' => []];
224
        foreach ($uniqueIds as $key => $value) {
225
            [$key, $value] = $this->getRowIdValue($selectEntity, $key, $value);
226
            // $unique_idf .= "&" . ($value !== null ? \urlencode("where[" .
227
            // $this->driver->bracketEscape($key) . "]") . "=" .
228
            // \urlencode($value) : \urlencode("null[]") . "=" . \urlencode($key));
229
            if ($value === null) {
230
                $rowIds['null'][] = $this->driver->bracketEscape($key);
231
                continue;
232
            }
233
            $rowIds['where'][$this->driver->bracketEscape($key)] = $value;
234
        }
235
        return $rowIds;
236
    }
237
238
    /**
239
     * @param SelectEntity $selectEntity
240
     * @param string $key
241
     * @param mixed $value
242
     *
243
     * @return array
244
     */
245
    private function getColumnValue(SelectEntity $selectEntity, string $key, $value): array
246
    {
247
        $field = $selectEntity->fields[$key] ?? new TableFieldEntity();
248
        $textLength = $selectEntity->textLength;
249
        $value = $this->driver->value($value, $field);
250
        return $this->page->getFieldValue($field, $textLength, $value);
251
    }
252
253
    /**
254
     * @param SelectEntity $selectEntity
255
     * @param array $row
256
     *
257
     * @return array
258
     */
259
    private function getRowValues(SelectEntity $selectEntity, array $row): array
260
    {
261
        $cols = [];
262
        foreach ($row as $key => $value) {
263
            if (isset($selectEntity->names[$key])) {
264
                $cols[] = $this->getColumnValue($selectEntity, $key, $value);
265
            }
266
        }
267
        return $cols;
268
    }
269
270
    /**
271
     * @param SelectEntity $selectEntity
272
     *
273
     * @return array
274
     */
275
    public function getRows(SelectEntity $selectEntity): array
276
    {
277
        return array_map(fn($row) => [
278
            // Unique identifier to edit returned data.
279
            'ids' => $this->getRowIds($selectEntity, $row),
280
            'cols' => $this->getRowValues($selectEntity, $row),
281
        ], $selectEntity->rows);
282
    }
283
}
284