DataFieldInput::getInputFieldMaxLength()   F
last analyzed

Complexity

Conditions 12
Paths 1536

Size

Total Lines 20
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 15
nc 1536
nop 1
dl 0
loc 20
rs 2.8
c 1
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Lagdo\DbAdmin\Db\Page\Dml;
4
5
use Lagdo\DbAdmin\Db\Page\AppPage;
6
use Lagdo\DbAdmin\Driver\DriverInterface;
7
use Lagdo\DbAdmin\Driver\Utils\Utils;
8
9
use function count;
10
use function explode;
11
use function in_array;
12
use function is_array;
13
use function is_string;
14
use function min;
15
use function preg_match;
16
use function preg_match_all;
17
use function stripcslashes;
18
use function str_replace;
19
use function substr_count;
20
21
/**
22
 * Make data for HTML elements in the user forms for data row insert and update.
23
 */
24
class DataFieldInput
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
39
    /**
40
     * @param FieldEditEntity $editField
41
     * @param string $fieldName
42
     * @param string|null $enumValue
43
     *
44
     * @return array
45
     */
46
    private function getCheckedAttr(FieldEditEntity $editField, string $fieldName, string|null $enumValue): array
47
    {
48
        $checked = is_array($editField->value) ?
49
            in_array($fieldName, $editField->value) : $editField->value === $enumValue;
50
        return $checked ? ['checked' => 'checked'] : [];
51
    }
52
53
    /**
54
     * Get data for enum or set input field
55
     * 
56
     * @param FieldEditEntity $editField
57
     */
58
    private function itemList(FieldEditEntity $editField, array $attrs, string $default = ""): array|null
59
    {
60
        if ($editField->type !== 'enum' && $editField->type !== 'set' ) {
61
            // Only for enums and sets
62
            return null;
63
        }
64
65
        // From html.inc.php: function enum_input(string $type, string $attrs, array $field, $value, string $empty = "")
66
        $prefix = $editField->type === 'enum' ? 'val-' : '';
67
        $items = [];
68
        if ($editField->field->null && $prefix) {
69
            $checkedAttr = $this->getCheckedAttr($editField, 'null', null);
70
            $items[] = [
71
                'attrs' => [
72
                    ...$attrs,
73
                    'id' => "{$attrs['id']}_null", // Overwrite the id value in the $attrs array.
74
                    ...$checkedAttr,
75
                ],
76
                'label' => "<i>$default</i>",
77
                'value' => 'null',
78
            ];
79
        }
80
81
        preg_match_all("~'((?:[^']|'')*)'~", $editField->field->length, $matches);
82
        foreach (($matches[1] ?? []) as $enumValue) {
83
            $enumValue = stripcslashes(str_replace("''", "'", $enumValue));
84
            $fieldName = "$prefix$enumValue";
85
            $checkedAttr = $this->getCheckedAttr($editField, $fieldName, $enumValue);
86
            $items[] = [
87
                'attrs' => [
88
                    ...$attrs,
89
                    'id' => "{$attrs['id']}_{$enumValue}", // Overwrite the id value in the $attrs array.
90
                    ...$checkedAttr,
91
                ],
92
                'label' => $this->utils->html($enumValue),
93
                'value' => $this->utils->html($fieldName),
94
            ];
95
        }
96
97
        return $items;
98
    }
99
100
    /**
101
     * @param FieldEditEntity $editField
102
     * @param array $attrs
103
     *
104
     * @return array
105
     */
106
    private function getEnumFieldInput(FieldEditEntity $editField, array $attrs): array
107
    {
108
        // From adminer.inc.php: function editInput(?string $table, array $field, string $attrs, $value): string
109
        $values = ['field' => 'enum'];
110
        if ($this->action === 'select') {
111
            $values['orig'] = [
112
                'attrs' => [
113
                    ...$attrs,
114
                    'checked' => 'checked',
115
                ],
116
                'label' => '<i>' . $this->utils->trans->lang('original') . '</i>',
117
                'value' => 'orig',
118
            ];
119
        }
120
        $values['items'] = $this->itemList($editField, $attrs, 'NULL');
121
122
        return $values;
123
    }
124
125
    /**
126
     * @param FieldEditEntity $editField
127
     * @param array $attrs
128
     *
129
     * @return array
130
     */
131
    private function getSetFieldInput(FieldEditEntity $editField, array $attrs): array
