form_Core   F
last analyzed

Complexity

Total Complexity 75

Size/Duplication

Total Lines 482
Duplicated Lines 10.79 %

Coupling/Cohesion

Components 0
Dependencies 0

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 52
loc 482
rs 2.3076
wmc 75
lcom 0
cbo 0

18 Methods

Rating   Name   Duplication   Size   Complexity  
C open() 0 29 7
A open_multipart() 0 7 1
A open_fieldset() 0 4 1
A close_fieldset() 0 4 1
A legend() 0 4 1
A hidden() 0 21 3
A input() 0 14 2
A password() 10 10 2
A upload() 10 10 2
A textarea() 0 14 3
C dropdown() 0 48 10
B checkbox() 16 16 5
B radio() 16 16 5
A submit() 0 15 3
B button() 0 17 5
A close() 0 4 1
B label() 0 19 5
C attributes() 0 68 18

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like form_Core 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_Core, and based on these observations, apply Extract Interface, too.

1
<?php defined('SYSPATH') or die('No direct access allowed.');
2
/**
3
 * Form helper class.
4
 *
5
 * $Id: form.php 4291 2009-04-29 22:51:58Z kiall $
6
 *
7
 * @package    Core
8
 * @author     Kohana Team
9
 * @copyright  (c) 2007-2008 Kohana Team
10
 * @license    http://kohanaphp.com/license.html
11
 */
