Passed
Push — rename-getters ( eab17b )
by Dmitriy
02:49
created

Form::begin()   B

Complexity

Conditions 8
Paths 8

Size

Total Lines 40
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 8.0079

Importance

Changes 0
Metric Value
cc 8
eloc 20
nc 8
nop 0
dl 0
loc 40
ccs 19
cts 20
cp 0.95
crap 8.0079
rs 8.4444
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Form\Widget;
6
7
use Yiisoft\Arrays\ArrayHelper;
8
use Yiisoft\Html\Html;
9
use Yiisoft\Http\Method;
10
use Yiisoft\Widget\Widget;
11
12
use function explode;
13
use function implode;
14
use function strcasecmp;
15
use function strpos;
16
use function substr;
17
use function urldecode;
18
19
/**
20
 * A widget for rendering a form
21
 */
22
final class Form extends Widget
23
{
24
    private string $action = '';
25
    private string $method = Method::POST;
26
    private array $options = [];
27
28
    /**
29
     * Generates a form start tag.
30
     *
31
     * @throws \JsonException
32
     *
33
     * @return string the generated form start tag.
34
     *
35
     * {@see end())}
36
     */
37 11
    public function begin(): ?string
38
    {
39 11
        parent::begin();
40
41 11
        $hiddenInputs = [];
42
43 11
        $csrfToken = ArrayHelper::remove($this->options, 'csrf', false);
44
45 11
        if ($csrfToken && strcasecmp($this->method, Method::POST) === 0) {
46
            $hiddenInputs[] = Html::hiddenInput('_csrf', $csrfToken);
47
        }
48
49 11
        if (!strcasecmp($this->method, 'get') && ($pos = strpos($this->action, '?')) !== false) {
50
            /**
51
             * Query parameters in the action are ignored for GET method we use hidden fields to add them back.
52
             */
53 1
            foreach (explode('&', substr($this->action, $pos + 1)) as $pair) {
54 1
                if (($pos1 = strpos($pair, '=')) !== false) {
55 1
                    $hiddenInputs[] = Html::hiddenInput(
56 1
                        urldecode(substr($pair, 0, $pos1)),
57 1
                        urldecode(substr($pair, $pos1 + 1))
58
                    );
59
                } else {
60 1
                    $hiddenInputs[] = Html::hiddenInput(urldecode($pair), '');
61
                }
62
            }
63
64 1
            $this->action = substr($this->action, 0, $pos);
65
        }
66
67 11
        $this->options['action'] = $this->action;
68 11
        $this->options['method'] = $this->method;
69
70 11
        $form = Html::beginTag('form', $this->options);
71
72 11
        if (!empty($hiddenInputs)) {
73 1
            $form .= "\n" . implode("\n", $hiddenInputs);
74
        }
75
76 11
        return $form;
77
    }
78
79
    /**
80
     * Generates a form end tag.
81
     *
82
     * @return string the generated tag.
83
     *
84
     * {@see beginForm()}
85
     */
86 7
    public function run(): string
87
    {
88 7
        return '</form>';
89
    }
90
91 9
    public function action(string $value): self
92
    {
93 9
        $new = clone $this;
94 9
        $new->action = $value;
95 9
        return $new;
96
    }
97
98 3
    public function method(string $value): self
99
    {
100 3
        $new = clone $this;
101 3
        $new->method = $value;
102 3
        return $new;
103
    }
104
105 3
    public function options(array $value = []): self
106
    {
107 3
        $new = clone $this;
108 3
        $new->options = $value;
109 3
        return $new;
110
    }
111
}
112