Skip to content

Commit 39725d3

Browse files
authored
Fixes for nested multipliers (#59)
1 parent a2ccdcf commit 39725d3

File tree

7 files changed

+86
-38
lines changed

7 files changed

+86
-38
lines changed

src/ComponentResolver.php

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,17 @@ final class ComponentResolver
2121
/** @var mixed[] */
2222
private ?array $purgedHttpData = null;
2323

24-
/** @var mixed[] */
25-
private array $defaults = [];
26-
2724
private int $minCopies;
2825

2926
private bool $reached = false;
3027

3128
/**
3229
* @param mixed[] $httpData
33-
* @param mixed[] $defaults
3430
*/
35-
public function __construct(array $httpData, array $defaults, ?int $maxCopies, int $minCopies)
31+
public function __construct(array $httpData, ?int $maxCopies, int $minCopies)
3632
{
3733
$this->httpData = $httpData;
3834
$this->maxCopies = $maxCopies;
39-
$this->defaults = $defaults;
4035
$this->minCopies = $minCopies;
4136

4237
foreach ($httpData as $index => $_) {
@@ -71,7 +66,7 @@ public function getCreateNum(): int
7166
*/
7267
public function getDefaults(): array
7368
{
74-
return array_slice($this->defaults, 0, $this->maxCopies, true);
69+
return array_slice([], 0, $this->maxCopies, true);
7570
}
7671

7772
/**

src/Latte/Extension/MultiplierExtension.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ public function getTags(): array
2020
'n:multiplier' => [MultiplierNode::class, 'create'],
2121
'multiplier:remove' => [MultiplierRemoveNode::class, 'create'],
2222
'multiplier:add' => [MultiplierAddNode::class, 'create'],
23+
'btnRemove' => [MultiplierRemoveNode::class, 'create'],
24+
'btnCreate' => [MultiplierAddNode::class, 'create'],
2325
];
2426
}
2527

src/Multiplier.php

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,6 @@ class Multiplier extends Container
5151

5252
protected ?RemoveButton $removeButton = null;
5353

54-
/** @var mixed[] */
55-
protected array $httpData = [];
56-
5754
protected ?int $maxCopies = null;
5855

5956
protected int $totalCopies = 0;
@@ -69,6 +66,9 @@ class Multiplier extends Container
6966

7067
private bool $attachedCalled = false;
7168

69+
/** @var ComponentResolver */
70+
protected ComponentResolver $resolver;
71+
7272
public function __construct(callable $factory, int $copyNumber = 1, ?int $maxCopies = null)
7373
{
7474
$this->factory = $factory;
@@ -211,28 +211,32 @@ public function addCopy(?int $number = null, array|object $defaults = []): Conta
211211
return $container;
212212
}
213213

214-
public function createCopies(): void
214+
public function createCopies(bool $forceValues = false): void
215215
{
216216
if ($this->created === true) {
217217
return;
218218
}
219-
220219
$this->created = true;
221220

222-
$resolver = new ComponentResolver($this->httpData, $this->values, $this->maxCopies, $this->minCopies);
221+
if (!isset($this->resolver)) {
222+
$this->resolver = new ComponentResolver($this->values, $this->maxCopies, $this->minCopies);
223+
}
223224

224225
$this->attachCreateButtons();
225-
$this->createComponents($resolver);
226+
$this->createComponents($forceValues);
226227
$this->detachCreateButtons();
227228

228229
if ($this->maxCopies === null || $this->totalCopies < $this->maxCopies) {
229230
$this->attachCreateButtons();
230231
}
231232

232-
if ($this->form !== null && $resolver->isRemoveAction() && $this->totalCopies >= $this->minCopies && !$resolver->reachedMinLimit()) {
233-
/** @var RemoveButton $removeButton */
234-
$removeButton = $this->removeButton;
235-
$this->form->setSubmittedBy($removeButton->create($this));
233+
if (
234+
$this->form !== null &&
235+
$this->resolver->isRemoveAction() &&
236+
$this->totalCopies >= $this->minCopies &&
237+
!$this->resolver->reachedMinLimit()
238+
) {
239+
$this->form->setSubmittedBy($this->removeButton->create($this));
236240

237241
$this->resetFormEvents();
238242

@@ -329,10 +333,12 @@ public function setValues($values, bool $erase = false): self
329333
if ($this->created) {
330334
foreach ($this->getContainers() as $container) {
331335
$this->removeComponent($container);
336+
$this->totalCopies--;
332337
}
333338

334339
$this->created = false;
335340
$this->detachCreateButtons();
341+
$this->resolver = new ComponentResolver($this->values, $this->maxCopies, $this->minCopies);
336342
$this->createCopies();
337343
}
338344

@@ -379,8 +385,9 @@ protected function isFormSubmitted(): bool
379385

380386
protected function loadHttpData(): void
381387
{
382-
if ($this->form !== null && $this->isFormSubmitted()) {
383-
$this->httpData = (array) Arrays::get($this->form->getHttpData(), $this->getHtmlName(), []);
388+
if ($this->isFormSubmitted()) {
389+
$httpData = Arrays::get($this->form->getHttpData(), $this->getHtmlName(), []);
390+
$this->resolver = new ComponentResolver($httpData ?? [], $this->maxCopies, $this->minCopies);
384391
}
385392
}
386393

@@ -443,31 +450,34 @@ protected function removeComponentProperly(IComponent $component): void
443450
$this->removeComponent($component);
444451
}
445452

446-
private function createComponents(ComponentResolver $resolver): void
453+
private function createComponents(bool $forceValues = false): void
447454
{
448455
$containers = [];
456+
$containerDefaults = $this->createContainer()->getValues('array');
449457

450458
// Components from httpData
451-
if ($this->isFormSubmitted()) {
452-
foreach ($resolver->getValues() as $number => $_) {
459+
if ($this->isFormSubmitted() && !$forceValues) {
460+
foreach ($this->resolver->getValues() as $number => $_) {
453461
$containers[] = $container = $this->addCopy($number);
454462

455463
/** @var BaseControl $control */
456-
foreach ($container->getControls() as $control) {
464+
foreach ($container->getComponents(false, Control::class) as $control) {
457465
$control->loadHttpData();
458466
}
459467
}
460468
} else { // Components from default values
461-
foreach ($resolver->getDefaults() as $number => $values) {
462-
$containers[] = $this->addCopy($number, $values);
469+
foreach ($this->resolver->getValues() as $number => $values) {
470+
$containers[] = $container = $this->addCopy($number, $values);
471+
$container->setValues($values);
463472
}
464473
}
465474

466475
// Default number of copies
467-
if (!$this->isFormSubmitted() && !$this->values) {
476+
if (!$this->values) {
468477
$copyNumber = $this->copyNumber;
469-
while ($copyNumber > 0 && $this->isValidMaxCopies()) {
478+
while ($copyNumber > 0 && $this->isValidMaxCopies() && $this->totalCopies < $this->minCopies) {
470479
$containers[] = $container = $this->addCopy();
480+
$container->setValues($containerDefaults);
471481
$copyNumber--;
472482
}
473483
}
@@ -478,11 +488,11 @@ private function createComponents(ComponentResolver $resolver): void
478488
}
479489

480490
// New containers, if create button hitted
481-
if ($this->form !== null && $resolver->isCreateAction() && $this->form->isValid()) {
482-
$count = $resolver->getCreateNum();
491+
if ($this->form !== null && $this->resolver->isCreateAction() && $this->form->isValid()) {
492+
$count = $this->resolver->getCreateNum();
483493
while ($count > 0 && $this->isValidMaxCopies()) {
484494
$this->noValidate[] = $containers[] = $container = $this->addCopy();
485-
$container->setValues($this->createContainer()->getValues('array'));
495+
$container->setValues($containerDefaults);
486496
$count--;
487497
}
488498
}

tests/unit/CreateButtonTest.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,11 @@ public function testCallback()
8989
$submitter->setHtmlAttribute('class', 'add-btn');
9090
});
9191

92-
$response = $this->services->form->createRequest($factory->createForm())->setPost([
92+
$response = $this->services->form->createRequest($factory
93+
->formModifier(function (\Nette\Application\UI\Form $form) {
94+
$form->onSuccess[] = $form->onError[] = $form->onSubmit[] = function () {
95+
};
96+
})->createForm())->setPost([
9397
'm' => [
9498
['bar' => ''],
9599
['bar' => ''],

tests/unit/LatteTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ public function testBtnCreate()
3636
$presenter['m'] = $form;
3737

3838
$string = $this->latte->renderToString(__DIR__ . '/templates/macros.latte', ['form' => $form]);
39-
$this->assertRegExp('#name="m\[multiplier_creator]"#', $string);
40-
$this->assertRegExp('#name="m\[multiplier_creator2]"#', $string);
39+
$this->assertMatchesRegularExpression('#name="m\[multiplier_creator]"#', $string);
40+
$this->assertMatchesRegularExpression('#name="m\[multiplier_creator2]"#', $string);
4141
}
4242

4343
}

tests/unit/MultiplierTest.php

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ public function testSendBase()
4444
$this->parameters['onCreate'][] = $container;
4545
};
4646
})
47+
->formModifier(function (Form $form) {
48+
$form->onSuccess[] = $form->onError[] = $form->onSubmit[] = function () {
49+
};
50+
})
4751
->createForm()
4852
)
4953
->setPost($params = [
@@ -93,6 +97,10 @@ public function testSendCopy2()
9397
$this->parameters['onCreate'][] = $container;
9498
};
9599
})
100+
->formModifier(function (Form $form) {
101+
$form->onSuccess[] = $form->onError[] = $form->onSubmit[] = function () {
102+
};
103+
})
96104
->createForm()
97105
)
98106
->setPost($params = [
@@ -143,6 +151,10 @@ public function testSendMaxCopy()
143151
$this->parameters['onCreate'][] = $container;
144152
};
145153
})
154+
->formModifier(function (Form $form) {
155+
$form->onSuccess[] = $form->onError[] = $form->onSubmit[] = function () {
156+
};
157+
})
146158
->createForm()
147159
)
148160
->setPost([
@@ -209,6 +221,10 @@ public function testSendNested()
209221
}));
210222
$container['m2']->addCreateButton('create');
211223
})
224+
->formModifier(function (Form $form) {
225+
$form->onSuccess[] = $form->onError[] = $form->onSubmit[] = function () {
226+
};
227+
})
212228
->createForm()
213229
);
214230
$request->setPost([
@@ -239,11 +255,15 @@ public function testSendNested()
239255
],
240256
[
241257
'bar' => 'bar',
242-
'm2' => [],
258+
'm2' => [
259+
['bar2' => ''],
260+
],
243261
],
244262
[
245263
'bar' => '',
246-
'm2' => [],
264+
'm2' => [
265+
['bar2' => ''],
266+
],
247267
],
248268
],
249269
], $send->getValues());
@@ -299,14 +319,15 @@ public function testGroupManualRenderWithButtons()
299319
->multiplierModifier(function (Multiplier $multiplier) {
300320
$multiplier->onCreate[] = function (Container $container) {
301321
$this->parameters['onCreate'][] = $container;
322+
$container->setParent(null, 'X');
323+
//var_dump($container);
302324
};
303325
$multiplier->addCreateButton();
304326
$multiplier->addRemoveButton();
305-
$multiplier->setMinCopies(1);
327+
//$multiplier->setMinCopies(1);
306328
})
307329
->createForm());
308330
$dom = $request->render(__DIR__ . '/templates/group.latte')->toDomQuery();
309-
310331
$this->assertDomHas($dom, 'input[name="m[0][multiplier_remover]"]');
311332
$this->assertDomHas($dom, 'input[name="m[1][multiplier_remover]"]');
312333
}
@@ -375,6 +396,10 @@ public function testPromptSelect()
375396
->setPrompt('Select');
376397
})
377398
->addCreateButton()
399+
->formModifier(function (Form $form) {
400+
$form->onSuccess[] = $form->onError[] = $form->onSubmit[] = function () {
401+
};
402+
})
378403
->createForm()
379404
)
380405
->setPost($params = [

tests/unit/RemoveButtonTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,10 @@ public function testAddClass()
188188
$submitter->setHtmlAttribute('class', 'btn btn-remove');
189189
})
190190
->addCreateButton()
191+
->formModifier(function (Form $form) {
192+
$form->onSuccess[] = $form->onError[] = $form->onSubmit[] = function () {
193+
};
194+
})
191195
->createForm()
192196
)->setPost([
193197
'm' => [
@@ -210,6 +214,10 @@ public function testDeleteLastElementToZero()
210214
->setMinCopies(0)
211215
->addRemoveButton()
212216
->addCreateButton()
217+
->formModifier(function (Form $form) {
218+
$form->onSuccess[] = $form->onError[] = $form->onSubmit[] = function () {
219+
};
220+
})
213221
->createForm()
214222
)->modifyForm(function (Form $form) {
215223
$form['m']->setValues([
@@ -239,6 +247,10 @@ public function testOnRemoveEvent()
239247
$called = true;
240248
};
241249
})
250+
->formModifier(function (Form $form) {
251+
$form->onSuccess[] = $form->onError[] = $form->onSubmit[] = function () {
252+
};
253+
})
242254
->createForm()
243255
)->setPost([
244256
'm' => [

0 commit comments

Comments
 (0)