12
class form_Core
13
{
14
15
    /**
16
     * Generates an opening HTML form tag.
17
     *
18
     * @param   string  form action attribute
19
     * @param   array   extra attributes
20
     * @param   array   hidden fields to be created immediately after the form tag
21
     * @return  string
22
     */
23
    public static function open($action = null, $attr = array(), $hidden = null)
24
    {
25
        // Make sure that the method is always set
26
        empty($attr['method']) and $attr['method'] = 'post';
27
28
        if ($attr['method'] !== 'post' and $attr['method'] !== 'get') {
29
            // If the method is invalid, use post
30
            $attr['method'] = 'post';
31
        }
32
33
        if ($action === null) {
34
            // Use the current URL as the default action
35
            $action = url::site(Router::$complete_uri);
36
        } elseif (strpos($action, '://') === false) {
37
            // Make the action URI into a URL
38
            $action = url::site($action);
39
        }
40
41
        // Set action
42
        $attr['action'] = $action;
43
44
        // Form opening tag
45
        $form = '<form'.form::attributes($attr).'>'."\n";
46
47
        // Add hidden fields immediate after opening tag
48
        empty($hidden) or $form .= form::hidden($hidden);
49
50
        return $form;
51
    }
52
53
    /**
54
     * Generates an opening HTML form tag that can be used for uploading files.
55
     *
56
     * @param   string  form action attribute
57
     * @param   array   extra attributes
58
     * @param   array   hidden fields to be created immediately after the form tag
59
     * @return  string
60
     */
61
    public static function open_multipart($action = null, $attr = array(), $hidden = array())
62
    {
63
        // Set multi-part form type
64
        $attr['enctype'] = 'multipart/form-data';
65
66
        return form::open($action, $attr, $hidden);
67
    }
68
69
    /**
70
     * Generates a fieldset opening tag.
71
     *
72
     * @param   array   html attributes
73
     * @param   string  a string to be attached to the end of the attributes
74
     * @return  string
75
     */
76
    public static function open_fieldset($data = null, $extra = '')
77
    {
78
        return '<fieldset'.html::attributes((array) $data).' '.$extra.'>'."\n";
79
    }
80
81
    /**
82
     * Generates a fieldset closing tag.
83
     *
84
     * @return  string
85
     */
86
    public static function close_fieldset()
87
    {
88
        return '</fieldset>'."\n";
89
    }
90
91
    /**
92
     * Generates a legend tag for use with a fieldset.
93
     *
94
     * @param   string  legend text
95
     * @param   array   HTML attributes
96
     * @param   string  a string to be attached to the end of the attributes
97
     * @return  string
98
     */
99
    public static function legend($text = '', $data = null, $extra = '')
100
    {
101
        return '<legend'.form::attributes((array) $data).' '.$extra.'>'.$text.'</legend>'."\n";
102
    }
103
104
    /**
105
     * Generates hidden form fields.
106
     * You can pass a simple key/value string or an associative array with multiple values.
107
     *
108
     * @param   string|array  input name (string) or key/value pairs (array)
109
     * @param   string        input value, if using an input name
110
     * @return  string
111
     */
112
    public static function hidden($data, $value = '')
113
    {
114
        if (! is_array($data)) {
115
            $data = array(
116
                $data => $value
117
            );
118
        }
119
120
        $input = '';
121
        foreach ($data as $name => $value) {
122
            $attr = array(
123
                'type'  => 'hidden',
124
                'name'  => $name,
125
                'value' => $value
126
            );
127
128
            $input .= form::input($attr)."\n";
129
        }
130
131
        return $input;
132
    }
133
134
    /**
135
     * Creates an HTML form input tag. Defaults to a text type.
136
     *
137
     * @param   string|array  input name or an array of HTML attributes
138
     * @param   string        input value, when using a name
139
     * @param   string        a string to be attached to the end of the attributes
140
     * @return  string
141
     */
142
    public static function input($data, $value = '', $extra = '')
143
    {
144
        if (! is_array($data)) {
145
            $data = array('name' => $data);
146
        }
147
148
        // Type and value are required attributes
149
        $data += array(
150
            'type'  => 'text',
151
            'value' => $value
152
        );
153
154
        return '<input'.form::attributes($data).' '.$extra.' />';
155
    }
156
157
    /**
158
     * Creates a HTML form password input tag.
159
     *
160
     * @param   string|array  input name or an array of HTML attributes
161
     * @param   string        input value, when using a name
162
     * @param   string        a string to be attached to the end of the attributes
163
     * @return  string
164
     */
165 View Code Duplication
    public static function password($data, $value = '', $extra = '')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
166
    {
167
        if (! is_array($data)) {
168
            $data = array('name' => $data);
169
        }
170
171
        $data['type'] = 'password';
172
173
        return form::input($data, $value, $extra);
174
    }
175
176
    /**
177
     * Creates an HTML form upload input tag.
178
     *
179
     * @param   string|array  input name or an array of HTML attributes
180
     * @param   string        input value, when using a name
181
     * @param   string        a string to be attached to the end of the attributes
182
     * @return  string
183
     */
184 View Code Duplication
    public static function upload($data, $value = '', $extra = '')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
185
    {
186
        if (! is_array($data)) {
187
            $data = array('name' => $data);
188
        }
189
190
        $data['type'] = 'file';
191
192
        return form::input($data, $value, $extra);
193
    }
194
195
    /**
196
     * Creates an HTML form textarea tag.
197
     *
198
     * @param   string|array  input name or an array of HTML attributes
199
     * @param   string        input value, when using a name
200
     * @param   string        a string to be attached to the end of the attributes
201
     * @param   boolean       encode existing entities
202
     * @return  string
203
     */
204
    public static function textarea($data, $value = '', $extra = '', $double_encode = true)
205
    {
206
        if (! is_array($data)) {
207
            $data = array('name' => $data);
208
        }
209
210
        // Use the value from $data if possible, or use $value
211
        $value = isset($data['value']) ? $data['value'] : $value;
212
213
        // Value is not part of the attributes
214
        unset($data['value']);
215
216
        return '<textarea'.form::attributes($data, 'textarea').' '.$extra.'>'.html::specialchars($value, $double_encode).'</textarea>';
217
    }
218
219
    /**
220
     * Creates an HTML form select tag, or "dropdown menu".
221
     *
222
     * @param   string|array  input name or an array of HTML attributes
223
     * @param   array         select options, when using a name
224
     * @param   string|array  option key(s) that should be selected by default
225
     * @param   string        a string to be attached to the end of the attributes
226
     * @return  string
227
     */
228
    public static function dropdown($data, $options = null, $selected = null, $extra = '')
229
    {
230
        if (! is_array($data)) {
231
            $data = array('name' => $data);
232
        } else {
233
            if (isset($data['options'])) {
234
                // Use data options
235
                $options = $data['options'];
236
            }
237
238
            if (isset($data['selected'])) {
239
                // Use data selected
240
                $selected = $data['selected'];
241
            }
242
        }
243
244
        if (is_array($selected)) {
245
            // Multi-select box
246
            $data['multiple'] = 'multiple';
247
        } else {
248
            // Single selection (but converted to an array)
249
            $selected = array($selected);
250
        }
251
252
        $input = '<select'.form::attributes($data, 'select').' '.$extra.'>'."\n";
253
        foreach ((array) $options as $key => $val) {
254
            // Key should always be a string
255
            $key = (string) $key;
256
257
            if (is_array($val)) {
258
                $input .= '<optgroup label="'.$key.'">'."\n";
259
                foreach ($val as $inner_key => $inner_val) {
260
                    // Inner key should always be a string
261
                    $inner_key = (string) $inner_key;
262
263
                    $sel = in_array($inner_key, $selected) ? ' selected="selected"' : '';
264
                    $input .= '<option value="'.$inner_key.'"'.$sel.'>'.$inner_val.'</option>'."\n";
265
                }
266
                $input .= '</optgroup>'."\n";
267
            } else {
268
                $sel = in_array($key, $selected) ? ' selected="selected"' : '';
269
                $input .= '<option value="'.$key.'"'.$sel.'>'.$val.'</option>'."\n";
270
            }
271
        }
272
        $input .= '</select>';
273
274
        return $input;
275
    }
276
277
    /**
278
     * Creates an HTML form checkbox input tag.
279
     *
280
     * @param   string|array  input name or an array of HTML attributes
281
     * @param   string        input value, when using a name
282
     * @param   boolean       make the checkbox checked by default
283
     * @param   string        a string to be attached to the end of the attributes
284
     * @return  string
285
     */
286 View Code Duplication
    public static function checkbox($data, $value = '', $checked = false, $extra = '')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
287
    {
288
        if (! is_array($data)) {
289
            $data = array('name' => $data);
290
        }
291
292
        $data['type'] = 'checkbox';
293
294
        if ($checked == true or (isset($data['checked']) and $data['checked'] == true)) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
Bug Best Practice introduced by
It seems like you are loosely comparing $data['checked'] of type string to the boolean true. If you are specifically checking for a non-empty string, consider using the more explicit !== '' instead.
Loading history...
295
            $data['checked'] = 'checked';
296
        } else {
297
            unset($data['checked']);
298
        }
299
300
        return form::input($data, $value, $extra);
301
    }
