Form::getField()   B
last analyzed

Complexity

Conditions 10
Paths 18

Size

Total Lines 25
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 15
c 1
b 0
f 0
dl 0
loc 25
rs 7.6666
cc 10
nc 18
nop 5

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
/**
4
 * KumbiaPHP web & app Framework
5
 *
6
 * LICENSE
7
 *
8
 * This source file is subject to the new BSD license that is bundled
9
 * with this package in the file LICENSE.
10
 *
11
 * @category   KumbiaPHP
12
 * @package    Helpers
13
 *
14
 * @copyright  Copyright (c) 2005 - 2023 KumbiaPHP Team (http://www.kumbiaphp.com)
15
 * @license    https://github.com/KumbiaPHP/KumbiaPHP/blob/master/LICENSE   New BSD License
16
 */
17
/**
18
 * Helper para Formularios.
19
 *
20
 * @category   KumbiaPHP
21
 */
22
class Form
23
{
24
    /**
25
     * Utilizado para generar los id de los radio button,
26
     * lleva un conteo interno.
27
     *
28
     * @var array
29
     */
30
    protected static $radios = array();
31
32
    /**
33
     * Utilizado para avisar al programador,si usa Form::file()
34
     * y no tiene el form mulipart muestra un error.
35
     *
36
     * @var bool
37
     */
38
    protected static $multipart = false;
39
40
    /**
41
     * Obtiene el valor de un componente tomado
42
     * del mismo valor del nombre del campo y formulario
43
     * que corresponda a un atributo del mismo nombre
44
     * que sea un string, objeto o array.
45
     *
46
     * @param string $field
47
     * @param mixed  $value    valor de campo
48
     * @param bool   $filter   filtrar caracteres especiales html
49
     * @param bool   $check    si esta marcado el checkbox
50
     * @param bool   $is_check
51
     *
52
     * @return array devuelve un array de longitud 3 con la forma array(id, name, value)
53
     */
54
    public static function getField($field, $value = null, $is_check = false, $filter = true, $check = false)
55
    {
56
        // Obtiene considerando el patrón de formato form.field
57
        $formField = explode('.', $field, 2);
58
        [$id, $name] = self::fieldName($formField);
59
        // Verifica en $_POST
60
        if (Input::hasPost($field)) {
61
            $value = $is_check ?
62
                Input::post($field) == $value : Input::post($field);
63
        } elseif ($is_check) {
64
            $value = $check;
65
        } elseif ($tmp_val = self::getFromModel($formField)) {
66
            // Autocarga de datos
67
            $value = $is_check ? $tmp_val == $value : $tmp_val;
0 ignored issues
show
introduced by
The condition $is_check is always false.
Loading history...
68
        }
69
        // Filtrar caracteres especiales
70
        if (!$is_check && $value !== null && $filter) {
71
            if (is_array($value)) {
72
                $value = self::filterArrayValues($value);
73
            } else {
74
                $value = htmlspecialchars($value, ENT_COMPAT, APP_CHARSET);
75
            }
76
        }
77
        // Devuelve los datos
78
        return array($id, $name, $value);
79
    }
80
81
    private static function filterArrayValues(array $array)
82
    {
83
        foreach ($array as &$value) {
84
            if (is_array($value)) {
85
                $value = self::filterArrayValues($value);
86
            } else {
87
                $value = htmlspecialchars($value, ENT_COMPAT, APP_CHARSET);
88
            }
89
        }
90
        return $array;
91
    }
92
93
    /**
94
     * Devuelve el valor del modelo.
95
     *
96
     * @param array $formField array [modelo, campo]
97
     *
98
     * @return mixed
99
     */
100
    protected static function getFromModel(array $formField)
101
    {
102
        $form = View::getVar($formField[0]);
103
        if (is_scalar($form) || is_null($form)) {
104
            return $form;
105
        }
106
        $form = (object) $form;
107
108
        return $form->{$formField[1]} ?? null;
109
    }
110
111
    /**
112
     * Devuelve el nombre y el id de un campo.
113
     *
114
     * @param array $field array del explode
115
     *
116
     * @return array array(id, name)
117
     */
118
    protected static function fieldName(array $field)
119
    {
120
        return isset($field[1]) ?
121
            array("{$field[0]}_{$field[1]}", "{$field[0]}[{$field[1]}]") : array($field[0], $field[0]);
122
    }
123
124
    /**
125
     * Obtiene el valor de un componente tomado
126
     * del mismo valor del nombre del campo y formulario
127
     * que corresponda a un atributo del mismo nombre
128
     * que sea un string, objeto o array.
129
     *
130
     * @param string $field
131
     * @param mixed  $value  valor de campo
132
     * @param bool   $filter filtrar caracteres especiales html
133
     *
134
     * @return array devuelve un array de longitud 3 con la forma array(id, name, value)
135
     */
136
    public static function getFieldData($field, $value = null, $filter = true)
137
    {
138
        return self::getField($field, $value, false, $filter);
139
    }
140
141
    /**
142
     * Obtiene el valor de un componente check tomado
143
     * del mismo valor del nombre del campo y formulario
144
     * que corresponda a un atributo del mismo nombre
145
     * que sea un string, objeto o array.
146
     *
147
     * @param string $field
148
     * @param string $checkValue
149
     * @param bool   $checked
150
     *
151
     * @return array Devuelve un array de longitud 3 con la forma array(id, name, checked);
152
     */
153
    public static function getFieldDataCheck($field, $checkValue, $checked = false)
154
    {
155
        return self::getField($field, $checkValue, true, false, $checked);
156
    }
157
158
    /**
159
     * @param string       $tag
160
     * @param string       $field
161
     * @param string       $value
162
     * @param string|array $attrs
163
     */
164
    protected static function tag($tag, $field, $attrs = '', $value = '', $extra = '', $close = true)
165
    {
166
        $attrs = Tag::getAttrs($attrs);
167
        $end = $close ? ">{{value}}</$tag>" : '/>';
168
        // Obtiene name, id y value (solo para autoload) para el campo y los carga en el scope
169
        [$id, $name, $value] = self::getFieldData($field, $value);
170
171
        return str_replace('{{value}}', (string) $value, "<$tag id=\"$id\" name=\"$name\" $extra $attrs $end");
172
    }
173
174
    /*
175
     * Crea un campo input
176
     *
177
     * @param string|array $attrs Atributos de campo (opcional)
178
     * @param string $type
179
     * @param string $field
180
     * @param string $value
181
     * @return string
182
     */
183
    public static function input($type, $field, $attrs = '', $value = '')
184
    {
185
        return self::tag('input', $field, $attrs, $value, "type=\"$type\" value=\"{{value}}\"", false);
186
    }
187
188
    /**
189
     * Crea una etiqueta de formulario.
190
     *
191
     * @param string $action Acción del formulario (opcional)
192
     * @param string $method Por defecto es post (opcional)
193
     * @param string $attrs  Atributos de etiqueta (opcional)
194
     *
195
     * @return string
196
     */
197
    public static function open($action = '', $method = 'post', $attrs = '')
198
    {
199
        $attrs = Tag::getAttrs($attrs);
200
        if ($action) {
201
            $action = PUBLIC_PATH . $action;
202
        } else {
203
            $action = PUBLIC_PATH . ltrim(Router::get('route'), '/');
0 ignored issues
show
Bug introduced by
It seems like Router::get('route') can also be of type array; however, parameter $string of ltrim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

203
            $action = PUBLIC_PATH . ltrim(/** @scrutinizer ignore-type */ Router::get('route'), '/');
Loading history...
204
        }
205
206
        return "<form action=\"$action\" method=\"$method\" $attrs>";
207
    }
208
209
    /**
210
     * Crea una etiqueta de formulario multipart.
211
     *
212
     * @param string       $action Acción del formulario (opcional)
213
     * @param string|array $attrs  Atributos de etiqueta (opcional)
214
     *
215
     * @return string
216
     */
217
    public static function openMultipart($action = null, $attrs = '')
218
    {
219
        self::$multipart = true;
220
        if (is_array($attrs)) {
221
            $attrs['enctype'] = 'multipart/form-data';
222
            $attrs = Tag::getAttrs($attrs);
223
        } else {
224
            $attrs .= ' enctype="multipart/form-data"';
225
        }
226
227
        return self::open($action, 'post', $attrs);
228
    }
229
230
    /**
231
     * Crea una etiqueta para cerrar un formulario.
232
     *
233
     * @return string
234
     */
235
    public static function close()
236
    {
237
        self::$multipart = false;
238
239
        return '</form>';
240
    }
241
242
    /**
243
     * Crea un botón de submit para el formulario actual.
244
     *
245
     * @param string       $text  Texto del botón
246
     * @param string|array $attrs Atributos de campo (opcional)
247
     *
248
     * @return string
249
     */
250
    public static function submit($text, $attrs = '')
251
    {
252
        return self::button($text, $attrs, 'submit');
253
    }
254
255
    /**
256
     * Crea un botón reset.
257
     *
258
     * @param string       $text  Texto del botón
259
     * @param string|array $attrs Atributos de campo (opcional)
260
     *
261
     * @return string
262
     */
263
    public static function reset($text, $attrs = '')
264
    {
265
        return self::button($text, $attrs, 'reset');
266
    }
267
268
    /**
269
     * Crea un botón.
270
     *
271
     * @param string       $text  Texto del botón
272
     * @param array|string $attrs Atributos de campo (opcional)
273
     * @param string       $type  tipo de botón
274
     * @param string       $value Valor para el boton
275
     *
276
     * @todo FALTA AGREGAR NOMBRE YA QUE SIN ESTE EL VALUE NO LLEGA AL SERVER
277
     *
278
     * @return string
279
     */
280
    public static function button($text, $attrs = '', $type = 'button', $value = null)
281
    {
282
        $attrs = Tag::getAttrs($attrs);
283
        $value = is_null($value) ? '' : "value=\"$value\"";
284
285
        return "<button type=\"$type\" $value $attrs>$text</button>";
286
    }
287
288
    /**
289
     * Crea un label.
290
     *
291
     * @param string        $text  Texto a mostrar
292
     * @param string        $field Campo al que hace referencia
293
     * @param string|array  $attrs Atributos de campo (opcional)
294
     *
295
     * @return string
296
     */
297
    public static function label($text, $field, $attrs = '')
298
    {
299
        $attrs = Tag::getAttrs($attrs);
300
301
        return "<label for=\"$field\" $attrs>$text</label>";
302
    }
303
304
    /**
305
     * Crea un campo text.
306
     *
307
     * @param string       $field Nombre de campo
308
     * @param string|array $attrs Atributos de campo (opcional)
309
     * @param string       $value (opcional)
310
     *
311
     * @return string
312
     */
313
    public static function text($field, $attrs = '', $value = null)
314
    {
315
        return self::input('text', $field, $attrs, $value);
316
    }
317
318
    /**
319
     * Crea un campo select.
320
     *
321
     * @param string       $field  Nombre de campo
322
     * @param array        $data   Array de valores para la lista desplegable
323
     * @param string|array $attrs  Atributos de campo (opcional)
324
     * @param string|array $value  Array para select multiple (opcional)
325
     * @param string       $blank  agrega un item vacio si es diferente de empty
326
     * @param string       $itemId En caso de usar array de objeto propiedad a tomar como id
327
     * @param string       $show   texto a mostrar, si es empty usa el to string
328
     *
329
     * @return string
330
     */
331
    public static function select($field, $data, $attrs = '', $value = null, $blank = '', $itemId = 'id', $show = '')
332
    {
333
        $attrs = Tag::getAttrs($attrs);
334
        // Obtiene name, id y value (solo para autoload) para el campo y los carga en el scope
335
        [$id, $name, $value] = self::getFieldData($field, $value);
336
        //Si se quiere agregar blank
337
        $options = empty($blank) ? '' :
338
            '<option value="">' . htmlspecialchars($blank, ENT_COMPAT, APP_CHARSET) . '</option>';
339
        foreach ($data as $k => $v) {
340
            $val = self::selectValue($v, $k, $itemId);
341
            $text = self::selectShow($v, $show);
342
            $selected = self::selectedValue($value, $val);
343
            $options .= "<option value=\"$val\" $selected>$text</option>";
344
        }
345
346
        return "<select id=\"$id\" name=\"$name\" $attrs>$options</select>";
347
    }
348
349
    /**
350
     * Retorna el value de un item de un select.
351
     *
352
     * @param mixed  $item item de un array
353
     * @param string $key  valor de item dentro del select
354
     * @param string $id   valor posible de la propiedad del objecto para el value
355
     *
356
     * @return string
357
     */
358
    public static function selectValue($item, $key, $id)
359
    {
360
        return htmlspecialchars(
361
            is_object($item) ? $item->$id : $key,
362
            ENT_COMPAT,
363
            APP_CHARSET
364
        );
365
    }
366
367
    /**
368
     * retorna el atributo para que quede seleccionado el item de un
369
     * select.
370
     *
371
     * @param string|array $value valor(es) que deben estar seleccionados
372
     * @param string       $key   valor del item actual
373
     *
374
     * @return string
375
     */
376
    public static function selectedValue($value, $key)
377
    {
378
        return ((is_array($value) && in_array($key, $value)) || $key === $value) ?
379
            'selected="selected"' : '';
380
    }
381
382
    /**
383
     * Retorna el valor a mostrar del item del select.
384
     *
385
     * @param mixed  $item item del array
386
     * @param string $show propiedad el objeto
387
     *
388
     * @return string
389
     */
390
    public static function selectShow($item, $show)
391
    {
392
        $value = (is_object($item) && !empty($show)) ? $item->$show : (string) $item;
393
394
        return htmlspecialchars($value, ENT_COMPAT, APP_CHARSET);
395
    }
396
397
    /**
398
     * Crea un campo checkbox.
399
     *
400
     * @param string       $field      Nombre de campo
401
     * @param string       $checkValue Valor en el checkbox
402
     * @param string|array $attrs      Atributos de campo (opcional)
403
     * @param bool         $checked    Indica si se marca el campo (opcional)
404
     *
405
     * @return string
406
     */
407
    public static function check($field, $checkValue, $attrs = '', $checked = false)
408
    {
409
        $attrs = Tag::getAttrs($attrs);
410
        // Obtiene name y id para el campo y los carga en el scope
411
        [$id, $name, $checked] = self::getFieldDataCheck($field, $checkValue, $checked);
412
413
        if ($checked) {
414
            $checked = 'checked="checked"';
415
        }
416
417
        return "<input id=\"$id\" name=\"$name\" type=\"checkbox\" value=\"$checkValue\" $attrs $checked/>";
418
    }
419
420
    /**
421
     * Crea un campo radio button.
422
     *
423
     * @param string       $field      Nombre de campo
424
     * @param string       $radioValue Valor en el radio
425
     * @param string|array $attrs      Atributos de campo (opcional)
426
     * @param bool         $checked    Indica si se marca el campo (opcional)
427
     *
428
     * @return string
429
     */
430
    public static function radio($field, $radioValue, $attrs = '', $checked = false)
431
    {
432
        $attrs = Tag::getAttrs($attrs);
433
        // Obtiene name y id para el campo y los carga en el scope
434
        [$id, $name, $checked] = self::getFieldDataCheck($field, $radioValue, $checked);
435
436
        if ($checked) {
437
            $checked = 'checked="checked"';
438
        }
439
440
        // contador de campos radio
441
        if (isset(self::$radios[$field])) {
442
            ++self::$radios[$field];
443
        } else {
444
            self::$radios[$field] = 0;
445
        }
446
        $id .= self::$radios[$field];
447
448
        return "<input id=\"$id\" name=\"$name\" type=\"radio\" value=\"$radioValue\" $attrs $checked/>";
449
    }
450
451
    /**
452
     * Crea un botón de tipo imagen.
453
     *
454
     * @param string       $img   Nombre o ruta de la imagen
455
     * @param string|array $attrs Atributos de campo (opcional)
456
     *
457
     * @return string
458
     */
459
    public static function submitImage($img, $attrs = '')
460
    {
461
        $attrs = Tag::getAttrs($attrs);
462
463
        return '<input type="image" src="' . PUBLIC_PATH . "img/$img\" $attrs/>";
464
    }
465
466
    /**
467
     * Crea un campo hidden.
468
     *
469
     * @param string       $field Nombre de campo
470
     * @param string|array $attrs Atributos de campo (opcional)
471
     * @param string       $value
472
     *
473
     * @return string
474
     */
475
    public static function hidden($field, $attrs = '', $value = null)
476
    {
477
        return self::input('hidden', $field, $attrs, $value);
478
    }
479
480
    /**
481
     * Crea un campo password.
482
     *
483
     * @deprecated Obsoleta desde la versión 1.0, usar password
484
     *
485
     * @param string       $field Nombre de campo
486
     * @param string|array $attrs Atributos de campo (opcional)
487
     * @param string       $value
488
     */
489
    public static function pass($field, $attrs = '', $value = null)
490
    {
491
        return self::password($field, $attrs, $value);
492
    }
493
494
    /**
495
     * Crea un campo passwordop.
496
     *
497
     * @param string       $field Nombre de campo
498
     * @param string|array $attrs Atributos de campo (opcional)
499
     * @param string       $value
500
     */
501
    public static function password($field, $attrs = '', $value = null)
502
    {
503
        return self::input('password', $field, $attrs, $value);
504
    }
505
506
    /**
507
     * Crea un campo select que toma los valores de un array de objetos.
508
     *
509
     * @param string       $field Nombre de campo
510
     * @param string       $show  Campo que se mostrara (opcional)
511
     * @param array        $data  Array('modelo','metodo','param') (opcional)
512
     * @param string       $blank Campo en blanco (opcional)
513
     * @param string|array $attrs Atributos de campo (opcional)
514
     * @param string|array $value (opcional) Array en select multiple
515
     *
516
     * @return string
517
     */
518
    public static function dbSelect($field, $show = null, $data = null, $blank = 'Seleccione', $attrs = '', $value = null)
519
    {
520
        $model = ($data === null) ? substr($field, strpos($field, '.') + 1, -3) : $data[0];
521
        $model = Util::camelcase($model);
522
        $model_asoc = new $model();
523
        //por defecto el primer campo no pk
524
        $show = $show ?: $model_asoc->non_primary[0];
525
        $pk = $model_asoc->primary_key[0];
526
        if ($data === null) {
527
            $data = $model_asoc->find("columns: $pk,$show", "order: $show asc"); //mejor usar array
528
        } else {
529
            $data = (isset($data[2])) ?
530
                $model_asoc->{$data[1]}($data[2]) :
531
                $model_asoc->{$data[1]}();
532
        }
533
534
        return self::select($field, $data, $attrs, $value, $blank, $pk, $show);
535
    }
536
537
    /**
538
     * Crea un campo file.
539
     *
540
     * @param string       $field Nombre de campo
541
     * @param string|array $attrs Atributos de campo (opcional)
542
     *
543
     * @return string
544
     */
545
    public static function file($field, $attrs = '')
546
    {
547
        // aviso al programador
548
        if (!self::$multipart) {
549
            Flash::error('Para poder subir ficheros, debe abrir el form con Form::openMultipart()');
550
        }
551
552
        $attrs = Tag::getAttrs($attrs);
553
554
        // Obtiene name y id, y los carga en el scope
555
        [$id, $name] = self::getFieldData($field, false);
556
557
        return "<input id=\"$id\" name=\"$name\" type=\"file\" $attrs/>";
558
    }
559
560
    /**
561
     * Crea un campo textarea.
562
     *
563
     * @param string       $field Nombre de campo
564
     * @param string|array $attrs Atributos de campo (opcional)
565
     * @param string       $value (opcional)
566
     *
567
     * @return string
568
     */
569
    public static function textarea($field, $attrs = '', $value = '')
570
    {
571
        return self::tag('textarea', $field, $attrs, $value);
572
    }
573
574
    /**
575
     * Crea un campo fecha nativo (HTML5).
576
     *
577
     * @param string       $field Nombre de campo
578
     * @param string|array $attrs Atributos de campo (opcional)
579
     * @param string       $value (opcional)
580
     *
581
     * @return string
582
     */
583
    public static function date($field, $attrs = '', $value = '')
584
    {
585
        return self::input('date', $field, $attrs, $value);
586
    }
587
588
    /**
589
     * Crea un campo de texo para fecha (Requiere JS ).
590
     *
591
     * @param string       $field Nombre de campo
592
     * @param string       $class Clase de estilo (opcional)
593
     * @param string|array $attrs Atributos de campo (opcional)
594
     * @param string       $value (opcional)
595
     *
596
     * @return string
597
     */
598
    public static function datepicker($field, $class = '', $attrs = '', $value = null)
599
    {
600
        return self::tag('input', $field, $attrs, null, "class=\"js-datepicker $class\" type=\"text\" value=\"$value\" ");
601
    }
602
603
    /**
604
     * Crea un campo tiempo nativo (HTML5).
605
     *
606
     * @param string       $field Nombre de campo
607
     * @param string|array $attrs Atributos de campo (opcional)
608
     * @param string       $value (opcional)
609
     *
610
     * @return string
611
     */
612
    public static function time($field, $attrs = '', $value = null)
613
    {
614
        return self::input('time', $field, $attrs, $value);
615
    }
616
617
    /**
618
     * Crea un campo fecha/tiempo nativo (HTML5).
619
     *
620
     * @param string       $field Nombre de campo
621
     * @param string|array $attrs Atributos de campo (opcional)
622
     * @param string       $value (opcional)
623
     *
624
     * @return string
625
     */
626
    public static function datetime($field, $attrs = '', $value = null)
627
    {
628
        return self::input('datetime-local', $field, $attrs, $value);
629
    }
630
631
    /**
632
     * Crea un campo numerico nativo (HTML5).
633
     *
634
     * @param string       $field Nombre de campo
635
     * @param string|array $attrs Atributos de campo (opcional)
636
     * @param string       $value (opcional)
637
     *
638
     * @return string
639
     */
640
    public static function number($field, $attrs = '', $value = null)
641
    {
642
        return self::input('number', $field, $attrs, $value);
643
    }
644
645
    /**
646
     * Crea un campo url nativo (HTML5).
647
     *
648
     * @param string       $field Nombre de campo
649
     * @param string|array $attrs Atributos de campo (opcional)
650
     * @param string       $value (opcional)
651
     *
652
     * @return string
653
     */
654
    public static function url($field, $attrs = '', $value = null)
655
    {
656
        return self::input('url', $field, $attrs, $value);
657
    }
658
659
    /**
660
     * Crea un campo email nativo (HTML5).
661
     *
662
     * @param string       $field Nombre de campo
663
     * @param string|array $attrs Atributos de campo (opcional)
664
     * @param string       $value (opcional)
665
     *
666
     * @return string
667
     */
668
    public static function email($field, $attrs = '', $value = null)
669
    {
670
        return self::input('email', $field, $attrs, $value);
671
    }
672
}
673