Passed
Push — main ( bf9e72...58a826 )
by Thierry
02:02
created

QueryInputTrait::setDataLength()   B

Complexity

Conditions 7
Paths 8

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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