Completed
Push — master ( 4d0d20...444a32 )
by Mikael
04:04
created

Form::rawValue()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 6
ccs 4
cts 4
cp 1
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Anax\HTMLForm;
4
5
use \Anax\DI\DIInterface;
6
7
/**
8
 * A utility class to easy creating and handling of forms
9
 */
10
class Form implements \ArrayAccess
11
{
12
    /**
13
     * @var array $form       settings for the form
14
     * @var array $elements   all form elements
15
     * @var array $output     messages to display together with the form
16
     * @var array $sessionKey key values for the session
17
     */
18
    protected $form;
19
    protected $elements;
20
    protected $output;
21
    protected $sessionKey;
22
23
    /**
24
     * @var boolean $rememberValues remember values in the session.
25
     */
26
    protected $rememberValues;
27
28
    /**
29
     * @var Anax\DI\DIInterface $di the DI service container.
30
     */
31
    protected $di;
32
33
34
35
    /**
36
     * Constructor injects with DI container.
37
     *
38
     * @param Anax\DI\DIInterface $di a service container
39
     */
40 6
    public function __construct(DIInterface $di)
41
    {
42 6
        $this->di = $di;
0 ignored issues
show
Documentation Bug introduced by
It seems like $di of type object<Anax\DI\DIInterface> is incompatible with the declared type object<Anax\HTMLForm\Anax\DI\DIInterface> of property $di.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
43 6
    }
44
45
46
47
    /**
48
     * Implementing ArrayAccess for this->elements
49
     */
50
    public function offsetSet($offset, $value)
51
    {
52 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...
53
            $this->elements[] = $value;
54
        } else {
55
            $this->elements[$offset] = $value;
56
        }
57
    }
58
59
    public function offsetExists($offset)
60
    {
61
        return isset($this->elements[$offset]);
62
    }
63
64
    public function offsetUnset($offset)
65
    {
66
        unset($this->elements[$offset]);
67
    }
68
69
    public function offsetGet($offset)
70
    {
71
        return isset($this->elements[$offset])
72
            ? $this->elements[$offset]
73
            : null;
74
    }
75
76
77
78
    /**
79
     * Add a form element
80
     *
81
     * @param array $form     details for the form
82
     * @param array $elements all the elements
83
     *
84
     * @return $this
85
     */
86 6
    public function create($form = [], $elements = [])
87
    {
88
        $defaults = [
89
            // Always have an id
90 6
            "id" => "anax/htmlform",
91
92
            // Use a default class on <form> to ease styling
93 6
            "class" => "htmlform",
94
95
            // Wrap fields within <fieldset>
96 6
            "use_fieldset"  => true,
97
98
            // Use legend for fieldset, set it to string value
99 6
            "legend"        => null,
100
101
            // Default wrapper element around form elements
102 6
            "wrapper-element" => "p",
103
104
            // Use a <br> after the label, where suitable
105 6
            "br-after-label" => true,
106
107
            // Default is to always encode values
108 6
            "escape-values" => true,
109 6
        ];
110 6
        $this->form = array_merge($defaults, $form);
111
112 6
        $this->elements = [];
113 6
        if (!empty($elements)) {
114 4
            foreach ($elements as $key => $element) {
115 4
                $this->elements[$key] = FormElementFactory::create($key, $element);
116 4
                $this->elements[$key]->setDefault([
117 4
                    "wrapper-element" => $this->form["wrapper-element"],
118 4
                    "br-after-label"  => $this->form["br-after-label"],
119 4
                    "escape-values"   => $this->form["escape-values"],
120 4
                ]);
121 4
            }
122 4
        }
123
124
        // Default values for <output>
125 6
        $this->output = [];
126
127
        // Setting keys used in the session
128 6
        $generalKey = "anax/htmlform-" . $this->form["id"] . "#";
129 6
        $this->sessionKey = [
130 6
            "save"      => $generalKey . "save",
131 6
            "output"    => $generalKey . "output",
132 6
            "failed"    => $generalKey . "failed",
133 6
            "remember"  => $generalKey . "remember",
134
        ];
135
136 6
        return $this;
137
    }
138
139
140
141
    /**
142
     * Add a form element
143
     *
144
     * @param FormElement $element the formelement to add.
145
     *
146
     * @return $this
147
     */