132
    {
133
        if (is_string($editField->value)) {
134
            $editField->value = explode(",", $editField->value);
135
        }
136
137
        return [
138
            'field' => 'set',
139
            'items' => $this->itemList($editField, $attrs),
140
        ];
141
    }
142
143
    /**
144
     * @param FieldEditEntity $editField
145
     * @param array $attrs
146
     *
147
     * @return array
148
     */
149
    private function getBoolFieldInput(FieldEditEntity $editField, array $attrs): array
150
    {
151
        $checkedAttr = $editField->isChecked() ? ['checked' => 'checked'] : [];
152
        return [
153
            'field' => 'bool',
154
            'attrs' => [
155
                'hidden' => [
156
                    ...$attrs,
157
                    'id' => '', // Unset the id value in the $attrs array
158
                    'value' => '0',
159
                ],
160
                'checkbox' => [
161
                    ...$attrs,
162
                    'value' => '1',
163
                    ...$checkedAttr,
164
                ],
165
            ],
166
        ];
167
    }
168
169
    /**
170
     * @param FieldEditEntity $editField
171
     *
172
     * @return bool
173
     */
174
    private function isBlob(FieldEditEntity $editField): bool
175
    {
176
        return $this->utils->isBlob($editField->field) && $this->utils->iniBool("file_uploads");
177
    }
178
179
    /**
180
     * @param FieldEditEntity $editField
181
     * @param array $attrs
182
     *
183
     * @return array
184
     */
185
    private function getFileFieldInput(FieldEditEntity $editField, array $attrs): array
186
    {
187
        return [
188
            'field' => 'file',
189
            'attrs' => [
190
                'id' => $attrs['id'],
191
                'name' => "fields-{$editField->name}",
192
            ],
193
        ];
194
    }
195
196
    /**
197
     * @param FieldEditEntity $editField
198
     * @param array $attrs
199
     *
200
     * @return array
201
     */
202
    private function getJsonFieldInput(FieldEditEntity $editField, array $attrs): array
203
    {
204
        return [
205
            'field' => 'json',
206
            'attrs' => [
207
                ...$attrs,
208
                'cols' => '50',
209
                'rows' => '5',
210
                'class' => 'jush-js',
211
            ],
212
            'value' => $this->utils->str->html($editField->value ?? ''),
213
        ];
214
    }
215
216
    /**
217
     * @param FieldEditEntity $editField
218
     *
219
     * @return bool
220
     */
221
    private function textSizeIsFixed(FieldEditEntity $editField): bool
222
    {
223
        return ($editField->isText() && $this->driver->jush() !== 'sqlite') || $editField->isSearch();
224
    }
225
226
    /**
227
     * @param FieldEditEntity $editField
228
     * @param array $attrs
229
     *
230
     * @return array
231
     */
232
    private function getTextFieldInput(FieldEditEntity $editField, array $attrs): array
233
    {
234
        $fieldAttrs = $this->textSizeIsFixed($editField) ? [
235
            'cols' => '50',
236
            'rows' => '5',
237
        ] : [
238
            'cols' => '30',
239
            'rows' => min(5, substr_count($editField->value ?? '', "\n") + 1),
240
        ];
241
        return [
242
            'field' => 'text',
243
            'attrs' => [
244
                ...$attrs,
245
                ...$fieldAttrs,
246
            ],
247
            'value' => $this->utils->html($editField->value ?? ''),
248
        ];
249
    }
250
251
    /**
252
     * @param FieldEditEntity $editField
253
     *
254
     * @return int
255
     */
256
    private function getInputFieldMaxLength(FieldEditEntity $editField): int
257
    {
258
        $unsigned = $editField->field->unsigned;
259
        $length = $editField->field->length;
260
        $type = $editField->type;
261
        $types = $this->driver->types();
262
263
        $maxlength = (!preg_match('~int~', $type) &&
264
            preg_match('~^(\d+)(,(\d+))?$~', $length, $match) ?
265
            ((preg_match("~binary~", $type) ? 2 : 1) *
266
                ($match[1] ?? 0) + (($match[3] ?? false) ? 1 : 0) +
267
                (($match[2] ?? false) && !$unsigned ? 1 : 0)) :
268
            (isset($types[$type]) ? $types[$type] + ($unsigned ? 0 : 1) : 0)
269
        );
270
271
        return $this->driver->jush() === 'sql' &&
272
            $this->driver->minVersion(5.6) &&
273
            preg_match('~time~', $type) ?
274
                $maxlength += 7 : // microtime
275
                $maxlength;
276
    }
