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