Passed
Push — main ( 37b358...598588 )
by Thierry
02:02
created

QueryInputTrait::getEntryInput()   B

Complexity

Conditions 10
Paths 7

Size

Total Lines 24
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

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