DataFieldValue::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
nc 1
nop 5
dl 0
loc 5
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace Lagdo\DbAdmin\Db\Page\Dml;
4
5
use Lagdo\DbAdmin\Db\Page\AppPage;
6
use Lagdo\DbAdmin\Driver\Utils\Utils;
7
use Lagdo\DbAdmin\Driver\DriverInterface;
8
use Lagdo\DbAdmin\Driver\Entity\TableFieldEntity;
9
use Lagdo\DbAdmin\Driver\Entity\UserTypeEntity;
10
11
use function bin2hex;
12
use function implode;
13
use function is_array;
14
use function is_bool;
15
use function json_encode;
16
use function preg_match;
17
18
/**
19
 * Writes data in the user forms for data row insert and update.
20
 */
21
class DataFieldValue
22
{
23
    /**
24
     * @var bool
25
     */
26
    private bool $isUpdate = false;
27
28
    /**
29
     * @var array<UserTypeEntity>
30
     */
31
    private array $userTypes;
32
33
    /**
34
     * The constructor
35
     *
36
     * @param AppPage $page
37
     * @param DriverInterface $driver
38
     * @param Utils $utils
39
     * @param string $action
40
     * @param string $operation
41
     */
42
    public function __construct(private AppPage $page, private DriverInterface $driver,
43
        private Utils $utils, private string $action, private string $operation)
44
    {
45
        $this->isUpdate = $operation === 'update';
46
        $this->userTypes = $this->driver->userTypes(true);
47
    }
48
49
    /**
50
     * @param array $names
51
     * @param array $functions
52
     * @param bool $addSql
53
     * @param TableFieldEntity $field
54
     *
55
     * @return array
56
     */
57
    private function addEditFunctions(array $names, array $functions, TableFieldEntity $field): array
58
    {
59
        foreach ($functions as $pattern => $_functions) {
60
            if (!$pattern || preg_match("~$pattern~", $field->type)) {
61
                $names = [...$names, ...$_functions]; // Array merge
62
            }
63
        }
64
        return $names;
65
    }
66
67
    /**
68
     * Functions displayed in edit form
69
     * function editFunctions() in adminer.inc.php
70
     *
71
     * @param TableFieldEntity $field Single field from fields()
72
     *
73
     * @return array
74
     */
75
    private function editFunctions(TableFieldEntity $field): array
76
    {
77
        if ($field->autoIncrement && !$this->isUpdate) {
78
            return [$this->utils->trans->lang('Auto Increment')];
79
        }
80
81
        $names = $field->null ? ['NULL', ''] : [''];
82
        $functions = $this->driver->insertFunctions();
83
        $names = $this->addEditFunctions($names, $functions, $field);
84
85
        $functions = $this->driver->editFunctions();
86
        if (/*!isset($this->utils->input->values['call']) &&*/ $this->isUpdate) { // relative functions
87
            $names = $this->addEditFunctions($names, $functions, $field);
88
        }
89
90
        $structuredTypes = $this->driver->structuredTypes();
91
        $userTypes = $structuredTypes[$this->utils->trans->lang('User types')] ?? [];
92
        if ($functions && !preg_match('~set|bool~', $field->type) &&
0 ignored issues
show
Bug Best Practice introduced by
The expression $functions of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
93
            !$this->utils->isBlob($field, $userTypes)) {
94
            $names[] = 'SQL';
95
        }
96
97
        // $dbFunctions = [
98
        //     'insert' => $this->driver->insertFunctions(),
99
        //     'edit' => $this->driver->editFunctions(),
100
        // ];
101
        // foreach ($dbFunctions as $key => $functions) {
102
        //     if ($key === 'insert' || (!$isCall && $this->isUpdate)) { // relative functions
103
        //         foreach ($functions as $pattern => $value) {
104
        //             if (!$pattern || preg_match("~$pattern~", $field->type)) {
105
        //                 $names = [...$names, ...$value]; // Array merge
106
        //             }
107
        //         }
108
        //     }
109
        //     if ($key === 'edit' && !preg_match('~set|bool~', $field->type) && !$this->utils->isBlob($field, $userTypes)) {
110
        //         $names[] = 'SQL';
111
        //     }
112
        // }
113
114
        return $names;
115
    }
116
117
    /**
118
     * @param TableFieldEntity $field
119
     * @param array|null $rowData
120
     *
121
     * @return mixed
122
     */
123
    private function getInputValue(TableFieldEntity $field, array|null $rowData): mixed
124
    {
125
        $update = $this->operation === 'update';
126
        // $default = $options["set"][$this->driver->bracketEscape($name)] ?? null;
127
        /*if ($default === null)*/ {
128
            $default = $field->default;
129
            if ($field->type == "bit" && preg_match("~^b'([01]*)'\$~", $default, $regs)) {
130
                $default = $regs[1];
131
            }
132
            if ($this->driver->jush() == "sql" && preg_match('~binary~', $field->type)) {
133
                $default = bin2hex($default); // same as UNHEX
134
            }
135
        }
136
137
        if ($rowData === null) {
0 ignored issues
show
introduced by
The condition $rowData === null is always false.
Loading history...
138
            return match(true) {
139
                !$update && $field->autoIncrement => '',
140
                $this->action === 'select' => false,
141
                default => $default,
142
            };
143
        }
144
145
        $fieldValue = $rowData[$field->name] ?? null;
146
        return match(true) {
147
            $fieldValue !== '' && $this->driver->jush() === 'sql' &&
148
                preg_match("~enum|set~", $field->type) &&
149
                is_array($fieldValue) => implode(",", $fieldValue),
150
            is_bool($fieldValue) => +$fieldValue,
151
            default => $fieldValue,
152
        };
153
    }
154
155
    /**
156
     * @param TableFieldEntity $field
157
     * @param mixed $value
158
     *
159
     * @return array
160
     */
161
    private function getInputFunction(TableFieldEntity $field, mixed $value): array
162
    {
163
        $formInput = []; // No user input available here.
164
        $update = $this->operation === 'update';
165
        $function = match(true) {
166
            $this->action === 'save' => $formInput['function'][$field->name] ?? '',
167
            $update && preg_match('~^CURRENT_TIMESTAMP~i', $field->onUpdate) => 'now',
168
            $value === false => null,
169
            $value !== null => '',
170
            default => 'NULL',
171
        };
172
        if ($this->action !== 'save' && !$update && $value === $field->default &&
173
            preg_match('~^[\w.]+\(~', $value ?? '')) {
174
            $function = 'SQL';
175
        }
176
        if (preg_match('~time~', $field->type) &&
177
            preg_match('~^CURRENT_TIMESTAMP~i', $value ?? '')) {
178
            $value = "";
179
            $function = "now";
180
        }
181
        if ($field->type === "uuid" && $value === "uuid()") {
182
            $value = "";
183
            $function = "uuid";
184
        }
185
186
        return [$value, $function];
187
    }
188
189
    /**
190
     * Get data for an input field
191
     *
192
     * @param TableFieldEntity $field
193
     * @param array|null $rowData
194
     *
195
     * @return FieldEditEntity
196
     */
197
    public function getFieldInputValues(TableFieldEntity $field, array|null $rowData): FieldEditEntity
198
    {
199
        $editField = new FieldEditEntity($field);
200
201
        // From html.inc.php: function edit_form(string $table, array $fields, $row, ?bool $update, string $error = '')
202
        $value = $this->getInputValue($field, $rowData);
203
        // if (!$this->action !== 'save' && is_string($value)) {
204
        //     $value = adminer()->editVal($value, $field);
205
        // }
206
        [$editField->value, $editField->function] = $this->getInputFunction($field, $value);
207
208
        // From html.inc.php: input(array $field, $value, ?string $function, ?bool $autofocus = false)
209
        $editField->name = $this->utils->html($this->driver->bracketEscape($field->name));
210
        $editField->fullType = $this->utils->html($field->fullType);
211
212
        if (is_array($editField->value) && !$editField->function) {
213
             // 128 - JSON_PRETTY_PRINT, 64 - JSON_UNESCAPED_SLASHES, 256 - JSON_UNESCAPED_UNICODE available since PHP 5.4
214
            $editField->value = json_encode($editField->value,
215
                JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
216
            $editField->function = 'json';
217
        }
218
219
        // Since mssql is not yet supported, $reset is always false.
220
        // $reset = $this->driver->jush() === 'mssql' && $field->autoIncrement;
221
        // if ($reset && $this->action !== 'save') {
222
        //     $editField->function = null;
223
        // }
224
225
        // $editField->functions = [];
226
        // if ($reset) {
227
        //     $editField->functions['orig'] = $this->utils->trans->lang('original');
228
        // }
229
        // $editField->functions = [...$editField->functions, ...$this->editFunctions($field)];
230
        $editField->functions = $this->editFunctions($field);
231
232
        $userType = $this->userTypes[$field->type] ?? null;
233
        $editField->enums = $userType?->enums ?? [];
234
        if ($editField->enums) {
235
            $editField->type = 'enum';
236
            $editField->field->length = $editField->enumsLength();
237
        }
238
239
        // Todo: process the output of tis function, which is available on MySQL only.
240
        // echo driver()->unconvertFunction($field) . " ";
241
242
        return $editField;
243
    }
244
}
245