302
303
    /**
304
     * Creates an HTML form radio input tag.
305
     *
306
     * @param   string|array  input name or an array of HTML attributes
307
     * @param   string        input value, when using a name
308
     * @param   boolean       make the radio selected by default
309
     * @param   string        a string to be attached to the end of the attributes
310
     * @return  string
311
     */
312 View Code Duplication
    public static function radio($data = '', $value = '', $checked = false, $extra = '')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
313
    {
314
        if (! is_array($data)) {
315
            $data = array('name' => $data);
316
        }
317
318
        $data['type'] = 'radio';
319
320
        if ($checked == true or (isset($data['checked']) and $data['checked'] == true)) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
Bug Best Practice introduced by
It seems like you are loosely comparing $data['checked'] of type string to the boolean true. If you are specifically checking for a non-empty string, consider using the more explicit !== '' instead.
Loading history...
321
            $data['checked'] = 'checked';
322
        } else {
323
            unset($data['checked']);
324
        }
325
326
        return form::input($data, $value, $extra);
327
    }
328
329
    /**
330
     * Creates an HTML form submit input tag.
331
     *
332
     * @param   string|array  input name or an array of HTML attributes
333
     * @param   string        input value, when using a name
334
     * @param   string        a string to be attached to the end of the attributes
335
     * @return  string
336
     */
337
    public static function submit($data = '', $value = '', $extra = '')
