Passed
Push — main ( 20361b...6d1b9c )
by Thierry
06:44 queued 04:24
created

DataFieldValue::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 5
dl 0
loc 4
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
10
use function bin2hex;
11
use function implode;
12
use function is_array;
13
use function is_bool;
14
use function preg_match;
15
16
/**
17
 * Writes data in the user forms for data row insert and update.
18
 */
19
class DataFieldValue
20
{
21
    /**
22
     * @var bool
23
     */
24
    private bool $isUpdate = false;
25
26
    /**
27
     * The constructor
28
     *
29
     * @param AppPage $page
30
     * @param DriverInterface $driver
31
     * @param Utils $utils
32
     * @param string $action
33
     * @param string $operation
34
     */
35
    public function __construct(private AppPage $page, private DriverInterface $driver,
36
        private Utils $utils, private string $action, private string $operation)
37
    {
38
        $this->isUpdate = $operation === 'update';
39
    }
40
41
    /**
42
     * @param array $names
43
     * @param array $functions
44
     * @param bool $addSql
45
     * @param TableFieldEntity $field
46
     *
47
     * @return array
48
     */
49
    private function addEditFunctions(array $names, array $functions, TableFieldEntity $field): array
50
    {
51
        foreach ($functions as $pattern => $_functions) {
52
            if (!$pattern || preg_match("~$pattern~", $field->type)) {
53
                $names = [...$names, ...$_functions]; // Array merge
54
            }
55
        }
56
        return $names;
57
    }
58
59
    /**
60
     * Functions displayed in edit form
61
     * function editFunctions() in adminer.inc.php
62
     *
63
     * @param TableFieldEntity $field Single field from fields()
64
     *
65
     * @return array
66
     */
67
    private function editFunctions(TableFieldEntity $field): array
68
    {
69
        if ($field->autoIncrement && !$this->isUpdate) {
70
            return [$this->utils->trans->lang('Auto Increment')];
71
        }
72
73
        $names = $field->null ? ['NULL', ''] : [''];
74
        $functions = $this->driver->insertFunctions();
75
        $names = $this->addEditFunctions($names, $functions, $field);
76
77
        $functions = $this->driver->editFunctions();
78
        if (/*!isset($this->utils->input->values['call']) &&*/ $this->isUpdate) { // relative functions
79
            $names = $this->addEditFunctions($names, $functions, $field);
80
        }
81
82
        $structuredTypes = $this->driver->structuredTypes();
83
        $userTypes = $structuredTypes[$this->utils->trans->lang('User types')] ?? [];
84
        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...
85
            !$this->utils->isBlob($field, $userTypes)) {
0 ignored issues
show
Bug introduced by
The method isBlob() does not exist on Lagdo\DbAdmin\Driver\Utils\Utils. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

85
            !$this->utils->/** @scrutinizer ignore-call */ isBlob($field, $userTypes)) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

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

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

225
        /** @scrutinizer ignore-call */ 
226
        $editField->enums = $this->driver->enumValues($field);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
226
        if ($editField->enums) {
227
            $editField->type = 'enum';
228
            $editField->field->length = $editField->enumsLength();
229
        }
230
231
        // Todo: process the output of tis function, which is available on MySQL only.
232
        // echo driver()->unconvertFunction($field) . " ";
233
234
        return $editField;
235
    }
236
}
237