148
    public function addElement($element)
149
    {
150
        $name = $element;
151
        if (isset($this->elements[$name])) {
152
            throw new Exception("Form element '$name' already exists, do not add it twice.");
153
        }
154
        $this[$element['name']] = $name;
155
        return $this;
156
    }
157
158
159
160
    /**
161
     * Get a form element
162
     *
163
     * @param string $name the name of the element.
164
     *
165
     * @return \Anax\HTMLForm\FormElement
166
     */
167 View Code Duplication
    public function getElement($name)
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...
168
    {
169
        if (!isset($this->elements[$name])) {
170
            throw new Exception("Form element '$name' is not found.");
171
        }
172
        return $this->elements[$name];
173
    }
174
175
176
177
    /**
178
     * Remove an form element
179
     *
180
     * @param string $name the name of the element.
181
     *
182
     * @return $this
183
     */
184 View Code Duplication
    public function removeElement($name)
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 (!isset($this->elements[$name])) {
187
            throw new Exception("Form element '$name' is not found.");
188
        }
189
        unset($this->elements[$name]);
190
        return $this;
191
    }
192
193
194
195
    /**
196
     * Set validation to a form element
197
     *
198
     * @param string $element the name of the formelement to add validation rules to.
199
     * @param array  $rules   array of validation rules.
200
     *
201
     * @return $this
202
     */
203
    public function setValidation($element, $rules)
204
    {
205
        $this[$element]['validation'] = $rules;
206
        return $this;
207
    }
208
209
210
211
    /**
212
     * Add output to display to the user for what happened whith the form and
213
     * optionally add a CSS class attribute.
214
     *
215
     * @param string $str   the string to add as output.
216
     * @param string $class a class attribute to set.
217
     *
218
     * @return $this.
0 ignored issues
show
Documentation introduced by
The doc-type $this. could not be parsed: Unknown type name "$this." at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
219
     */
220
    public function addOutput($str, $class = null)
221
    {
222
        $key     = $this->sessionKey["output"];
223
        $session = $this->di->get("session");
224
        $output  = $session->get($key);
225
226
        $output["message"] = isset($output["message"])
227
            ? $output["message"] . " $str"
228
            : $str;
229
230
        if ($class) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $class of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
231
            $output["class"] = $class;
232
        }
233
        $session->set($key, $output);
234
235
        return $this;
236
    }
237
238
239
240
    /**
241
     * Set a CSS class attribute for the <output> element.
242
     *
243
     * @param string $class a class attribute to set.
244
     *
245
     * @return $this.
0 ignored issues
show
Documentation introduced by
The doc-type $this. could not be parsed: Unknown type name "$this." at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
246
     */
247
    public function setOutputClass($class)
248
    {
249
        $key     = $this->sessionKey["output"];
250
        $session = $this->di->get("session");
251
        $output  = $session->get($key);
252
        $output["class"] = $class;
253
        $session->set($key, $output);
254
        return $this;
255
    }
256
257
258
259
    /**
260
     * Remember current values in session, useful for storing values of
261
     * current form when submitting it.
262
     *
263
     * @return $this.
0 ignored issues
show
Documentation introduced by
The doc-type $this. could not be parsed: Unknown type name "$this." at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
264
     */
265
    public function rememberValues()
266
    {
267
        $this->rememberValues = true;
268
        return $this;
269
    }
270
271
272
273
274
    /**
275
     * Get value of a form element and respect settings of escaped or
276
     * raw value.
277
     *
278
     * @param string $name the name of the formelement.
279
     *
280
     * @return mixed the value of the element.
281
     */
282
    public function value($name)
283
    {
284
        return isset($this->elements[$name])
285
            ? $this->elements[$name]->value()
286
            : null;
287
    }
288
289
290
291
    /**
292
     * Get escaped value of a form element.
293
     *
294
     * @param string $name the name of the formelement.
295
     *
296
     * @return mixed the value of the element.
297
     */
298 4
    public function escValue($name)
299
    {
300 4
        return isset($this->elements[$name])
301 4
            ? $this->elements[$name]->getEscapedValue()
302 4
            : null;
303
    }
