Form   F
last analyzed

Complexity

Total Complexity 67

Size/Duplication

Total Lines 632
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 0
Metric Value
dl 0
loc 632
rs 3.008
c 0
b 0
f 0
wmc 67
lcom 1
cbo 6

35 Methods

Rating   Name   Duplication   Size   Complexity  
B getField() 0 22 9
A getFromModel() 0 10 4
A fieldName() 0 5 2
A getFieldData() 0 4 1
A getFieldDataCheck() 0 4 1
A tag() 0 9 2
A input() 0 4 1
A open() 0 11 2
A openMultipart() 0 12 2
A close() 0 6 1
A submit() 0 4 1
A reset() 0 4 1
A button() 0 7 2
A label() 0 6 1
A text() 0 4 1
A select() 0 17 3
A selectValue() 0 5 2
A selectedValue() 0 5 4
A selectShow() 0 6 3
A check() 0 12 2
A radio() 0 20 3
A submitImage() 0 6 1
A hidden() 0 4 1
A pass() 0 4 1
A password() 0 4 1
A dbSelect() 0 18 5
A file() 0 14 2
A textarea() 0 4 1
A date() 0 4 1
A datepicker() 0 4 1
A time() 0 4 1
A datetime() 0 4 1
A number() 0 4 1
A url() 0 4 1
A email() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like Form often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Form, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * KumbiaPHP web & app Framework
4
 *
5
 * LICENSE
6
 *
7
 * This source file is subject to the new BSD license that is bundled
8
 * with this package in the file LICENSE.
9
 *
10
 * @category   KumbiaPHP
11
 * @package    Helpers
12
 *
