Passed
Push — 5.x ( 65a76f...3a1e20 )
by Enjoys
59s queued 13s
created

Form::getDefaultsHandler()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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