304
305
306
307
    /**
308
     * Get raw value of a form element.
309
     *
310
     * @param string $name the name of the formelement.
311
     *
312
     * @return mixed the value of the element.
313
     */
314 4
    public function rawValue($name)
315
    {
316 4
        return isset($this->elements[$name])
317 4
            ? $this->elements[$name]->getRawValue()
318 4
            : null;
319
    }
320
321
322
323
    /**
324
     * Check if a element is checked
325
     *
326
     * @param string $name the name of the formelement.
327
     *
328
     * @return mixed the value of the element.
329
     */
330
    public function checked($name)
331
    {
332
        return isset($this->elements[$name])
333
            ? $this->elements[$name]->checked()
334
            : null;
335
    }
336
337
338
339
    /**
340
     * Return HTML for the form.
341
     *
342
     * @param array $options with options affecting the form output.
343
     *
344
     * @return string with HTML for the form.
345
     */
346 2
    public function getHTML($options = [])
347
    {
348
        $defaults = [
349
            // Only return the start of the form element
350 2
            'start'         => false,
351
352
            // Layout all elements in one column
353 2
            'columns'       => 1,
354
355
            // Layout consequtive buttons as one element wrapped in <p>
356 2
            'use_buttonbar' => true,
357 2
        ];
358 2
        $options = array_merge($defaults, $options);
359
360 2
        $form = array_merge($this->form, $options);
361 2
        $id      = isset($form['id'])      ? " id='{$form['id']}'" : null;
362 2
        $class   = isset($form['class'])   ? " class='{$form['class']}'" : null;
363 2
        $name    = isset($form['name'])    ? " name='{$form['name']}'" : null;
364 2
        $action  = isset($form['action'])  ? " action='{$form['action']}'" : null;
365 2
        $method  = isset($form['method'])  ? " method='{$form['method']}'" : " method='post'";
366 2
        $enctype = isset($form['enctype']) ? " enctype='{$form['enctype']}'" : null;
367 2
        $cformId = isset($form['id'])      ? "{$form['id']}" : null;
368
369 2
        if ($options['start']) {
370
            return "<form{$id}{$class}{$name}{$action}{$method}>\n";
371
        }
372
373 2
        $fieldsetStart  = '<fieldset>';
374 2
        $legend         = null;
375 2
        $fieldsetEnd    = '</fieldset>';
376 2
        if (!$form['use_fieldset']) {
377
            $fieldsetStart = $fieldsetEnd = null;
378
        }
379
380 2
        if ($form['use_fieldset'] && $form['legend']) {
381
            $legend = "<legend>{$form['legend']}</legend>";
382
        }
383
384 2
        $elementsArray  = $this->getHTMLForElements($options);
385 2
        $elements       = $this->getHTMLLayoutForElements($elementsArray, $options);
386 2
        $output         = $this->getOutput();
387
388
        $html = <<< EOD
389 2
\n<form{$id}{$class}{$name}{$action}{$method}{$enctype}>
390 2
<input type="hidden" name="anax/htmlform-id" value="$cformId" />
391 2
{$fieldsetStart}
392 2
{$legend}
393 2
{$elements}
394 2
{$output}
395 2
{$fieldsetEnd}
396 2
</form>\n
397 2
EOD;
398
399 2
        return $html;
400
    }
401
402
403
404
    /**
405
     * Return HTML for the elements
406
     *
407
     * @param array $options with options affecting the form output.
408
     *
409
     * @return array with HTML for the formelements.
410
     */
411 2
    public function getHTMLForElements($options = [])
412
    {
413
        $defaults = [
414 2
            'use_buttonbar' => true,
415 2
        ];
416 2
        $options = array_merge($defaults, $options);
417
418 2
        $elements = array();
419 2
        reset($this->elements);
420 2
        while (list($key, $element) = each($this->elements)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $key is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
421
            if (in_array($element['type'], array('submit', 'reset', 'button'))
422
                && $options['use_buttonbar']
423
            ) {
424
                // Create a buttonbar
425
                $name = 'buttonbar';
426
                $html = "<p class='buttonbar'>\n" . $element->GetHTML() . '&nbsp;';
427
428
                // Get all following submits (and buttons)
429
                while (list($key, $element) = each($this->elements)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $key is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
430
                    if (in_array($element['type'], array('submit', 'reset', 'button'))) {
431
                        $html .= $element->GetHTML();
432
                    } else {
433
                        prev($this->elements);
434
                        break;
435
                    }
436
                }
437
                $html .= "\n</p>";
438
            } else {
439
                // Just add the element
440
                $name = $element['name'];
441
                $html = $element->GetHTML();
442
            }
443
444
            $elements[] = array('name'=>$name, 'html'=> $html);
445
        }
446
447 2
        return $elements;
448
    }
