Skip to content

Commit 91cbc96

Browse files
committed
Container: detects property type of mapped class
1 parent c57f604 commit 91cbc96

File tree

2 files changed

+325
-1
lines changed

2 files changed

+325
-1
lines changed

src/Forms/Container.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,16 @@ public function getValues($returnType = null)
113113

114114
$isArray = $returnType === self::ARRAY;
115115
$obj = $isArray ? new \stdClass : new $returnType;
116+
$rc = new \ReflectionClass($obj);
116117

117118
foreach ($this->getComponents() as $name => $control) {
118119
if ($control instanceof IControl && !$control->isOmitted()) {
119120
$obj->$name = $control->getValue();
120121
} elseif ($control instanceof self) {
121-
$obj->$name = $control->getValues($isArray && !$control->mappedType ? self::ARRAY : null);
122+
$type = $isArray && !$control->mappedType
123+
? self::ARRAY
124+
: ($rc->hasProperty($name) ? Nette\Utils\Reflection::getPropertyType($rc->getProperty($name)) : null);
125+
$obj->$name = $control->getValues($type);
122126
}
123127
}
124128
return $isArray ? (array) $obj : $obj;
Lines changed: 320 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
<?php
2+
3+
/**
4+
* @phpVersion 7.4
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
use Nette\Forms\Form;
10+
use Nette\Utils\ArrayHash;
11+
use Tester\Assert;
12+
13+
14+
require __DIR__ . '/../bootstrap.php';
15+
16+
17+
class FormData
18+
{
19+
/** @var string */
20+
public $title;
21+
22+
public FormFirstLevel $first;
23+
}
24+
25+
26+
class FormFirstLevel
27+
{
28+
/** @var string */
29+
public $name;
30+
31+
/** @var int */
32+
public $age;
33+
34+
/** @var FormSecondLevel */
35+
public $second;
36+
}
37+
38+
39+
class FormSecondLevel
40+
{
41+
/** @var string */
42+
public $city;
43+
}
44+
45+
46+
function hydrate(string $class, array $data)
47+
{
48+
$obj = new $class;
49+
foreach ($data as $key => $value) {
50+
$obj->$key = $value;
51+
}
52+
return $obj;
53+
}
54+
55+
56+
$_POST = [
57+
'title' => 'sent title',
58+
'first' => [
59+
'age' => '999',
60+
'second' => [
61+
'city' => 'sent city',
62+
],
63+
],
64+
];
65+
66+
67+
function createForm(): Form
68+
{
69+
$form = new Form;
70+
$form->addText('title');
71+
72+
$first = $form->addContainer('first');
73+
$first->addText('name');
74+
$first->addInteger('age');
75+
76+
$second = $first->addContainer('second');
77+
$second->addText('city');
78+
return $form;
79+
}
80+
81+
82+
test(function () { // setDefaults() + object
83+
$form = createForm();
84+
Assert::false($form->isSubmitted());
85+
86+
$form->setDefaults(hydrate(FormData::class, [
87+
'title' => 'xxx',
88+
'extra' => '50',
89+
'first' => hydrate(FormFirstLevel::class, [
90+
'name' => 'yyy',
91+
'age' => '30',
92+
'second' => hydrate(FormSecondLevel::class, [
93+
'city' => 'zzz',
94+
]),
95+
]),
96+
]));
97+
98+
Assert::same([
99+
'title' => 'xxx',
100+
'first' => [
101+
'name' => 'yyy',
102+
'age' => '30',
103+
'second' => [
104+
'city' => 'zzz',
105+
],
106+
],
107+
], $form->getValues(true));
108+
});
109+
110+
111+
test(function () { // submitted form + getValues()
112+
$_SERVER['REQUEST_METHOD'] = 'POST';
113+
114+
$form = createForm();
115+
$form->setMappedType(FormData::class);
116+
117+
Assert::truthy($form->isSubmitted());
118+
Assert::equal(hydrate(FormData::class, [
119+
'title' => 'sent title',
120+
'first' => hydrate(FormFirstLevel::class, [
121+
'name' => '',
122+
'age' => '999',
123+
'second' => ArrayHash::from([
124+
'city' => 'sent city',
125+
]),
126+
]),
127+
]), $form->getValues());
128+
});
129+
130+
131+
test(function () { // submitted form + reset()
132+
$_SERVER['REQUEST_METHOD'] = 'POST';
133+
134+
$form = createForm();
135+
$form->setMappedType(FormData::class);
136+
137+
Assert::truthy($form->isSubmitted());
138+
139+
$form->reset();
140+
141+
Assert::false($form->isSubmitted());
142+
Assert::equal(hydrate(FormData::class, [
143+
'title' => '',
144+
'first' => hydrate(FormFirstLevel::class, [
145+
'name' => '',
146+
'age' => null,
147+
'second' => ArrayHash::from([
148+
'city' => '',
149+
]),
150+
]),
151+
]), $form->getValues());
152+
});
153+
154+
155+
test(function () { // setValues() + object
156+
$_SERVER['REQUEST_METHOD'] = 'POST';
157+
158+
$form = createForm();
159+
$form->setMappedType(FormData::class);
160+
161+
Assert::truthy($form->isSubmitted());
162+
163+
$form->setValues(hydrate(FormData::class, [
164+
'title' => 'new1',
165+
'first' => hydrate(FormFirstLevel::class, [
166+
'name' => 'new2',
167+
// age => null
168+
]),
169+
]));
170+
171+
Assert::equal(hydrate(FormData::class, [
172+
'title' => 'new1',
173+
'first' => hydrate(FormFirstLevel::class, [
174+
'name' => 'new2',
175+
'age' => null,
176+
'second' => ArrayHash::from([
177+
'city' => 'sent city',
178+
]),
179+
]),
180+
]), $form->getValues());
181+
182+
// erase
183+
$form->setValues(hydrate(FormData::class, [
184+
'title' => 'new1',
185+
'first' => hydrate(FormFirstLevel::class, [
186+
'name' => 'new2',
187+
]),
188+
]), true);
189+
190+
Assert::equal(hydrate(FormData::class, [
191+
'title' => 'new1',
192+
'first' => hydrate(FormFirstLevel::class, [
193+
'name' => 'new2',
194+
'age' => null,
195+
'second' => ArrayHash::from([
196+
'city' => '',
197+
]),
198+
]),
199+
]), $form->getValues());
200+
});
201+
202+
203+
test(function () { // getValues(...arguments...)
204+
$_SERVER['REQUEST_METHOD'] = null;
205+
206+
$form = createForm();
207+
208+
$form->setValues([
209+
'title' => 'new1',
210+
'first' => [
211+
'name' => 'new2',
212+
],
213+
]);
214+
215+
Assert::equal(hydrate(FormData::class, [
216+
'title' => 'new1',
217+
'first' => hydrate(FormFirstLevel::class, [
218+
'name' => 'new2',
219+
'age' => null,
220+
'second' => ArrayHash::from([
221+
'city' => '',
222+
]),
223+
]),
224+
]), $form->getValues(FormData::class));
225+
226+
227+
$form->setMappedType(FormData::class);
228+
$form['first']->setMappedType(FormFirstLevel::class);
229+
$form['first-second']->setMappedType(FormSecondLevel::class);
230+
231+
Assert::equal(hydrate(FormData::class, [
232+
'title' => 'new1',
233+
'first' => hydrate(FormFirstLevel::class, [
234+
'name' => 'new2',
235+
'age' => null,
236+
'second' => hydrate(FormSecondLevel::class, [
237+
'city' => '',
238+
]),
239+
]),
240+
]), $form->getValues());
241+
242+
Assert::equal([
243+
'title' => 'new1',
244+
'first' => hydrate(FormFirstLevel::class, [
245+
'name' => 'new2',
246+
'age' => null,
247+
'second' => hydrate(FormSecondLevel::class, [
248+
'city' => '',
249+
]),
250+
]),
251+
], $form->getValues(true));
252+
});
253+
254+
255+
test(function () { // onSuccess test
256+
$_SERVER['REQUEST_METHOD'] = 'POST';
257+
258+
$form = createForm();
259+
$form->setMappedType(FormData::class);
260+
261+
$form->onSuccess[] = function (Form $form, array $values) {
262+
Assert::same([
263+
'title' => 'sent title',
264+
'first' => [
265+
'name' => '',
266+
'age' => 999,
267+
'second' => [
268+
'city' => 'sent city',
269+
],
270+
],
271+
], $values);
272+
};
273+
274+
$form->onSuccess[] = function (Form $form, ArrayHash $values) {
275+
Assert::equal(ArrayHash::from([
276+
'title' => 'sent title',
277+
'first' => ArrayHash::from([
278+
'name' => '',
279+
'age' => 999,
280+
'second' => ArrayHash::from([
281+
'city' => 'sent city',
282+
]),
283+
]),
284+
]), $values);
285+
};
286+
287+
$form->onSuccess[] = function (Form $form, $values) {
288+
Assert::equal(hydrate(FormData::class, [
289+
'title' => 'sent title',
290+
'first' => hydrate(FormFirstLevel::class, [
291+
'name' => '',
292+
'age' => 999,
293+
'second' => ArrayHash::from([
294+
'city' => 'sent city',
295+
]),
296+
]),
297+
]), $values);
298+
};
299+
300+
$form->onSuccess[] = function (Form $form, FormData $values) {
301+
Assert::equal(hydrate(FormData::class, [
302+
'title' => 'sent title',
303+
'first' => hydrate(FormFirstLevel::class, [
304+
'name' => '',
305+
'age' => 999,
306+
'second' => ArrayHash::from([
307+
'city' => 'sent city',
308+
]),
309+
]),
310+
]), $values);
311+
};
312+
313+
$ok = false;
314+
$form->onSuccess[] = function () use (&$ok) {
315+
$ok = true;
316+
};
317+
318+
$form->fireEvents();
319+
Assert::true($ok);
320+
});

0 commit comments

Comments
 (0)