Skip to content

Commit 63594dd

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

File tree

4 files changed

+163
-1
lines changed

4 files changed

+163
-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: 65 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,68 @@ 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(null) . '}' : null;
92+
}
93+
94+
95+
public function getControl()
96+
{
97+
return '{input ' . $this->inner->lookupPath(null) . '}';
98+
}
99+
100+
101+
public function isRequired(): bool
102+
{
103+
return $this->inner->isRequired();
104+
}
105+
106+
107+
public function getOption($key, $default = null)
108+
{
109+
return $key === 'rendered' ? parent::getOption($key) : $this->inner->getOption($key, $default);
110+
}
111+
};
112+
$dummyControl->inner = $input;
113+
$dummyForm->addComponent($dummyControl, (string) $dict->count());
114+
}
115+
116+
foreach ($form->getGroups() as $group) {
117+
$dummyGroup = $dummyForm->addGroup();
118+
foreach ($group->getOptions() as $k => $v) {
119+
$dummyGroup->setOption($k, $v);
120+
}
121+
foreach ($group->getControls() as $control) {
122+
if ($dict[$control]) {
123+
$dummyGroup->add($dict[$control]);
124+
}
125+
}
126+
}
127+
128+
$dummyForm->setRenderer($form->getRenderer());
129+
ob_start();
130+
$dummyForm->render('body');
131+
$body = ob_get_clean();
132+
133+
$blueprint = new Latte\Runtime\Blueprint;
134+
$end = $blueprint->printCanvas();
135+
$blueprint->printHeader('Form ' . $form->getName());
136+
$blueprint->printCode('<form n:name="' . $form->getName() . '">' . $body . '</form>');
137+
echo $end;
138+
}
74139
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
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+
<div id="form">
42+
43+
<h3>Personal data</h3>
44+
45+
<dl>
46+
47+
<dt>{label name}:</dt>
48+
49+
<dd>{input name}</dd>
50+
51+
52+
53+
<dt>{label cont-name}:</dt>
54+
55+
<dd class="odd">{input cont-name}</dd>
56+
57+
58+
59+
<dt></dt>
60+
61+
<dd>{input agree}</dd>
62+
63+
</dl>
64+
65+
66+
67+
<dl>
68+
69+
<dt></dt>
70+
71+
<dd>{input submit}</dd>
72+
73+
</dl>
74+
75+
</div>
76+
</form>%A%',
77+
$res
78+
);

0 commit comments

Comments
 (0)