449
450
451
452
453
    /**
454
     * Place the elements according to a layout and return the HTML
455
     *
456
     * @param array $elements as returned from GetHTMLForElements().
457
     * @param array $options  with options affecting the layout.
458
     *
459
     * @return array with HTML for the formelements.
460
     */
461 6
    public function getHTMLLayoutForElements($elements, $options = [])
462 4
    {
463
        $defaults = [
464 2
            'columns' => 1,
465 2
            'wrap_at_element' => false,  // Wraps column in equal size or at the set number of elements
466 2
        ];
467 2
        $options = array_merge($defaults, $options);
468
469 2
        $html = null;
470 2
        if ($options['columns'] === 1) {
471 2
            foreach ($elements as $element) {
472
                $html .= $element['html'];
473 2
            }
474 6
        } elseif ($options['columns'] === 2) {
475
            $buttonbar = null;
476
            $col1 = null;
477
            $col2 = null;
478
479
            $end = end($elements);
480
            if ($end['name'] == 'buttonbar') {
481
                $end = array_pop($elements);
482
                $buttonbar = "<div class='cform-buttonbar'>\n{$end['html']}</div>\n";
483
            }
484
485
            $size = count($elements);
486
            $wrapAt = $options['wrap_at_element'] ? $options['wrap_at_element'] : round($size/2);
487
            for ($i=0; $i<$size; $i++) {
488
                if ($i < $wrapAt) {
489
                    $col1 .= $elements[$i]['html'];
490
                } else {
491
                    $col2 .= $elements[$i]['html'];
492
                }
493
            }
494
495
            $html = <<<EOD
496
<div class='cform-columns-2'>
497
<div class='cform-column-1'>
498
{$col1}
499
</div>
500
<div class='cform-column-2'>
501
{$col2}
502
</div>
503
{$buttonbar}</div>
504
EOD;
505
        }
506
507 2
        return $html;
508
    }
509
510
511
512
    /**
513
     * Get an array with all elements that failed validation together with their id and validation message.
514
     *
515
     * @return array with elements that failed validation.
516
     */
517
    public function getValidationErrors()
518
    {
519
        $errors = [];
520
        foreach ($this->elements as $name => $element) {
521
            if ($element['validation-pass'] === false) {
522
                $errors[$name] = [
523
                    'id' => $element->GetElementId(),
524
                    'label' => $element['label'],
525
                    'message' => implode(' ', $element['validation-messages'])
526
                ];
527
            }
528
        }
529
        return $errors;
530
    }
531
532
533
534
    /**
535
     * Get output messages as <output>.
536
     *
537
     * @return string|null with the complete <output> element or null if no output.
538
     */
539 2
    public function getOutput()
540
    {
541 2
        $output = $this->output;
542 2
        $message = isset($output["message"]) && !empty($output["message"])
543 2
            ? $output["message"]
544 2
            : null;
545
546 2
        $class = isset($output["class"]) && !empty($output["class"])
547 2
            ? " class=\"{$output["class"]}\""
548 2
            : null;
549
550
        return $message
551 2
            ? "<output{$class}>{$message}</output>"
552 2
            : null;
553
    }
554
555
556
557
    /**
558
     * Init all element with values from session, clear all and fill in with values from the session.
559
     *
560
     * @param array $values retrieved from session
561
     *
562
     * @return void
563
     */
564
    protected function initElements($values)
