Skip to content

Commit f0ddb4b

Browse files
committed
FormMacros: added {formPrint $form}
1 parent fd5d69d commit f0ddb4b

File tree

4 files changed

+172
-1
lines changed

4 files changed

+172
-1
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"require-dev": {
2424
"nette/di": "^3.0",
2525
"nette/tester": "^2.0",
26-
"latte/latte": "^2.4.1",
26+
"latte/latte": "^2.7",
2727
"tracy/tracy": "^2.4",
2828
"phpstan/phpstan-nette": "^0.12"
2929
},

src/Bridges/FormsLatte/FormMacros.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public static function install(Latte\Compiler $compiler): void
3636
$me->addMacro('input', [$me, 'macroInput']);
3737
$me->addMacro('name', [$me, 'macroName'], [$me, 'macroNameEnd'], [$me, 'macroNameAttr']);
3838
$me->addMacro('inputError', [$me, 'macroInputError']);
39+
$me->addMacro('formPrint', [$me, 'macroFormPrint']);
3940
}
4041

4142

@@ -240,4 +241,22 @@ public function macroInputError(MacroNode $node, PhpWriter $writer)
240241
return $writer->write('echo %escape(end($this->global->formsStack)[%0.word]->getError());', $name);
241242
}
242243
}
244+
245+
246+
/**
247+
* {formPrint [ClassName]}
248+
*/
249+
public function macroFormPrint(MacroNode $node, PhpWriter $writer)
250+
{
251+
$name = $node->tokenizer->fetchWord();
252+
if ($name == null) { // null or false
253+
throw new CompileException('Missing form name in ' . $node->getNotation());
254+
}
255+
$node->tokenizer->reset();
256+
return $writer->write(
257+
'Nette\Bridges\FormsLatte\Runtime::renderBlueprint('
258+
. ($name[0] === '$' ? 'is_object(%node.word) ? %node.word : ' : '')
259+
. '$this->global->uiControl[%node.word]); exit;'
260+
);
261+
}
243262
}

src/Bridges/FormsLatte/Runtime.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
namespace Nette\Bridges\FormsLatte;
1111

12+
use Latte;
1213
use Nette;
1314
use Nette\Forms\Form;
1415
use Nette\Utils\Html;
@@ -71,4 +72,76 @@ public static function renderFormEnd(Form $form, bool $withTags = true): string
7172

7273
return $s . ($withTags ? $form->getElementPrototype()->endTag() . "\n" : '');
7374
}
75+
76+
77+
/**
78+
* Generates blueprint of form.
79+
*/
80+
public static function renderBlueprint($form): void
81+
{
82+
$dummyForm = new Form;
83+
$dict = new \SplObjectStorage;
84+
foreach ($form->getControls() as $name => $input) {
85+
$dict[$input] = $dummyControl = new class extends Nette\Forms\Controls\BaseControl {
86+
public $inner;
87+
88+
89+
public function getLabel($name = null)
90+
{
91+
return $this->inner->getLabel() ? '{label ' . $this->inner->lookupPath(Form::class) . '}' : null;
92+
}
93+
94+
95+
public function getControl()
96+
{
97+
$name = $this->inner->lookupPath(Form::class);
98+
return $this->inner->getOption('type') === 'button'
99+
? "{input $name}"
100+
: "{input $name} {inputError $name}";
101+
}
102+
103+
104+
public function isRequired(): bool
105+
{
106+
return $this->inner->isRequired();
107+
}
108+
109+
110+
public function getOption($key, $default = null)
111+
{
112+
return $key === 'rendered' ? parent::getOption($key) : $this->inner->getOption($key, $default);
113+
}
114+
};
115+
$dummyControl->inner = $input;
116+
$dummyForm->addComponent($dummyControl, (string) $dict->count());
117+
}
118+
119+
foreach ($form->getGroups() as $group) {
120+
$dummyGroup = $dummyForm->addGroup();
121+
foreach ($group->getOptions() as $k => $v) {
122+
$dummyGroup->setOption($k, $v);
123+
}
124+
foreach ($group->getControls() as $control) {
125+
if ($dict[$control]) {
126+
$dummyGroup->add($dict[$control]);
127+
}
128+
}
129+
}
130+
131+
$dummyForm->setRenderer($form->getRenderer());
132+
ob_start();
133+
$dummyForm->render('body');
134+
$body = ob_get_clean();
135+
136+
$blueprint = new Latte\Runtime\Blueprint;
137+
$end = $blueprint->printCanvas();
138+
$blueprint->printHeader('Form ' . $form->getName());
139+
$blueprint->printCode(
140+
'<form n:name="' . $form->getName() . "\">\n"
141+
. '<ul><li n:foreach="$form->getOwnErrors() as $error">{$error}</li></ul>'
142+
. $body
143+
. '</form>'
144+
);
145+
echo $end;
146+
}
74147
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Nette\Forms\Form;
6+
use Nette\Utils\Html;
7+
use Tester\Assert;
8+
9+
10+
require __DIR__ . '/../bootstrap.php';
11+
12+
13+
$form = new Form('signForm');
14+
$form->addGroup('Personal data');
15+
$form->addText('name')->setRequired('Enter your name');
16+
$form->addContainer('cont')
17+
->addText('name');
18+
$form->addHidden('id');
19+
$form->addCheckbox('agree');
20+
$form->addGroup();
21+
$form->addSubmit('submit', 'Send');
22+
23+
$renderer = $form->getRenderer();
24+
$renderer->wrappers['form']['container'] = Html::el('div')->id('form');
25+
$renderer->wrappers['group']['container'] = null;
26+
$renderer->wrappers['group']['label'] = 'h3';
27+
$renderer->wrappers['pair']['container'] = null;
28+
$renderer->wrappers['controls']['container'] = 'dl';
29+
$renderer->wrappers['control']['container'] = 'dd';
30+
$renderer->wrappers['control']['.odd'] = 'odd';
31+
$renderer->wrappers['label']['container'] = 'dt';
32+
$renderer->wrappers['label']['suffix'] = ':';
33+
34+
35+
ob_start();
36+
Nette\Bridges\FormsLatte\Runtime::renderBlueprint($form);
37+
$res = ob_get_clean();
38+
39+
Assert::match(
40+
'%A%<form n:name="signForm">
41+
<ul><li n:foreach="$form->getOwnErrors() as $error">{$error}</li></ul>
42+
<div id="form">
43+
44+
<h3>Personal data</h3>
45+
46+
<dl>
47+
48+
<dt>{label name}:</dt>
49+
50+
<dd>{input name} {inputError name}</dd>
51+
52+
53+
54+
<dt>{label cont-name}:</dt>
55+
56+
<dd class="odd">{input cont-name} {inputError cont-name}</dd>
57+
58+
59+
60+
<dt></dt>
61+
62+
<dd>{input agree} {inputError agree}</dd>
63+
64+
</dl>
65+
66+
67+
68+
<dl>
69+
70+
<dt></dt>
71+
72+
<dd>{input submit}</dd>
73+
74+
</dl>
75+
76+
</div>
77+
</form>%A%',
78+
$res
79+
);

0 commit comments

Comments
 (0)