Passed
Push — main ( 263507...cf95a9 )
by Thierry
01:46
created

QueryInputTrait::getDefaultInput()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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