QueryInputTrait::getEnumItemValue()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 4
nop 3
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Lagdo\DbAdmin\Db\Facades\Traits;
4
5
use Lagdo\DbAdmin\Driver\Entity\TableFieldEntity;
6
7
use function is_array;
8
use function in_array;
9
use function reset;
10
use function count;
11
use function preg_match;
12
use function preg_match_all;
13
use function stripcslashes;
14
use function str_replace;
15
use function is_int;
16
use function explode;
17
use function substr_count;
18
use function min;
19
use function array_pad;
20
21
trait QueryInputTrait
22
{
23
    /**
24
     * @param TableFieldEntity $field
25
     * @param string $name
26
     * @param string|null $function
27
     * @param array $functions
28
     *
29
     * @return array
30
     */
31
    private function getEntryFunctions(TableFieldEntity $field, string $name, ?string $function, array $functions): array
32
    {
33
        // Input for functions
34
        if ($field->type === 'enum') {
35
            return [
36
                'type' => 'name',
37
                'name' => $this->utils->str->html($functions[''] ?? ''),
38
            ];
39
        }
40
        if (count($functions) > 1) {
41
            $hasFunction = (in_array($function, $functions) || isset($functions[$function]));
42
            return [
43
                'type' => 'select',
44
                'name' => "function[$name]",
45
                'options' => $functions,
46
                'selected' => $function === null || $hasFunction ? $function : '',
47
            ];
48
        }
49
        return [
50
            'type' => 'name',
51
            'name' => $this->utils->str->html(reset($functions)),
52
        ];
53
    }
54
55
    /**
56
     * @param string $val
57
     * @param int $i
58
     * @param mixed $value
59
     *
60
     * @return array
61
     */
62
    private function getEnumItemValue(string $val, int $i, $value): array
63
    {
64
        $val = stripcslashes(str_replace("''", "'", $val));
65
        $checked = (is_int($value) ? $value == $i + 1 :
66
            (is_array($value) ? in_array($i+1, $value) : $value === $val));
67
        return ['value' => $i + 1, 'checked' => $checked, 'text' => $this->utils->str->html($val)];
68
    }
69
70
    /**
71
     * @param TableFieldEntity $field
72
     * @param bool $select
73
     * @param mixed $value
74
     *
75
     * @return array
76
     */
77
    private function getEnumValues(TableFieldEntity $field, bool $select, $value): array
78
    {
79
        $values = [];
80
        if (($select)) {
81
            $values[] = ['value' => '-1', 'checked' => true,
82
                'text' => '<i>' . $this->utils->trans->lang('original') . '</i>'];
83
        }
84
        if ($field->null) {
85
            $values[] =  ['value' => '', 'checked' => $value === null && !$select, 'text' => '<i>NULL</i>'];
86
        }
87
88
        // From functions.inc.php (function enum_input())
89
        $empty = 0; // 0 - empty
90
        $values[] = ['value' => $empty, 'checked' => is_array($value) ? in_array($empty, $value) : $value === 0,
91
            'text' => '<i>' . $this->utils->trans->lang('empty') . '</i>'];
92
93
        preg_match_all("~'((?:[^']|'')*)'~", $field->fullType, $matches);
94
        foreach ($matches[1] as $i => $val) {
95
            $values[] = $this->getEnumItemValue($val, $i, $value);
96
        }
97
98
        return $values;
99
    }
100
101
    /**
102
     * @param TableFieldEntity $field
103
     * @param array $attrs
104
     * @param mixed $value
105
     *
106
     * @return array
107
     */
108
    private function getSetInput(TableFieldEntity $field, array $attrs, $value): array
109
    {
110
        $values = [];
111
        preg_match_all("~'((?:[^']|'')*)'~", $field->length, $matches);
112
        foreach ($matches[1] as $i => $val) {
113
            $val = stripcslashes(str_replace("''", "'", $val));
114
            $checked = (is_int($value) ? ($value >> $i) & 1 : in_array($val, explode(',', $value), true));
115
            $values[] = ['value=' => (1 << $i), 'checked' => $checked, 'text' => $this->utils->str->html($val)];
116
        }
117
        return ['type' => 'checkbox', 'attrs' => $attrs, 'values' => $values];
118
    }
119
120
    /**
121
     * @param TableFieldEntity $field
122
     * @param array $attrs
123
     * @param mixed $value
124
     *
125
     * @return array
126
     */
127
    private function getBlobInput(TableFieldEntity $field, array $attrs, $value): array
128
    {
129
        if (preg_match('~text|lob|memo~i', $field->type) && $this->driver->jush() !== 'sqlite') {
130
            $attrs['cols'] = 50;
131
            $attrs['rows'] = 12;
132
        } else {
133
            $rows = min(12, substr_count($value, "\n") + 1);
134
            $attrs['cols'] = 30;
135
            $attrs['rows'] = $rows;
136
            if ($rows == 1) {
137
                $attrs['style'] = 'height: 1.2em;';
138
            }
139
        }
140
        return ['type' => 'textarea', 'attrs' => $attrs, 'value' => $this->utils->str->html($value)];
141
    }
142
143
    /**
144
     * @param TableFieldEntity $field
145
     *
146
     * @return int
147
     */
148
    private function getLengthValue(TableFieldEntity $field): int
149
    {
150
        // int(3) is only a display hint
151
        if (!preg_match('~int~', $field->type) &&
152
            preg_match('~^(\d+)(,(\d+))?$~', $field->length, $match)) {
153
            $match = array_pad($match, 4, false);
154
            $length1 = preg_match('~binary~', $field->type) ? 2 : 1;
155
            $length2 = empty($match[3]) ? 0 : 1;
156
            $length3 = empty($match[2]) || $field->unsigned ? 0 : 1;
157
            return $length1 * $match[1] + $length2 + $length3;
158
        }
159
        if ($this->driver->typeExists($field->type)) {
160
            return $this->driver->type($field->type) + ($field->unsigned ? 0 : 1);
161
        }
162
        return 0;
163
    }
164
165
    /**
166
     * @param TableFieldEntity $field
167
     *
168
     * @return int
169
     */
170
    private function getMaxLength(TableFieldEntity $field): int
171
    {
172
        $maxlength = $this->getLengthValue($field);
173
        if ($this->driver->jush() == 'sql' && $this->driver->minVersion(5.6) &&
174
            preg_match('~time~', $field->type)) {
175
            return $maxlength + 7; // microtime
176
        }
177
        return $maxlength;
178
    }
179
180
    /**
181
     * @param TableFieldEntity $field
182
     * @param array $attrs
183
     *
184
     * @return void
185
     */
186
    private function setDataLength(TableFieldEntity $field, array &$attrs)
187
    {
188
        $maxlength = $this->getMaxLength($field);
189
        if ($maxlength > 0) {
190
            $attrs['data-maxlength'] = $maxlength;
191
        }
192
        if (preg_match('~char|binary~', $field->type) && $maxlength > 20) {
193
            $attrs['size'] = 40;
194
        }
195
    }
196
197
    /**
198
     * @param TableFieldEntity $field
199
     * @param array $attrs
200
     *
201
     * @return void
202
     */
203
    private function setDataType(TableFieldEntity $field, array &$attrs)
204
    {
205
        // type='date' and type='time' display localized value which may be confusing,
206
        // type='datetime' uses 'T' as date and time separator
207
        if (preg_match('~(?<!o)int(?!er)~', $field->type) && !preg_match('~\[\]~', $field->fullType)) {
208
            $attrs['type'] = 'number';
209
        }
210
    }
211
212
    /**
213
     * @param TableFieldEntity $field
214
     * @param array $attrs
215
     * @param mixed $value
216
     * @param string|null $function
217
     * @param array $functions
218
     *
219
     * @return array
220
     */
221
    private function getDefaultInput(TableFieldEntity $field, array $attrs, $value, $function, array $functions): array
222
    {
223
        $this->setDataLength($field, $attrs);
224
        $hasFunction = (in_array($function, $functions) || isset($functions[$function]));
225
        if (!$hasFunction || $function === '') {
226
            $this->setDataType($field, $attrs);
227
        }
228
        $attrs['value'] = $this->utils->str->html($value);
229
        return ['type' => 'input', 'attrs' => $attrs];
230
    }
231
232
    /**
233
     * @param TableFieldEntity $field
234
     * @param string $name
235
     * @param mixed $value
236
     * @param string|null $function
237
     * @param array $functions
238
     * @param array $options
239
     *
240
     * @return array
241
     */
242
    private function getEntryInput(TableFieldEntity $field, string $name, $value,
243
        ?string $function, array $functions, array $options): array
244
    {
245
        $attrs = ['name' => "fields[$name]"];
246
        if ($field->type === 'enum') {
247
            return ['type' => 'radio', 'attrs' => $attrs,
248
                'values' => $this->getEnumValues($field, isset($options['select']), $value)];
249
        }
250
        if (preg_match('~bool~', $field->type)) {
251
            $attrs['checked'] = preg_match('~^(1|t|true|y|yes|on)$~i', $value);
252
            return ['type' => 'bool', 'attrs' => $attrs];
253
        }
254
        if ($field->type === 'set') {
255
            return $this->getSetInput($field, $attrs, $value);
256
        }
257
        if (preg_match('~blob|bytea|raw|file~', $field->type) && $this->admin->iniBool('file_uploads')) {
258
            $attrs['name'] = "fields-$name";
259
            return ['type' => 'file', 'attrs' => $attrs];
260
        }
261
        if (preg_match('~text|lob|memo~i', $field->type) || preg_match("~\n~", $value ?? '')) {
262
            return $this->getBlobInput($field, $attrs, $value);
263
        }
264
        if ($function === 'json' || preg_match('~^jsonb?$~', $field->type)) {
265
            $attrs['cols'] = 50;
266
            $attrs['rows'] = 12;
267
            return ['type' => 'textarea', 'attrs' => $attrs, 'value' => $this->utils->str->html($value)];
268
        }
269
        return $this->getDefaultInput($field, $attrs, $value, $function, $functions);
270
    }
271
}
272