13
 * @copyright  Copyright (c) 2005 - 2019 KumbiaPHP Team (http://www.kumbiaphp.com)
14
 * @license    https://github.com/KumbiaPHP/KumbiaPHP/blob/master/LICENSE   New BSD License
15
 */
16
/**
17
 * Helper para Formularios.
18
 *
19
 * @category   KumbiaPHP
20
 */
21
class Form
22
{
23
    /**
24
     * Utilizado para generar los id de los radio button,
25
     * lleva un conteo interno.
26
     *
27
     * @var array
28
     */
29
    protected static $radios = array();
30
31
    /**
32
     * Utilizado para avisar al programador,si usa Form::file()
33
     * y no tiene el form mulipart muestra un error.
34
     *
35
     * @var bool
36
     */
37
    protected static $multipart = false;
38
39
    /**
40
     * Obtiene el valor de un componente tomado
41
     * del mismo valor del nombre del campo y formulario
42
     * que corresponda a un atributo del mismo nombre
43
     * que sea un string, objeto o array.
44
     *
45
     * @param string $field
46
     * @param mixed  $value    valor de campo
47
     * @param bool   $filter   filtrar caracteres especiales html
48
     * @param bool   $check    si esta marcado el checkbox
49
     * @param bool   $is_check
50
     *
51
     * @return array devuelve un array de longitud 3 con la forma array(id, name, value)
52
     */
53
    public static function getField($field, $value = null, $is_check = false, $filter = true, $check = false)
54
    {
55
        // Obtiene considerando el patrón de formato form.field
56
        $formField = explode('.', $field, 2);
57
        list($id, $name) = self::fieldName($formField);
58
        // Verifica en $_POST
59
        if (Input::hasPost($field)) {
60
            $value = $is_check ?
61
            Input::post($field) == $value : Input::post($field);
62
        } elseif ($is_check) {
63
            $value = $check;
64
        } elseif ($tmp_val = self::getFromModel($formField)) {
65
            // Autocarga de datos
66
            $value = $is_check ? $tmp_val == $value : $tmp_val;
67
        }
68
        // Filtrar caracteres especiales
69
        if (!$is_check && $value !== null && $filter) {
70
            $value = htmlspecialchars($value, ENT_COMPAT, APP_CHARSET);
71
        }
72
        // Devuelve los datos
73
        return array($id, $name, $value);
74
    }
75
76
    /**
77
     * Devuelve el valor del modelo.
78
     *
79
     * @param array $formField array [modelo, campo]
80
     *
81
     * @return mixed
82
     */
83
    protected static function getFromModel(array $formField)
84
    {
85
        $form = View::getVar($formField[0]);
86
        if (is_scalar($form) || is_null($form)) {
87
            return $form;
88
        }
89
        $form = (object) $form;
90
91
        return isset($form->{$formField[1]}) ? $form->{$formField[1]} : null;
92
    }
93
94
    /**
95
     * Devuelve el nombre y el id de un campo.
96
     *
97
     * @param array $field array del explode
98
     *
99
     * @return array array(id, name)
100
     */
101
    protected static function fieldName(array $field)
102
    {
103
        return isset($field[1]) ?
104
                    array("{$field[0]}_{$field[1]}", "{$field[0]}[{$field[1]}]") : array($field[0], $field[0]);
105
    }
106
107
    /**
108
     * Obtiene el valor de un componente tomado
109
     * del mismo valor del nombre del campo y formulario
110
     * que corresponda a un atributo del mismo nombre
111
     * que sea un string, objeto o array.
112
     *
113
     * @param string $field
114
     * @param mixed  $value  valor de campo
115
     * @param bool   $filter filtrar caracteres especiales html
116
     *
117
     * @return array devuelve un array de longitud 3 con la forma array(id, name, value)
118
     */
119
    public static function getFieldData($field, $value = null, $filter = true)
120
    {
121
        return self::getField($field, $value, false, $filter);
122
    }
123
124
    /**
125
     * Obtiene el valor de un componente check 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 string $checkValue
132
     * @param bool   $checked
133
     *
134
     * @return array Devuelve un array de longitud 3 con la forma array(id, name, checked);
135
     */
136
    public static function getFieldDataCheck($field, $checkValue, $checked = false)
137
    {
138
        return self::getField($field, $checkValue, true, false, $checked);
139
    }
140
141
    /**
142
     * @param string       $tag
143
     * @param string       $field
144
     * @param string       $value
145
     * @param string|array $attrs
146
     */
147
    protected static function tag($tag, $field, $attrs = '', $value = null, $extra = '', $close = true)
148
    {
149
        $attrs = Tag::getAttrs($attrs);
150
        $end = $close ? ">{{value}}</$tag>" : '/>';
151
        // Obtiene name, id y value (solo para autoload) para el campo y los carga en el scope
152
        list($id, $name, $value) = self::getFieldData($field, $value);
153
154
        return str_replace('{{value}}', $value, "<$tag id=\"$id\" name=\"$name\" $extra $attrs $end");
155
    }
156
157
    /*
158
     * Crea un campo input
159
     *
160
     * @param string|array $attrs Atributos de campo (opcional)
161
     * @param string $type
162
     * @param string $field
163
     * @param string $value
164
     * @return string
165
     */
166
    public static function input($type, $field, $attrs = '', $value = null)
167
    {
168
        return self::tag('input', $field, $attrs, $value, "type=\"$type\" value=\"{{value}}\"", false);
169
    }
170
171
    /**
172
     * Crea una etiqueta de formulario.
173
     *
174
     * @param string $action Acción del formulario (opcional)
175
     * @param string $method Por defecto es post (opcional)
176
     * @param string $attrs  Atributos de etiqueta (opcional)
177
     *
178
     * @return string
179
     */
180
    public static function open($action = '', $method = 'post', $attrs = '')
181
    {
182
        $attrs = Tag::getAttrs($attrs);
183
        if ($action) {
184
            $action = PUBLIC_PATH.$action;
185
        } else {
186
            $action = PUBLIC_PATH.ltrim(Router::get('route'), '/');
187
        }
188
189
        return "<form action=\"$action\" method=\"$method\" $attrs>";
190
    }
191
192
    /**
193
     * Crea una etiqueta de formulario multipart.
194
     *
195
     * @param string       $action Acción del formulario (opcional)
196
     * @param string|array $attrs  Atributos de etiqueta (opcional)
197
     *
198
     * @return string
199
     */
200
    public static function openMultipart($action = null, $attrs = '')
201
    {
202
        self::$multipart = true;
203
        if (is_array($attrs)) {
204
            $attrs['enctype'] = 'multipart/form-data';
205
            $attrs = Tag::getAttrs($attrs);
206
        } else {
207
            $attrs .= ' enctype="multipart/form-data"';
208
        }
209
210
        return self::open($action, 'post', $attrs);
211
    }
212
213
    /**
214
     * Crea una etiqueta para cerrar un formulario.
215
     *
216
     * @return string
217
     */
218
    public static function close()
219
    {
220
        self::$multipart = false;
221
222
        return '</form>';
223
    }
224
225
    /**
226
     * Crea un botón de submit para el formulario actual.
227
     *
228
     * @param string       $text  Texto del botón
229
     * @param string|array $attrs Atributos de campo (opcional)
230
     *
231
     * @return string
232
     */
233
    public static function submit($text, $attrs = '')
234
    {
235
        return self::button($text, $attrs, 'submit');
236
    }
237
238
    /**
239
     * Crea un botón reset.
240
     *
241
     * @param string       $text  Texto del botón
242
     * @param string|array $attrs Atributos de campo (opcional)
243
     *
244
     * @return string
245
     */
246
    public static function reset($text, $attrs = '')
247
    {
248
        return self::button($text, $attrs, 'reset');
249
    }
250
251
    /**
252
     * Crea un botón.
253
     *
254
     * @param string       $text  Texto del botón
255
     * @param array|string $attrs Atributos de campo (opcional)
256
     * @param string       $type  tipo de botón
257
     * @param string       $value Valor para el boton
258
     *
259
     * @todo FALTA AGREGAR NOMBRE YA QUE SIN ESTE EL VALUE NO LLEGA AL SERVER
260
     *
261
     * @return string
262
     */
263
    public static function button($text, $attrs = '', $type = 'button', $value = null)
264
    {
265
        $attrs = Tag::getAttrs($attrs);
266
        $value = is_null($value) ? '' : "value=\"$value\"";
267
268
        return "<button type=\"$type\" $value $attrs>$text</button>";
269
    }
270
271
    /**
272
     * Crea un label.
273
     *
274
     * @param string        $text  Texto a mostrar
275
     * @param string        $field Campo al que hace referencia
276
     * @param string|array  $attrs Atributos de campo (opcional)
277
     *
278
     * @return string
279
     */
280
    public static function label($text, $field, $attrs = '')
281
    {
282
        $attrs = Tag::getAttrs($attrs);
283
284
        return "<label for=\"$field\" $attrs>$text</label>";
285
    }
286
287
    /**
288
     * Crea un campo text.
289
     *
290
     * @param string       $field Nombre de campo
291
     * @param string|array $attrs Atributos de campo (opcional)
292
     * @param string       $value (opcional)
293
     *
294
     * @return string
295
     */
296
    public static function text($field, $attrs = '', $value = null)
297
    {
298
        return self::input('text', $field, $attrs, $value);
299
    }
300
301
    /**
302
     * Crea un campo select.
303
     *
304
     * @param string       $field  Nombre de campo
305
     * @param array        $data   Array de valores para la lista desplegable
306
     * @param string|array $attrs  Atributos de campo (opcional)
307
     * @param string|array $value  Array para select multiple (opcional)
308
     * @param string       $blank  agrega un item vacio si es diferente de empty
309
     * @param string       $itemId En caso de usar array de objeto propiedad a tomar como id
310
     * @param string       $show   texto a mostrar, si es empty usa el to string
311
     *
312
     * @return string
313
     */
314
    public static function select($field, $data, $attrs = '', $value = null, $blank = '', $itemId = 'id', $show = '')
315
    {
316
        $attrs = Tag::getAttrs($attrs);
317
        // Obtiene name, id y value (solo para autoload) para el campo y los carga en el scope
318
        list($id, $name, $value) = self::getFieldData($field, $value);
319
        //Si se quiere agregar blank
320
        $options = empty($blank) ? '' :
321
        '<option value="">'.htmlspecialchars($blank, ENT_COMPAT, APP_CHARSET).'</option>';
322
        foreach ($data as $k => $v) {
323
            $val = self::selectValue($v, $k, $itemId);
324
            $text = self::selectShow($v, $show);
325
            $selected = self::selectedValue($value, $val);
326
            $options .= "<option value=\"$val\" $selected>$text</option>";
327
        }
328
329
        return "<select id=\"$id\" name=\"$name\" $attrs>$options</select>";
330
    }
331
332
    /**
333
     * Retorna el value de un item de un select.
334
     *
335
     * @param mixed  $item item de un array
336
     * @param string $key  valor de item dentro del select
337
     * @param string $id   valor posible de la propiedad del objecto para el value
338
     *
339
     * @return string
340
     */
341
    public static function selectValue($item, $key, $id)
342
    {
343
        return htmlspecialchars(is_object($item) ? $item->$id : $key,
344
                                ENT_COMPAT, APP_CHARSET);
345
    }
346
347
    /**
348
     * retorna el atributo para que quede seleccionado el item de un
349
     * select.
350
     *
351
     * @param string|array $value valor(es) que deben estar seleccionados
352
     * @param string       $key   valor del item actual
353
     *
354
     * @return string
355
     */
356
    public static function selectedValue($value, $key)
357
    {
358
        return ((is_array($value) && in_array($key, $value)) || $key === $value) ?
359
                'selected="selected"' : '';
360
    }
361
362
    /**
363
     * Retorna el valor a mostrar del item del select.
364
     *
365
     * @param mixed  $item item del array
366
     * @param string $show propiedad el objeto
367
     *
368
     * @return string
369
     */
370
    public static function selectShow($item, $show)
371
    {
372
        $value = (is_object($item) && !empty($show)) ? $item->$show : (string) $item;
373
374
        return htmlspecialchars($value, ENT_COMPAT, APP_CHARSET);
375
    }
376
377
    /**
378
     * Crea un campo checkbox.
379
     *
380
     * @param string       $field      Nombre de campo
381
     * @param string       $checkValue Valor en el checkbox
382
     * @param string|array $attrs      Atributos de campo (opcional)
383
     * @param bool         $checked    Indica si se marca el campo (opcional)
384
     *
385
     * @return string
386
     */
387
    public static function check($field, $checkValue, $attrs = '', $checked = false)
388
    {
389
        $attrs = Tag::getAttrs($attrs);
390
        // Obtiene name y id para el campo y los carga en el scope
391
        list($id, $name, $checked) = self::getFieldDataCheck($field, $checkValue, $checked);
392
393
        if ($checked) {
394
            $checked = 'checked="checked"';
395
        }
396
397
        return "<input id=\"$id\" name=\"$name\" type=\"checkbox\" value=\"$checkValue\" $attrs $checked/>";
398
    }
399
400
    /**
401
     * Crea un campo radio button.
402
     *
403
     * @param string       $field      Nombre de campo
404
     * @param string       $radioValue Valor en el radio
405
     * @param string|array $attrs      Atributos de campo (opcional)
406
     * @param bool         $checked    Indica si se marca el campo (opcional)
407
     *
408
     * @return string
409
     */
410
    public static function radio($field, $radioValue, $attrs = '', $checked = false)
411
    {
412
        $attrs = Tag::getAttrs($attrs);
413
        // Obtiene name y id para el campo y los carga en el scope
414
        list($id, $name, $checked) = self::getFieldDataCheck($field, $radioValue, $checked);
415
416
        if ($checked) {
417
            $checked = 'checked="checked"';
418
        }
419
420
        // contador de campos radio
421
        if (isset(self::$radios[$field])) {
422
            ++self::$radios[$field];
423
        } else {
424
            self::$radios[$field] = 0;
425
        }
426
        $id .= self::$radios[$field];
427
428
        return "<input id=\"$id\" name=\"$name\" type=\"radio\" value=\"$radioValue\" $attrs $checked/>";
429
    }
430
431
    /**
432
     * Crea un botón de tipo imagen.
433
     *
434
     * @param string       $img   Nombre o ruta de la imagen
435
     * @param string|array $attrs Atributos de campo (opcional)
436
     *
437
     * @return string
438
     */
439
    public static function submitImage($img, $attrs = '')
440
    {
441
        $attrs = Tag::getAttrs($attrs);
442
443
        return '<input type="image" src="'.PUBLIC_PATH."img/$img\" $attrs/>";
444
    }
445
446
    /**
447
     * Crea un campo hidden.
448
     *
449
     * @param string       $field Nombre de campo
450
     * @param string|array $attrs Atributos de campo (opcional)
451
     * @param string       $value
452
     *
453
     * @return string
454
     */
455
    public static function hidden($field, $attrs = '', $value = null)
456
    {
457
        return self::input('hidden', $field, $attrs, $value);
458
    }
459
460
    /**
461
     * Crea un campo password.
462
     *
463
     * @deprecated Obsoleta desde la versión 1.0, usar password
464
     *
465
     * @param string       $field Nombre de campo
466
     * @param string|array $attrs Atributos de campo (opcional)
467
     * @param string       $value
468
     */
469
    public static function pass($field, $attrs = '', $value = null)
470
    {
471
        return self::password($field, $attrs, $value);
472
    }
473
474
    /**
475
     * Crea un campo passwordop.
476
     *
477
     * @param string       $field Nombre de campo
478
     * @param string|array $attrs Atributos de campo (opcional)
479
     * @param string       $value
480
     */
481
    public static function password($field, $attrs = '', $value = null)
482
    {
483
        return self::input('password', $field, $attrs, $value);
484
    }
485
486
    /**
487
     * Crea un campo select que toma los valores de un array de objetos.
488
     *
489
     * @param string       $field Nombre de campo
490
     * @param string       $show  Campo que se mostrara (opcional)
491
     * @param array        $data  Array('modelo','metodo','param') (opcional)
492
     * @param string       $blank Campo en blanco (opcional)
493
     * @param string|array $attrs Atributos de campo (opcional)
494
     * @param string|array $value (opcional) Array en select multiple
495
     *
496
     * @return string
497
     */
498
    public static function dbSelect($field, $show = null, $data = null, $blank = 'Seleccione', $attrs = '', $value = null)
499
    {
500
        $model = ($data === null) ? substr($field, strpos($field, '.') + 1, -3) : $data[0];
501
        $model = Util::camelcase($model);
502
        $model_asoc = new $model();
503
        //por defecto el primer campo no pk
504
        $show = $show ?: $model_asoc->non_primary[0];
505
        $pk = $model_asoc->primary_key[0];
506
        if ($data === null) {
507
            $data = $model_asoc->find("columns: $pk,$show", "order: $show asc"); //mejor usar array
508
        } else {
509
            $data = (isset($data[2])) ?
510
            $model_asoc->{$data[1]}($data[2]) :
511
            $model_asoc->{$data[1]}();
512
        }
513
514
        return self::select($field, $data, $attrs, $value, $blank, $pk, $show);
515
    }
516
517
    /**
518
     * Crea un campo file.
519
     *
520
     * @param string       $field Nombre de campo
521
     * @param string|array $attrs Atributos de campo (opcional)
522
     *
523
     * @return string
524
     */
525
    public static function file($field, $attrs = '')
526
    {
527
        // aviso al programador
528
        if (!self::$multipart) {
529
            Flash::error('Para poder subir ficheros, debe abrir el form con Form::openMultipart()');
530
        }
531
532
        $attrs = Tag::getAttrs($attrs);
533
534
        // Obtiene name y id, y los carga en el scope
535
        list($id, $name) = self::getFieldData($field, false);
536
537
        return "<input id=\"$id\" name=\"$name\" type=\"file\" $attrs/>";
538
    }
539
540
    /**
541
     * Crea un campo textarea.
542
     *
543
     * @param string       $field Nombre de campo
544
     * @param string|array $attrs Atributos de campo (opcional)
545
     * @param string       $value (opcional)
546
     *
547
     * @return string
548
     */
549
    public static function textarea($field, $attrs = '', $value = null)
550
    {
551
        return self::tag('textarea', $field, $attrs, $value);
552
    }
553
554
    /**
555
     * Crea un campo fecha nativo (HTML5).
556
     *
557
     * @param string       $field Nombre de campo
558
     * @param string|array $attrs Atributos de campo (opcional)
559
     * @param string       $value (opcional)
560
     *
561
     * @return string
562
     */
563
    public static function date($field, $attrs = '', $value = null)
564
    {
565
        return self::input('date', $field, $attrs, $value);
566
    }
567
568
    /**
569
     * Crea un campo de texo para fecha (Requiere JS ).
570
     *
571
     * @param string       $field Nombre de campo
572
     * @param string       $class Clase de estilo (opcional)
573
     * @param string|array $attrs Atributos de campo (opcional)
574
     * @param string       $value (opcional)
575
     *
576
     * @return string
577
     */
578
    public static function datepicker($field, $class = '', $attrs = '', $value = null)
579
    {
580
        return self::tag('input', $field, $attrs, null, "class=\"js-datepicker $class\" type=\"text\" value=\"$value\" ");
581
    }
582
583
    /**
584
     * Crea un campo tiempo nativo (HTML5).
585
     *
586
     * @param string       $field Nombre de campo
587
     * @param string|array $attrs Atributos de campo (opcional)
588
     * @param string       $value (opcional)
589
     *
590
     * @return string
591
     */
592
    public static function time($field, $attrs = '', $value = null)
593
    {
594
        return self::input('time', $field, $attrs, $value);
595
    }
596
597
    /**
598
     * Crea un campo fecha/tiempo nativo (HTML5).
599
     *
600
     * @param string       $field Nombre de campo
601
     * @param string|array $attrs Atributos de campo (opcional)
602
     * @param string       $value (opcional)
603
     *
604
     * @return string
605
     */
606
    public static function datetime($field, $attrs = '', $value = null)
607
    {
608
        return self::input('datetime', $field, $attrs, $value);
609
    }
610
611
    /**
612
     * Crea un campo numerico nativo (HTML5).
613
     *
614
     * @param string       $field Nombre de campo
615
     * @param string|array $attrs Atributos de campo (opcional)
616
     * @param string       $value (opcional)
617
     *
618
     * @return string
619
     */
620
    public static function number($field, $attrs = '', $value = null)
621
    {
622
        return self::input('number', $field, $attrs, $value);
623
    }
624
625
    /**
626
     * Crea un campo url nativo (HTML5).
627
     *
628
     * @param string       $field Nombre de campo
629
     * @param string|array $attrs Atributos de campo (opcional)
630
     * @param string       $value (opcional)
631
     *
632
     * @return string
633
     */
634
    public static function url($field, $attrs = '', $value = null)
635
    {
636
        return self::input('url', $field, $attrs, $value);
637
    }
638
639
    /**
640
     * Crea un campo email nativo (HTML5).
641
     *
642
     * @param string       $field Nombre de campo
643
     * @param string|array $attrs Atributos de campo (opcional)
644
     * @param string       $value (opcional)
645
     *
646
     * @return string
647
     */
648
    public static function email($field, $attrs = '', $value = null)
649
    {
650
        return self::input('email', $field, $attrs, $value);
651
    }
652
}
653