Passed
Push — master ( 68d467...3da7f9 )
by Mikael
02:33
created

FormElement::offsetUnset()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 0
cts 3
cp 0
crap 2
1
<?php
2
3
namespace Anax\HTMLForm;
4
5
/**
6
 * A utility class to easy creating and handling of forms
7
 */
8
abstract class FormElement implements \ArrayAccess
9
{
10
11
    /**
12
     * @var array $attributes        settings to use to create element
13
     * @var array $config            default settings to use to create element
14
     * @var array $characterEncoding setting for character encoding
15
     */
16
    public $attributes;
17
    public $config;
18
    public $characterEncoding;
19
20
21
22
    /**
23
     * Constructor creating a form element.
24
     *
25
     * @param string $name       of the element.
26
     * @param array  $attributes to set to the element. Default is an empty
27
     *                           array.
28
     */
29 21
    public function __construct($name, $attributes = [])
30
    {
31 21
        $this->attributes = $attributes;
32 21
        $this['name'] = $name;
33
        //$this['key'] = $name;
34
        //$this['name'] = isset($this['name']) ? $this['name'] : $name;
35
36 21
        $this->characterEncoding = 'UTF-8';
37 21
        $this->default["wrapper-element"] = "p";
0 ignored issues
show
Bug introduced by
The property default does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
38 21
        $this->default["br-after-label"] = true;
39 21
    }
40
41
42
43
    /**
44
     * Set default values to use, merge incoming with existing.
45
     *
46
     * @param array  $options key value array with settings to use.
47
     *
48
     * @return void
49
     */
50
    public function setDefault($options)
51
    {
52
        $this->default = array_merge($this->default, $options);
53
    }
54
55
56
57
    /**
58
     * Implementing ArrayAccess for this->attributes
59
     *
60
     * @return void
61
     */
62 21
    public function offsetSet($offset, $value)
63
    {
64 21 View Code Duplication
        if (is_null($offset)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
65
            $this->attributes[] = $value;
66
        } else {
67 21
            $this->attributes[$offset] = $value;
68
        }
69 21
    }
70
71
72
73
    /**
74
     * Implementing ArrayAccess for this->attributes
75
     */
76 21
    public function offsetExists($offset)
77
    {
78 21
        return isset($this->attributes[$offset]);
79
    }
80
81
82
83
    /**
84
     * Implementing ArrayAccess for this->attributes
85
     */
86
    public function offsetUnset($offset)
87
    {
88
        unset($this->attributes[$offset]);
89
    }
90
91
92
93
    /**
94
     * Implementing ArrayAccess for this->attributes
95
     */
96 20
    public function offsetGet($offset)
97
    {
98 20
        return isset($this->attributes[$offset]) ? $this->attributes[$offset] : null;
99
    }
100
101
102
103
    /**
104
     * Get id of an element.
105
     *
106
     * @return HTML code for the element.
107
     */
108 9
    public function getElementId()
109
    {
110 9
        return ($this['id'] = isset($this['id']) ? $this['id'] : 'form-element-' . $this['name']);
111
    }
112
113
114
115
    /**
116
     * Get alll validation messages.
117
     *
118
     * @return HTML code for the element.
119
     */
120 9
    public function getValidationMessages()
121
    {
122 9
        $messages = null;
123 9
        if (isset($this['validation-messages'])) {
124
            $message = null;
125
            foreach ($this['validation-messages'] as $val) {
126
                $message .= "<li>{$val}</li>\n";
127
            }
128
            $messages = "<ul class='validation-message'>\n{$message}</ul>\n";
129
        }
130 9
        return $messages;
131
    }
132
133
134
135
    /**
136
     * Get details for a HTML element, prepare for creating HTML code for it.
137
     *
138
     * @return HTML code for the element.
139
     */
140 9
    public function getHTMLDetails()
141
    {
142
        // Add disabled to be able to disable a form element
143
        // Add maxlength
144 9
        $id =  $this->getElementId();
145
146 9
        $class = isset($this['class'])
147 9
            ? "{$this['class']}"
148 9
            : null;
149
150 9
        $validates = (isset($this['validation-pass']) && $this['validation-pass'] === false)
151 9
            ? ' validation-failed'
152 9
            : null;
153
154 9
        $class = (isset($class) || isset($validates))
155 9
            ? " class='{$class}{$validates}'"
156 9
            : null;
157
158 9
        $wrapperElement = isset($this['wrapper-element'])
159 9
            ? $this['wrapper-element']
160 9
            : $this->default["wrapper-element"];
161
162 9
        $wrapperClass = isset($this['wrapper-class'])
163 9
            ? " class=\"{$this['wrapper-class']}\""
164 9
            : null;
165
166 9
        $brAfterLabel = isset($this['br-after-label'])
167 9
            ? $this['br-after-label']
168 9
            : $this->default["br-after-label"];
169
170
        $brAfterLabel = $brAfterLabel
171 9
            ? "<br>"
172 9
            : null;
173
174 9
        $name = " name='{$this['name']}'";
175
176 9
        $label = isset($this['label'])
177 9
            ? ($this['label'] . (isset($this['required']) && $this['required']
178 5
                ? "<span class='form-element-required'>*</span>"
179 5
                : null))
180 9
            : null;
181
182 9
        $autofocus = isset($this['autofocus']) && $this['autofocus']
183 9
            ? " autofocus='autofocus'"
184 9
            : null;
185
186 9
        $required = isset($this['required']) && $this['required']
187 9
            ? " required='required'"
188 9
            : null;
189
190 9
        $readonly = isset($this['readonly']) && $this['readonly']
191 9
            ? " readonly='readonly'"
192 9
            : null;
193
194 9
        $placeholder = isset($this['placeholder']) && $this['placeholder']
195 9
            ? " placeholder='{$this['placeholder']}'"
196 9
            : null;
197
198 9
        $multiple = isset($this['multiple']) && $this['multiple']
199 9
            ? " multiple"
200 9
            : null;
201
202 9
        $max = isset($this['max'])
203 9
            ? " max='{$this['max']}'"
204 9
            : null;
205
206 9
        $min = isset($this['min'])
207 9
            ? " min='{$this['min']}'"
208 9
            : null;
209
210 9
        $low = isset($this['low'])
211 9
            ? " low='{$this['low']}'"
212 9
            : null;
213
214 9
        $high = isset($this['high'])
215 9
            ? " high='{$this['high']}'"
216 9
            : null;
217
218 9
        $optimum = isset($this['optimum'])
219 9
            ? " optimum='{$this['optimum']}'"
220 9
            : null;
221
222 9
        $step = isset($this['step'])
223 9
            ? " step='{$this['step']}'"
224 9
            : null;
225
226 9
        $size = isset($this['size'])
227 9
            ? " size='{$this['size']}'"
228 9
            : null;
229
230 9
        $text = isset($this['text'])
231 9
            ? htmlentities($this['text'], ENT_QUOTES, $this->characterEncoding)
232 9
            : null;
233
234 9
        $checked = isset($this['checked']) && $this['checked']
235 9
            ? " checked='checked'"
236 9
            : null;
237
238 9
        $type = isset($this['type'])
239 9
            ? " type='{$this['type']}'"
240 9
            : null;
241
242 9
        $title = isset($this['title'])
243 9
            ? " title='{$this['title']}'"
244 9
            : null;
245
246 9
        $pattern = isset($this['pattern'])
247 9
            ? " pattern='{$this['pattern']}'"
248 9
            : null;
249
250 9
        $description = isset($this['description'])
251 9
            ? $this['description']
252 9
            : null;
253
254 9
        $novalidate = isset($this['formnovalidate'])
255 9
            ? " formnovalidate='formnovalidate'"
256 9
            : null;
257
258 9
        $onlyValue = isset($this['value'])
259 9
            ? htmlentities($this['value'], ENT_QUOTES, $this->characterEncoding)
260 9
            : null;
261
262 9
        $value = isset($this['value'])
263 9
            ? " value='{$onlyValue}'"
264 9
            : null;
265
266 9
        $onclick = isset($this['onclick'])
267 9
            ? " onclick=\"{$this['onclick']}\""
268 9
            : null;
269
270 9
        $messages = $this->getValidationMessages();
271
272
        return [
273 9
            'id'             => $id,
274 9
            'class'          => $class,
275 9
            'wrapperElement' => $wrapperElement,
276 9
            'wrapperClass'   => $wrapperClass,
277 9
            'brAfterLabel'   => $brAfterLabel,
278 9
            'name'           => $name,
279 9
            'label'          => $label,
280 9
            'autofocus'      => $autofocus,
281 9
            'required'       => $required,
282 9
            'readonly'       => $readonly,
283 9
            'placeholder'    => $placeholder,
284 9
            'multiple'       => $multiple,
285 9
            'min'            => $min,
286 9
            'max'            => $max,
287 9
            'low'            => $low,
288 9
            'high'           => $high,
289 9
            'step'           => $step,
290 9
            'optimum'        => $optimum,
291 9
            'size'           => $size,
292 9
            'text'           => $text,
293 9
            'checked'        => $checked,
294 9
            'type'           => $type,
295 9
            'title'          => $title,
296 9
            'pattern'        => $pattern,
297 9
            'description'    => $description,
298 9
            'novalidate'     => $novalidate,
299 9
            'onlyValue'      => $onlyValue,
300 9
            'value'          => $value,
301 9
            'onclick'        => $onclick,
302 9
            'messages'       => $messages,
303 9
        ];
304
    }
305
306
307
308
    /**
309
     * Get HTML code for a element, must be implemented by each subclass.
310
     *
311
     * @return HTML code for the element.
312
     */
313
    abstract public function getHTML();
314
315
316
317
    /**
318
     * Validate the form element value according a ruleset.
319
     *
320
     * @param array     $rules validation rules.
321
     * @param Form|null $form  the parent form.
322
     *
323
     * @return boolean true if all rules pass, else false.
324
     */
325 2
    public function validate($rules, $form = null)
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
326
    {
327 2
        $regExpEmailAddress = '/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b/i';
0 ignored issues
show
Unused Code introduced by
$regExpEmailAddress is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
328
        $tests = [
329
            'fail' => [
330 2
                'message' => 'Will always fail.',
331
                'test' => 'return false;'
332 2
            ],
333
334
            'pass' => [
335 2
                'message' => 'Will always pass.',
336
                'test' => 'return true;'
337 2
            ],
338
339
            'not_empty' => [
340 2
                'message' => 'Can not be empty.',
341
                'test' => 'return $value != "";'
342 2
            ],
343
344
            'not_equal' => [
345 2
                'message' => 'Value not valid.',
346
                'test' => 'return $value != $arg;'
347 2
            ],
348
349
            'number' => [
350 2
                'message' => 'Must be a number.',
351
                'test' => 'return is_numeric($value);'
352 2
            ],
353
354
            'email' => [
355 2
                'message' => 'Must be an email adress.',
356 1
                'test' => function ($value) {
357 1
                    return preg_match('/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b/i', $value) === 1;
358
                }
359 2
            ],
360
361
            'match' => [
362 2
                'message' => 'The field does not match.',
363
                'test' => 'return $value == $form[$arg]["value"] ;'
364 2
            ],
365
366
            'must_accept' => [
367 2
                'message' => 'You must accept this.',
368
                'test' => 'return $checked;'
369 2
            ],
370
371 2
            'custom_test' => true,
372 2
        ];
373
374
        // max tecken, min tecken, datum, tid, datetime, mysql datetime
375
376 2
        $pass = true;
377 2
        $messages = array();
378 2
        $value = $this['value'];
379 2
        $checked = $this['checked'];
0 ignored issues
show
Unused Code introduced by
$checked is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
380
381 2
        foreach ($rules as $key => $val) {
382 2
            $rule = is_numeric($key) ? $val : $key;
383 2
            if (!isset($tests[$rule])) {
384 1
                throw new Exception("Validation of form element failed, no such validation rule exists: $rule");
385
            }
386 1
            $arg = is_numeric($key) ? null : $val;
387
388 1
            $test = ($rule == 'custom_test') ? $arg : $tests[$rule];
389 1
            $status = null;
0 ignored issues
show
Unused Code introduced by
$status is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
390 1
            if (is_callable($test['test'])) {
391 1
                $status = $test['test']($value);
392 1
            } else {
393
                $status = eval($test['test']);
394
            }
395
396 1
            if ($status === false) {
397
                $messages[] = $test['message'];
398
                $pass = false;
399
            }
400 1
        }
401
402 1
        if (!empty($messages)) {
403
            $this['validation-messages'] = $messages;
404
        }
405 1
        return $pass;
406
    }
407
408
409
410
    /**
411
     * Use the element name as label if label is not set.
412
     *
413
     * @param string $append a colon as default to the end of the label.
414
     *
415
     * @return void
416
     */
417 14
    public function useNameAsDefaultLabel($append = ':')
418
    {
419 14 View Code Duplication
        if (!isset($this['label'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
420 14
            $this['label'] = ucfirst(strtolower(str_replace(array('-','_'), ' ', $this['name']))).$append;
421 14
        }
422 14
    }
423
424
425
426
    /**
427
     * Use the element name as value if value is not set.
428
     *
429
     * @return void
430
     */
431 3
    public function useNameAsDefaultValue()
432
    {
433 3 View Code Duplication
        if (!isset($this['value'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
434 3
            $this['value'] = ucfirst(strtolower(str_replace(array('-','_'), ' ', $this['name'])));
435 3
        }
436 3
    }
437
438
439
440
    /**
441
     * Get the value of the form element.
442
     *
443
     * @return mixed the value of the form element.
444
     */
445 6
    public function getValue()
446
    {
447 6
        return $this['value'];
448
    }
449
450
451
452
    /**
453
     * Get the value of the form element.
454
     *
455
     * @return mixed the value of the form element.
456
     */
457
    public function value()
458
    {
459
        return $this['value'];
460
    }
461
462
463
464
    /**
465
     * Get the status of the form element if it is checked or not.
466
     *
467
     * @return mixed the value of the form element.
468
     */
469
    public function checked()
470
    {
471
        return $this['checked'];
472
    }
473
}
474