277
278
    /**
279
     * @param FieldEditEntity $editField
280
     * @param array $attrs
281
     *
282
     * @return array
283
     */
284
    private function getDefaultFieldInput(FieldEditEntity $editField, array $attrs): array
285
    {
286
        $maxlength = $this->getInputFieldMaxLength($editField);
287
        // type='date' and type='time' display localized value which may be confusing,
288
        // type='datetime' uses 'T' as date and time separator
289
290
        if ($editField->isNumber()) {
291
            $attrs['type'] = 'number';
292
        }
293
        if ($maxlength > 0) {
294
            $attrs['data-maxlength'] = $maxlength;
295
        }
296
        if ($editField->bigSize($maxlength)) {
297
            $attrs['size'] = $maxlength > 99 ? '60' : '40';
298
        }
299
300
        return [
301
            'field' => 'input',
302
            'attrs' => $attrs,
303
            'value' => $this->utils->html($editField->value ?? ''),
304
        ];
305
    }
306
307
    /**
308
     * Get the input field for value
309
     *
310
     * @param FieldEditEntity $editField
311
     * @param bool|null $autofocus
312
     *
313
     * @return array
314
     */
315
    private function getFieldValueInput(FieldEditEntity $editField, bool|null $autofocus): array
316
    {
317
        // From input(array $field, $value, ?string $function, ?bool $autofocus = false) in html.inc.php
318
        $attrs = [
319
            'id' => "fields_{$editField->name}",
320
            'name' => $editField->isEnum() || $editField->isSet() ?
321
                "fields[{$editField->name}][]" : "fields[{$editField->name}]",
322
        ];
323
        if ($editField->isDisabled()) {
324
            $attrs['disabled'] = 'disabled';
325
        }
326
        if ($autofocus) {
327
            $attrs['autofocus'] = true;
328
        }
329
330
        // This function is implemented only for MySQL.
331
        // Todo: check what it actually does.
332
        // echo driver()->unconvertFunction($field) . " ";
333
334
        return match(true) {
335
            $editField->isEnum() => $this->getEnumFieldInput($editField, $attrs),
336
            $editField->isBool() => $this->getBoolFieldInput($editField, $attrs),
337
            $editField->isSet() => $this->getSetFieldInput($editField, $attrs),
338
            $this->isBlob($editField) => $this->getFileFieldInput($editField, $attrs),
339
            $editField->isJson() => $this->getJsonFieldInput($editField, $attrs),
340
            $editField->editText() => $this->getTextFieldInput($editField, $attrs),
341
            default => $this->getDefaultFieldInput($editField, $attrs),
342
        };
343
    }
344
345
    /**
346
     * Get the input field for function
347
     *
348
     * @param FieldEditEntity $editField
349
     *
350
     * @return array|null
351
     */
352
    private function getFieldFunctionInput(FieldEditEntity $editField): array|null
353
    {
354
        // From html.inc.php: function input(array $field, $value, ?string $function, ?bool $autofocus = false)
355
        if ($editField->type === 'enum' || $editField->function === null) {
356
            return null; // No function for enum values
357
        }
358
359
        if (count($editField->functions) < 2) {
360
            return [
361
                'label' => $this->utils->str->html($editField->functions[0] ?? ''),
362
            ];
363
        }
364
365
        $disabledAttr = $editField->isDisabled() ? ['disabled' => 'disabled'] : [];
366
        return [
367
            'select' => [
368
                'attrs' => [
369
                    'name' => "function[{$editField->name}]",
370
                    ...$disabledAttr,
371
                ],
372
                'options' => $editField->functions,
373
                'value' => $editField->functionValue(),
374
            ],
375
        ];
376
    }
377
378
    /**
379
     * @param FieldEditEntity $editField
380
     * @param bool|null $autofocus
381
     *
382
     * @return void
383
     */
384
    public function setFieldInputValues(FieldEditEntity $editField, bool|null $autofocus): void
385
    {
386
        $editField->functionInput = $this->getFieldFunctionInput($editField);
387
        $editField->valueInput = $this->getFieldValueInput($editField, $autofocus);
388
    }
389
}
390