Passed
Push — 5.x ( 4d7971...bef106 )
by Enjoys
02:40
created

Form::setSubmitted()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2
c 1
b 0
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Enjoys\Forms;
6
7
use Closure;
8
use Enjoys\Forms\Elements\Csrf;
9
use Enjoys\Forms\Elements\TokenSubmit;
10
use Enjoys\Forms\Interfaces\DefaultsHandlerInterface;
11
use Enjoys\Forms\Traits;
12
use Enjoys\ServerRequestWrapper;
13
use Enjoys\ServerRequestWrapperInterface;
14
use Enjoys\Session\Session;
15
use Enjoys\Traits\Options;
16
use HttpSoft\ServerRequest\ServerRequestCreator;
17
use Webmozart\Assert\Assert;
18
19
use function json_encode;
20
use function strtoupper;
21
22
/**
23
 * Class Form
24
 * @package Enjoys\Forms
25
 */
26
class Form
27
{
28
    use Traits\Attributes;
29
    use Options;
30
    use Traits\Container {
31
        addElement as private parentAddElement;
32
    }
33
34
    private const _ALLOWED_FORM_METHOD_ = ['GET', 'POST'];
35
36
    public const _TOKEN_CSRF_ = '_token_csrf';
37
    public const _TOKEN_SUBMIT_ = '_token_submit';
38
39
    //public const _FLAG_FORMMETHOD_ = '_form_method';
40
    public const ATTRIBUTES_DESC = '_desc_attributes_';
41
    public const ATTRIBUTES_VALIDATE = '_validate_attributes_';
42
    public const ATTRIBUTES_LABEL = '_label_attributes_';
43
    public const ATTRIBUTES_FIELDSET = '_fieldset_attributes_';
44
    public const ATTRIBUTES_FILLABLE_BASE = '_fillable_base_attributes_';
45
46
47
    private string $method = 'POST';
48
    private ?string $action = null;
49
    private ?string $id = null;
50
51
    private ServerRequestWrapperInterface $request;
52
    private DefaultsHandlerInterface $defaultsHandler;
53
54
    private bool $submitted = false;
55
    private Session $session;
56
57
    /**
58
     * @throws Exception\ExceptionRule
59
     */
60 80
    public function __construct(
61
        string $method = 'POST',
62
        string $action = null,
63
        string $id = null,
64
        ServerRequestWrapperInterface $request = null,
65
        DefaultsHandlerInterface $defaultsHandler = null,
66
        Session $session = null
67
    ) {
68 80
        $this->request = $request ?? new ServerRequestWrapper(ServerRequestCreator::createFromGlobals());
69 80
        $this->session = $session ?? new Session();
70 80
        $this->defaultsHandler = $defaultsHandler ?? new DefaultsHandler();
71
72 80
        $this->setMethod($method);
73 80
        $this->setAction($action);
74 80
        $this->setId($id);
75
76 80
        if ($this->submitted === true) {
77
            $this->setDefaults([]);
78
        }
79
80
    }
81
82 80
    private function setSubmitted(bool $submitted): Form
83
    {
84 80
        $this->submitted = $submitted;
85 80
        return $this;
86
    }
87
88
    /**
89
     * Возвращает true если форма отправлена и валидна.
90
     * На валидацию форма проверяется по умолчанию, если использовать параметр $validate
91
     * false, проверка будет только на отправку формы
92
     * @param bool $validate
93
     * @return bool
94
     */
95 5
    public function isSubmitted(bool $validate = true): bool
96
    {
97 5
        if ($this->submitted === false) {
98 2
            return false;
99
        }
100
        //  dump($this->getElements());
101 4
        if ($validate !== false) {
102 2
            return Validator::check($this->getElements());
103
        }
104
105 2
        return true;
106
    }
107
108
109
    /**
110
     * @param array|Closure():array $data
111
     * @return $this
112
     * @noinspection PhpMissingParamTypeInspection
113
     */
114 21
    public function setDefaults($data): Form
115
    {
116 21
        if ($data instanceof Closure) {
117 1
            $data = $data();
118
        }
119
120 21
        Assert::isArray($data);
121
122 20
        if ($this->submitted === true) {
123 3
            $data = [];
124
125 3
            $requestData = match (strtolower($this->getMethod())) {
126 2
                'get' => $this->getRequest()->getQueryData()->toArray(),
127 1
                'post' => $this->getRequest()->getPostData()->toArray(),
128
                default => [],
129
            };
130
131 3
            foreach ($requestData as $key => $items) {
132 3
                if (in_array($key, [self::_TOKEN_CSRF_, self::_TOKEN_SUBMIT_])) {
133
                    continue;
134
                }
135 3
                $data[$key] = $items;
136
            }
137
        }
138 20
        $this->defaultsHandler->setData($data);
139 20
        return $this;
140
    }
141
142
143
    /**
144
     *
145
     * Если prepare() возвращает false, то элемент добавляется,
146
     * если true, то элемент добавлен в коллекцию не будет.
147
     * @use Element::setForm()
148
     * @use Element::prepare()
149
     * @param Element $element
150
     * @return $this
151
     */
152 80
    public function addElement(Element $element): self
153
    {
154 80
        $element->setForm($this);
155 80
        return $this->parentAddElement($element);
156
    }
157
158
159 80
    public function getDefaultsHandler(): DefaultsHandlerInterface
160
    {
161 80
        return $this->defaultsHandler;
162
    }
163
164 80
    public function getRequest(): ServerRequestWrapperInterface
165
    {
166 80
        return $this->request;
167
    }
168
169
    /**
170
     * @throws Exception\ExceptionRule
171
     */
172 80
    public function setMethod(string $method): void
173
    {
174 80
        if (in_array(strtoupper($method), self::_ALLOWED_FORM_METHOD_)) {
175 79
            $this->method = strtoupper($method);
176
        }
177 80
        $this->setAttribute(AttributeFactory::create('method', $this->method));
178 80
        $this->setOption('method', $this->method, false);
179 80
        $this->addElement(new Csrf($this->session));
180 80
        $this->setTokenSubmitElement();
181
    }
182
183 80
    public function getMethod(): string
184
    {
185 80
        return $this->method;
186
    }
187
188 80
    public function setAction(?string $action): self
189
    {
190 80
        $this->action = $action;
191 80
        $this->setAttribute(AttributeFactory::create('action', $this->action));
192 80
        $this->setOption('action', $this->action, false);
193 80
        $this->setTokenSubmitElement();
194 80
        return $this;
195
    }
196
197 5
    public function getAction(): ?string
198
    {
199 5
        return $this->action;
200
    }
201
202 80
    public function setId(?string $id): Form
203
    {
204 80
        $this->id = $id;
205 80
        $this->setAttribute(AttributeFactory::create('id', $this->id));
206 80
        $this->setOption('id', $this->id, false);
207 80
        $this->setTokenSubmitElement();
208 80
        return $this;
209
    }
210
211
212
    public function getId(): ?string
213
    {
214
        return $this->id;
215
    }
216
217 80
    private function setTokenSubmitElement(): void
218
    {
219 80
        $tokenSubmit = new TokenSubmit(md5(json_encode($this->getOptions())));
220 80
        $this->addElement($tokenSubmit);
221 80
        $this->setSubmitted($tokenSubmit->getSubmitted());
222
    }
223
224
//    /**
225
//     * Вывод формы в Renderer
226
//     * @param \Enjoys\Forms\Interfaces\RendererInterface $renderer
227
//     * @return mixed Возвращается любой формат, в зависимоти от renderer`а, может
228
//     * вернутся строка в html, или, например, xml или массив, все зависит от рендерера.
229
//     */
230
//    public function render(\Enjoys\Forms\Interfaces\RendererInterface $renderer): mixed
231
//    {
232
//        $renderer->setForm($this);
233
//        return $renderer->output();
234
//    }
235
}
236