565
    {
566
        // First clear all
567
        foreach ($this->elements as $key => $val) {
568
            // Do not reset value for buttons
569
            if (in_array($this[$key]['type'], array('submit', 'reset', 'button'))) {
570
                continue;
571
            }
572
573
            // Reset the value
574
            $this[$key]['value'] = null;
575
576
            // Checkboxes must be cleared
577
            if (isset($this[$key]['checked'])) {
578
                $this[$key]['checked'] = false;
579
            }
580
        }
581
582
        // Now build up all values from $values (session)
583
        foreach ($values as $key => $val) {
584
            // Take care of arrays as values (multiple-checkbox)
585
            if (isset($val['values'])) {
586
                $this[$key]['checked'] = $val['values'];
587
                //$this[$key]['values']  = $val['values'];
588
            } elseif (isset($val['value'])) {
589
                $this[$key]['value'] = $val['value'];
590
            }
591
592
            if ($this[$key]['type'] === 'checkbox') {
593
                $this[$key]['checked'] = true;
594
            } elseif ($this[$key]['type'] === 'radio') {
595
                $this[$key]['checked'] = $val['value'];
596
            }
597
598
            // Keep track on validation messages if set
599
            if (isset($val['validation-messages'])) {
600
                $this[$key]['validation-messages'] = $val['validation-messages'];
601
                $this[$key]['validation-pass'] = false;
602
            }
603
        }
604
    }
605
606
607
608
    /**
609
     * Check if a form was submitted and perform validation and call callbacks.
610
     * The form is stored in the session if validation or callback fails. The
611
     * page should then be redirected to the original form page, the form
612
     * will populate from the session and should be rendered again.
613
     * Form elements may remember their value if 'remember' is set and true.
614
     *
615
     * @param callable $callIfSuccess handler to call if function returns true.
616
     * @param callable $callIfFail    handler to call if function returns true.
617
     *
618
     * @throws \Anax\HTMLForm\Exception
619
     *
620
     * @return boolean|null $callbackStatus if submitted&validates, false if
621
     *                                      not validate, null if not submitted.
622
     *                                      If submitted the callback function
623
     *                                      will return the actual value which
624
     *                                      should be true or false.
625
     */
626
    public function check($callIfSuccess = null, $callIfFail = null)
