1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Bridges\FormsLatte;
9:
10: use Nette;
11: use Latte;
12: use Latte\MacroNode;
13: use Latte\PhpWriter;
14: use Latte\CompileException;
15: use Latte\Macros\MacroSet;
16: use Nette\Forms\Form;
17:
18:
19: 20: 21: 22: 23: 24: 25: 26: 27:
28: class FormMacros extends MacroSet
29: {
30:
31: public static function install(Latte\Compiler $compiler)
32: {
33: $me = new static($compiler);
34: $me->addMacro('form', array($me, 'macroForm'), 'echo Nette\Bridges\FormsLatte\Runtime::renderFormEnd($_form)');
35: $me->addMacro('formContainer', array($me, 'macroFormContainer'), '$formContainer = $_form = array_pop($_formStack)');
36: $me->addMacro('label', array($me, 'macroLabel'), array($me, 'macroLabelEnd'));
37: $me->addMacro('input', array($me, 'macroInput'), NULL, array($me, 'macroInputAttr'));
38: $me->addMacro('name', array($me, 'macroName'), array($me, 'macroNameEnd'), array($me, 'macroNameAttr'));
39: $me->addMacro('inputError', array($me, 'macroInputError'));
40: }
41:
42:
43:
44:
45:
46: 47: 48:
49: public function macroForm(MacroNode $node, PhpWriter $writer)
50: {
51: if ($node->prefix) {
52: throw new CompileException('Did you mean <form n:name=...> ?');
53: }
54: $name = $node->tokenizer->fetchWord();
55: if ($name === FALSE) {
56: throw new CompileException("Missing form name in {{$node->name}}.");
57: }
58: $node->tokenizer->reset();
59: return $writer->write(
60: 'echo Nette\Bridges\FormsLatte\Runtime::renderFormBegin($form = $_form = '
61: . ($name[0] === '$' ? 'is_object(%node.word) ? %node.word : ' : '')
62: . '$_control[%node.word], %node.array)'
63: );
64: }
65:
66:
67: 68: 69:
70: public function macroFormContainer(MacroNode $node, PhpWriter $writer)
71: {
72: $name = $node->tokenizer->fetchWord();
73: if ($name === FALSE) {
74: throw new CompileException("Missing name in {{$node->name}}.");
75: }
76: $node->tokenizer->reset();
77: return $writer->write(
78: '$_formStack[] = $_form; $formContainer = $_form = ' . ($name[0] === '$' ? 'is_object(%node.word) ? %node.word : ' : '') . '$_form[%node.word]'
79: );
80: }
81:
82:
83: 84: 85:
86: public function macroLabel(MacroNode $node, PhpWriter $writer)
87: {
88: $words = $node->tokenizer->fetchWords();
89: if (!$words) {
90: throw new CompileException("Missing name in {{$node->name}}.");
91: }
92: $name = array_shift($words);
93: return $writer->write(
94: ($name[0] === '$' ? '$_input = is_object(%0.word) ? %0.word : $_form[%0.word]; if ($_label = $_input' : 'if ($_label = $_form[%0.word]')
95: . '->%1.raw) echo $_label'
96: . ($node->tokenizer->isNext() ? '->addAttributes(%node.array)' : ''),
97: $name,
98: $words ? ('getLabelPart(' . implode(', ', array_map(array($writer, 'formatWord'), $words)) . ')') : 'getLabel()'
99: );
100: }
101:
102:
103: 104: 105:
106: public function macroLabelEnd(MacroNode $node, PhpWriter $writer)
107: {
108: if ($node->content != NULL) {
109: $node->openingCode = rtrim($node->openingCode, '?> ') . '->startTag() ?>';
110: return $writer->write('if ($_label) echo $_label->endTag()');
111: }
112: }
113:
114:
115: 116: 117:
118: public function macroInput(MacroNode $node, PhpWriter $writer)
119: {
120: $words = $node->tokenizer->fetchWords();
121: if (!$words) {
122: throw new CompileException("Missing name in {{$node->name}}.");
123: }
124: $name = array_shift($words);
125: return $writer->write(
126: ($name[0] === '$' ? '$_input = is_object(%0.word) ? %0.word : $_form[%0.word]; echo $_input' : 'echo $_form[%0.word]')
127: . '->%1.raw'
128: . ($node->tokenizer->isNext() ? '->addAttributes(%node.array)' : ''),
129: $name,
130: $words ? 'getControlPart(' . implode(', ', array_map(array($writer, 'formatWord'), $words)) . ')' : 'getControl()'
131: );
132: }
133:
134:
135: 136: 137:
138: public function macroInputAttr(MacroNode $node, PhpWriter $writer)
139: {
140: throw new CompileException('Use n:name instead of n:input.');
141: }
142:
143:
144: 145: 146:
147: public function macroNameAttr(MacroNode $node, PhpWriter $writer)
148: {
149: $words = $node->tokenizer->fetchWords();
150: if (!$words) {
151: throw new CompileException("Missing name in n:{$node->name}.");
152: }
153: $name = array_shift($words);
154: $tagName = strtolower($node->htmlNode->name);
155: $node->isEmpty = $tagName === 'input';
156:
157: if ($tagName === 'form') {
158: return $writer->write(
159: 'echo Nette\Bridges\FormsLatte\Runtime::renderFormBegin($form = $_form = '
160: . ($name[0] === '$' ? 'is_object(%0.word) ? %0.word : ' : '')
161: . '$_control[%0.word], %1.var, FALSE)',
162: $name,
163: array_fill_keys(array_keys($node->htmlNode->attrs), NULL)
164: );
165: } else {
166: $method = $tagName === 'label' ? 'getLabel' : 'getControl';
167: return $writer->write(
168: '$_input = ' . ($name[0] === '$' ? 'is_object(%0.word) ? %0.word : ' : '')
169: . '$_form[%0.word]; echo $_input->%1.raw'
170: . ($node->htmlNode->attrs ? '->addAttributes(%2.var)' : '') . '->attributes()',
171: $name,
172: $words
173: ? $method . 'Part(' . implode(', ', array_map(array($writer, 'formatWord'), $words)) . ')'
174: : "{method_exists(\$_input, '{$method}Part')?'{$method}Part':'{$method}'}()",
175: array_fill_keys(array_keys($node->htmlNode->attrs), NULL)
176: );
177: }
178: }
179:
180:
181: public function macroName(MacroNode $node, PhpWriter $writer)
182: {
183: if (!$node->prefix) {
184: throw new CompileException("Unknown macro {{$node->name}}, use n:{$node->name} attribute.");
185: } elseif ($node->prefix !== MacroNode::PREFIX_NONE) {
186: throw new CompileException("Unknown attribute n:{$node->prefix}-{$node->name}, use n:{$node->name} attribute.");
187: }
188: }
189:
190:
191: public function macroNameEnd(MacroNode $node, PhpWriter $writer)
192: {
193: preg_match('#^(.*? n:\w+>)(.*)(<[^?].*)\z#s', $node->content, $parts);
194: $tagName = strtolower($node->htmlNode->name);
195: if ($tagName === 'form') {
196: $node->content = $parts[1] . $parts[2] . '<?php echo Nette\Bridges\FormsLatte\Runtime::renderFormEnd($_form, FALSE) ?>' . $parts[3];
197: } elseif ($tagName === 'label') {
198: if ($node->htmlNode->isEmpty) {
199: $node->content = $parts[1] . "<?php echo \$_input->{method_exists(\$_input, 'getLabelPart')?'getLabelPart':'getLabel'}()->getHtml() ?>" . $parts[3];
200: }
201: } elseif ($tagName === 'button') {
202: if ($node->htmlNode->isEmpty) {
203: $node->content = $parts[1] . '<?php echo htmlspecialchars($_input->caption) ?>' . $parts[3];
204: }
205: } else {
206: $node->content = $parts[1] . '<?php echo $_input->getControl()->getHtml() ?>' . $parts[3];
207: }
208: }
209:
210:
211: 212: 213:
214: public function macroInputError(MacroNode $node, PhpWriter $writer)
215: {
216: $name = $node->tokenizer->fetchWord();
217: if (!$name) {
218: return $writer->write('echo %escape($_input->getError())');
219: } elseif ($name[0] === '$') {
220: return $writer->write('$_input = is_object(%0.word) ? %0.word : $_form[%0.word]; echo %escape($_input->getError())', $name);
221: } else {
222: return $writer->write('echo %escape($_form[%0.word]->getError())', $name);
223: }
224: }
225:
226:
227:
228: public static function renderFormBegin(Form $form, array $attrs, $withTags = TRUE)
229: {
230: echo Runtime::renderFormBegin($form, $attrs, $withTags);
231: }
232:
233:
234:
235: public static function renderFormEnd(Form $form, $withTags = TRUE)
236: {
237: echo Runtime::renderFormEnd($form, $withTags);
238: }
239:
240: }
241: