Passed
Push — main ( d7e834...58bb3a )
by Thierry
01:48
created

QueryInputTrait::getMaxLength()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 4
eloc 5
c 2
b 0
f 0
nc 2
nop 1
dl 0
loc 8
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
     * 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 int
136
     */
137
    private function _getMaxLength(TableFieldEntity $field): int
138
    {
139
        // int(3) is only a display hint
140
        if (!preg_match('~int~', $field->type) &&
141
            preg_match('~^(\d+)(,(\d+))?$~', $field->length, $match)) {
142
            $length1 = preg_match("~binary~", $field->type) ? 2 : 1;
143
            $length2 = ($match[3] ?? false) ? 1 : 0;
144
            $length3 = ($match[2] ?? false) && !$field->unsigned ? 1 : 0;
145
            return $length1 * $match[1] + $length2 + $length3;
146
        }
147
        if ($this->driver->typeExists($field->type)) {
148
            return $this->driver->type($field->type) + ($field->unsigned ? 0 : 1);
149
        }
150
        return 0;
151
    }
152
153
    /**
154
     * @param TableFieldEntity $field
155
     *
156
     * @return int
157
     */
158
    private function getMaxLength(TableFieldEntity $field): int
159
    {
160
        $maxlength = $this->_getMaxLength($field);
161
        if ($this->driver->jush() == 'sql' && $this->driver->minVersion(5.6) &&
162
            preg_match('~time~', $field->type)) {
163
            return $maxlength + 7; // microtime
164
        }
165
        return $maxlength;
166
    }
167
168
    /**
169
     * @param TableFieldEntity $field
170
     * @param array $attrs
171
     *
172
     * @return void
173
     */
174
    private function setDataLength(TableFieldEntity $field, array &$attrs)
175
    {
176
        $maxlength = $this->getMaxLength($field);
177
        if ($maxlength > 0) {
178
            $attrs['data-maxlength'] = $maxlength;
179
        }
180
        if (preg_match('~char|binary~', $field->type) && $maxlength > 20) {
181
            $attrs['size'] = 40;
182
        }
183
    }
184
185
    /**
186
     * @param TableFieldEntity $field
187
     * @param array $attrs
188
     *
189
     * @return void
190
     */
191
    private function setDataType(TableFieldEntity $field, array &$attrs)
192
    {
193
        // type='date' and type='time' display localized value which may be confusing,
194
        // type='datetime' uses 'T' as date and time separator
195
        if (preg_match('~(?<!o)int(?!er)~', $field->type) && !preg_match('~\[\]~', $field->fullType)) {
196
            $attrs['type'] = 'number';
197
        }
198
    }
199
200
    /**
201
     * @param TableFieldEntity $field
202
     * @param array $attrs
203
     * @param mixed $value
204
     * @param string|null $function
205
     * @param array $functions
206
     *
207
     * @return array
208
     */
209
    private function getDefaultInput(TableFieldEntity $field, array $attrs, $value, $function, array $functions): array
210
    {
211
        $this->setDataLength($field, $attrs);
212
        $hasFunction = (in_array($function, $functions) || isset($functions[$function]));
213
        if (!$hasFunction || $function === "") {
214
            $this->setDataType($field, $attrs);
215
        }
216
        $attrs['value'] = $this->util->html($value);
217
        return ['type' => 'input', 'attrs' => $attrs];
218
    }
219
220
    /**
221
     * @param TableFieldEntity $field
222
     * @param string $name
223
     * @param mixed $value
224
     * @param string|null $function
225
     * @param array $functions
226
     * @param array $options
227
     *
228
     * @return array
229
     */
230
    private function getEntryInput(TableFieldEntity $field, string $name, $value, $function, array $functions, array $options): array
231
    {
232
        $attrs = ['name' => "fields[$name]"];
233
        if ($field->type == "enum") {
234
            return ['type' => 'radio', 'attrs' => $attrs,
235
                'values' => $this->getEnumValues($field, isset($options["select"]), $value)];
236
        }
237
        if (preg_match('~bool~', $field->type)) {
238
            $attrs['checked'] = preg_match('~^(1|t|true|y|yes|on)$~i', $value);
239
            return ['type' => 'bool', 'attrs' => $attrs];
240
        }
241
        if ($field->type == "set") {
242
            return $this->getSetInput($field, $attrs, $value);
243
        }
244
        if (preg_match('~blob|bytea|raw|file~', $field->type) && $this->util->iniBool("file_uploads")) {
245
            $attrs['name'] = "fields-$name";
246
            return ['type' => 'file', 'attrs' => $attrs];
247
        }
248
        if (preg_match('~text|lob|memo~i', $field->type) || preg_match("~\n~", $value)) {
249
            return $this->getBlobInput($field, $attrs, $value);
250
        }
251
        if ($function == "json" || preg_match('~^jsonb?$~', $field->type)) {
252
            $attrs['cols'] = 50;
253
            $attrs['rows'] = 12;
254
            return ['type' => 'textarea', 'attrs' => $attrs, 'value' => $this->util->html($value)];
255
        }
256
        return $this->getDefaultInput($field, $attrs, $value, $function, $functions);
257
    }
258
}
259