338
    {
339
        if (! is_array($data)) {
340
            $data = array('name' => $data);
341
        }
342
343
        if (empty($data['name'])) {
344
            // Remove the name if it is empty
345
            unset($data['name']);
346
        }
347
348
        $data['type'] = 'submit';
349
350
        return form::input($data, $value, $extra);
351
    }
352
353
    /**
354
     * Creates an HTML form button input tag.
355
     *
356
     * @param   string|array  input name or an array of HTML attributes
357
     * @param   string        input value, when using a name
358
     * @param   string        a string to be attached to the end of the attributes
359
     * @return  string
360
     */
361
    public static function button($data = '', $value = '', $extra = '')
362
    {
363
        if (! is_array($data)) {
364
            $data = array('name' => $data);
365
        }
366
367
        if (empty($data['name'])) {
368
            // Remove the name if it is empty
369
            unset($data['name']);
370
        }
371
372
        if (isset($data['value']) and empty($value)) {
373
            $value = arr::remove('value', $data);
374
        }
375
376
        return '<button'.form::attributes($data, 'button').' '.$extra.'>'.$value.'</button>';
377
    }
378
379
    /**
380
     * Closes an open form tag.
381
     *
382
     * @param   string  string to be attached after the closing tag
383
     * @return  string
384
     */
385
    public static function close($extra = '')
386
    {
387
        return '</form>'."\n".$extra;
388
    }
389
390
    /**
391
     * Creates an HTML form label tag.
392
     *
393
     * @param   string|array  label "for" name or an array of HTML attributes
394
     * @param   string        label text or HTML
395
     * @param   string        a string to be attached to the end of the attributes
396
     * @return  string
397
     */
398
    public static function label($data = '', $text = null, $extra = '')
399
    {
400
        if (! is_array($data)) {
401
            if (is_string($data)) {
402
                // Specify the input this label is for
403
                $data = array('for' => $data);
404
            } else {
405
                // No input specified
406
                $data = array();
407
            }
408
        }
409
410
        if ($text === null and isset($data['for'])) {
411
            // Make the text the human-readable input name
412
            $text = ucwords(inflector::humanize($data['for']));
413
        }
414
415
        return '<label'.form::attributes($data).' '.$extra.'>'.$text.'</label>';
416
    }
417
418
    /**
419
     * Sorts a key/value array of HTML attributes, putting form attributes first,
420
     * and returns an attribute string.
421
     *
422
     * @param   array   HTML attributes array
423
     * @return  string
424
     */
425
    public static function attributes($attr, $type = null)
426
    {
427
        if (empty($attr)) {
428
            return '';
429
        }
430
431
        if (isset($attr['name']) and empty($attr['id']) and strpos($attr['name'], '[') === false) {
432
            if ($type === null and ! empty($attr['type'])) {
433
                // Set the type by the attributes
434
                $type = $attr['type'];
435
            }
436
437
            switch ($type) {
438
                case 'text':
439
                case 'textarea':
440
                case 'password':
441
                case 'select':
442
                case 'checkbox':
443
                case 'file':
444
                case 'image':
445
                case 'button':
446
                case 'submit':
447
                    // Only specific types of inputs use name to id matching
448
                    $attr['id'] = $attr['name'];
449
                break;
450
            }
451
        }
452
453
        $order = array(
454
            'action',
455
            'method',
456
            'type',
457
            'id',
458
            'name',
459
            'value',
460
            'src',
461
            'size',
462
            'maxlength',
463
            'rows',
464
            'cols',
465
            'accept',
466
            'tabindex',
467
            'accesskey',
468
            'align',
469
            'alt',
470
            'title',
471
            'class',
472
            'style',
473
            'selected',
474
            'checked',
475
            'readonly',
476
            'disabled'
477
        );
478
479
        $sorted = array();
480
        foreach ($order as $key) {
481
            if (isset($attr[$key])) {
482
                // Move the attribute to the sorted array
483
                $sorted[$key] = $attr[$key];
484
485
                // Remove the attribute from unsorted array
486
                unset($attr[$key]);
487
            }
488
        }
489
490
        // Combine the sorted and unsorted attributes and create an HTML string
491
        return html::attributes(array_merge($sorted, $attr));
492
    }
493
} // End form
494