627
    {
628
        $remember = null;
629
        $validates = null;
0 ignored issues
show
Unused Code introduced by
$validates 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...
630
        $callbackStatus = null;
631
        $values = [];
632
633
        // Remember flash output messages in session
634
        $output = $this->sessionKey["output"];
635
        $session = $this->di->get("session");
636
        $this->output = $session->getOnce($output, []);
637
638
        // Check if this was a post request
639
        $requestMethod = $this->di->get("request")->getServer("REQUEST_METHOD");
640
        if ($requestMethod !== "POST") {
641
            // Its not posted, but check if values should be used from session
642
            $failed   = $this->sessionKey["failed"];
643
            $remember = $this->sessionKey["remember"];
644
            $save     = $this->sessionKey["save"];
645
646
            if ($session->has($failed)) {
647
                // Read form data from session if the previous post failed
648
                // during validation.
649
                $this->InitElements($session->getOnce($failed));
650
            } elseif ($session->has($remember)) {
651
                // Read form data from session if some form elements should
652
                // be remembered
653
                foreach ($session->getOnce($remember) as $key => $val) {
654
                    $this[$key]['value'] = $val['value'];
655
                }
656
            } elseif ($session->has($save)) {
657
                // Read form data from session,
658
                // useful during test where the original form is displayed
659
                // with its posted values
660
                $this->InitElements($session->getOnce($save));
661
            }
662
663
            return null;
664
        }
665
666
        $request = $this->di->get("request");
667
        $formid = $request->getPost("anax/htmlform-id");
668
        // Check if its a form we are dealing with
669
        if (!$formid) {
670
            return null;
671
        }
672
673
        // Check if its this form that was posted
674
        if ($this->form["id"] !== $formid) {
675
            return null;
676
        }
677
678
        // This form was posted, process it
679
        $session->delete($this->sessionKey["failed"]);
680
        $validates = true;
681
        foreach ($this->elements as $element) {
682
            $elementName = $element['name'];
683
            $elementType = $element['type'];
684
685
            $postElement = $request->getPost($elementName);
686
            if ($postElement) {
687
                // The form element has a value set
688
                // Multiple choices comes in the form of an array
689
                if (is_array($postElement)) {
690
                    $values[$elementName]['values'] = $element['checked'] = $postElement;
691
                } else {
692
                    $values[$elementName]['value'] = $element['value'] = $postElement;
693
                }
694
695
                // If the element is a password, do not remember.
696
                if ($elementType === 'password') {
697
                    $values[$elementName]['value'] = null;
698
                }
699
700
                // If the element is a checkbox, set its value of checked.
701
                if ($elementType === 'checkbox') {
702
                    $element['checked'] = true;
703
                }
704
705
                // If the element is a radio, set the value to checked.
706
                if ($elementType === 'radio') {
707
                    $element['checked'] = $element['value'];
708
                }
709
710
                // Do validation of form element
711 View Code Duplication
                if (isset($element['validation'])) {
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...
712
                    $element['validation-pass'] = $element->Validate($element['validation'], $this);
713
714
                    if ($element['validation-pass'] === false) {
715
                        $values[$elementName] = [
716
                            'value' => $element['value'],
717
                            'validation-messages' => $element['validation-messages']
718
                        ];
719
                        $validates = false;
720
                    }
721
                }
722
723
                // Hmmm.... Why did I need this remember thing?
724
                if (isset($element['remember'])
725
                    && $element['remember']
726
                ) {
727
                    $values[$elementName] = ['value' => $element['value']];
728
                    $remember = true;
729
                }
730
731
                // Carry out the callback if the form element validates
732
                // Hmmm, what if the element with the callback is not the last element?
733
                if (isset($element['callback'])
734
                    && $validates
735
                ) {
736
                    if (isset($element['callback-args'])) {
737
                        $callbackStatus = call_user_func_array(
738
                            $element['callback'],
739
                            array_merge([$this]),
740
                            $element['callback-args']
741
                        );
742
                    } else {
743
                        $callbackStatus = call_user_func($element['callback'], $this);
744
                    }
745
                }
746
            } else {
747
                // The form element has no value set
748
749
                // Set element to null, then we know it was not set.
750
                //$element['value'] = null;
751
                //echo $element['type'] . ':' . $elementName . ':' . $element['value'] . '<br>';
752
753
                // If the element is a checkbox, clear its value of checked.
754
                if ($element['type'] === 'checkbox'
755
                    || $element['type'] === 'checkbox-multiple'
756
                ) {
757
                    $element['checked'] = false;
758
                }
759
760
                // Do validation even when the form element is not set?
761
                // Duplicate code, revise this section and move outside
762
                // this if-statement?
763 View Code Duplication
                if (isset($element['validation'])) {
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...
764
                    $element['validation-pass'] = $element->Validate($element['validation'], $this);
765
766
                    if ($element['validation-pass'] === false) {
767
                        $values[$elementName] = [
768
                            'value' => $element['value'], 'validation-messages' => $element['validation-messages']
769
                        ];
770
                        $validates = false;
771
                    }
772
                }
773
            }
774
        }
775
776
        // Prepare if data should be stored in the session during redirects
777
        // Did form validation or the callback fail?
778
        if ($validates === false
779
            || $callbackStatus === false
780
        ) {
781
            $session->set($this->sessionKey["failed"], $values);
782
        } elseif ($remember) {
783
            // Hmmm, why do I want to use this
784
            $session->set($this->sessionKey["remember"], $values);
785
        }
786
787
        if ($this->rememberValues) {
788
            // Remember all posted values
789
            $session->set($this->sessionKey["save"], $values);
790
        }
791
792
        // Lets se what the return value should be
793
        $ret = $validates
794
            ? $callbackStatus
795
            : $validates;
796
797
798
        if ($ret === true && isset($callIfSuccess)) {
799
            // Use callback for success, if defined
800
            if (!is_callable($callIfSuccess)) {
801
                throw new Exception("Form, success-method is not callable.");
802
            }
803
            call_user_func_array($callIfSuccess, [$this]);
804
        } elseif ($ret === false && isset($callIfFail)) {
805
            // Use callback for fail, if defined
806
            if (!is_callable($callIfFail)) {
807
                throw new Exception("Form, success-method is not callable.");
808
            }
809
            call_user_func_array($callIfFail, [$this]);
810
        }
811
812
        return $ret;
813
    }
814
}
815