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->modifiers) {
52: trigger_error("Modifiers are not allowed in {{$node->name}}", E_USER_WARNING);
53: }
54: if ($node->prefix) {
55: throw new CompileException('Did you mean <form n:name=...> ?');
56: }
57: $name = $node->tokenizer->fetchWord();
58: if ($name === FALSE) {
59: throw new CompileException("Missing form name in {{$node->name}}.");
60: }
61: $node->tokenizer->reset();
62: return $writer->write(
63: 'echo Nette\Bridges\FormsLatte\Runtime::renderFormBegin($form = $_form = '
64: . ($name[0] === '$' ? 'is_object(%node.word) ? %node.word : ' : '')
65: . '$_control[%node.word], %node.array)'
66: );
67: }
68:
69:
70: 71: 72:
73: public function macroFormContainer(MacroNode $node, PhpWriter $writer)
74: {
75: if ($node->modifiers) {
76: trigger_error("Modifiers are not allowed in {{$node->name}}", E_USER_WARNING);
77: }
78: $name = $node->tokenizer->fetchWord();
79: if ($name === FALSE) {
80: throw new CompileException("Missing name in {{$node->name}}.");
81: }
82: $node->tokenizer->reset();
83: return $writer->write(
84: '$_formStack[] = $_form; $formContainer = $_form = ' . ($name[0] === '$' ? 'is_object(%node.word) ? %node.word : ' : '') . '$_form[%node.word]'
85: );
86: }
87:
88:
89: 90: 91:
92: public function macroLabel(MacroNode $node, PhpWriter $writer)
93: {
94: if ($node->modifiers) {
95: trigger_error("Modifiers are not allowed in {{$node->name}}", E_USER_WARNING);
96: }
97: $words = $node->tokenizer->fetchWords();
98: if (!$words) {
99: throw new CompileException("Missing name in {{$node->name}}.");
100: }
101: $name = array_shift($words);
102: return $writer->write(
103: ($name[0] === '$' ? '$_input = is_object(%0.word) ? %0.word : $_form[%0.word]; if ($_label = $_input' : 'if ($_label = $_form[%0.word]')
104: . '->%1.raw) echo $_label'
105: . ($node->tokenizer->isNext() ? '->addAttributes(%node.array)' : ''),
106: $name,
107: $words ? ('getLabelPart(' . implode(', ', array_map(array($writer, 'formatWord'), $words)) . ')') : 'getLabel()'
108: );
109: }
110:
111:
112: 113: 114:
115: public function macroLabelEnd(MacroNode $node, PhpWriter $writer)
116: {
117: if ($node->content != NULL) {
118: $node->openingCode = rtrim($node->openingCode, '?> ') . '->startTag() ?>';
119: return $writer->write('if ($_label) echo $_label->endTag()');
120: }
121: }
122:
123:
124: 125: 126:
127: public function macroInput(MacroNode $node, PhpWriter $writer)
128: {
129: if ($node->modifiers) {
130: trigger_error("Modifiers are not allowed in {{$node->name}}", E_USER_WARNING);
131: }
132: $words = $node->tokenizer->fetchWords();
133: if (!$words) {
134: throw new CompileException("Missing name in {{$node->name}}.");
135: }
136: $name = array_shift($words);
137: return $writer->write(
138: ($name[0] === '$' ? '$_input = is_object(%0.word) ? %0.word : $_form[%0.word]; echo $_input' : 'echo $_form[%0.word]')
139: . '->%1.raw'
140: . ($node->tokenizer->isNext() ? '->addAttributes(%node.array)' : ''),
141: $name,
142: $words ? 'getControlPart(' . implode(', ', array_map(array($writer, 'formatWord'), $words)) . ')' : 'getControl()'
143: );
144: }
145:
146:
147: 148: 149:
150: public function macroInputAttr(MacroNode $node, PhpWriter $writer)
151: {
152: throw new CompileException('Use n:name instead of n:input.');
153: }
154:
155:
156: 157: 158:
159: public function macroNameAttr(MacroNode $node, PhpWriter $writer)
160: {
161: $words = $node->tokenizer->fetchWords();
162: if (!$words) {
163: throw new CompileException("Missing name in n:{$node->name}.");
164: }
165: $name = array_shift($words);
166: $tagName = strtolower($node->htmlNode->name);
167: $node->isEmpty = $tagName === 'input';
168:
169: if ($tagName === 'form') {
170: return $writer->write(
171: 'echo Nette\Bridges\FormsLatte\Runtime::renderFormBegin($form = $_form = '
172: . ($name[0] === '$' ? 'is_object(%0.word) ? %0.word : ' : '')
173: . '$_control[%0.word], %1.var, FALSE)',
174: $name,
175: array_fill_keys(array_keys($node->htmlNode->attrs), NULL)
176: );
177: } else {
178: $method = $tagName === 'label' ? 'getLabel' : 'getControl';
179: return $writer->write(
180: '$_input = ' . ($name[0] === '$' ? 'is_object(%0.word) ? %0.word : ' : '')
181: . '$_form[%0.word]; echo $_input->%1.raw'
182: . ($node->htmlNode->attrs ? '->addAttributes(%2.var)' : '') . '->attributes()',
183: $name,
184: $words
185: ? $method . 'Part(' . implode(', ', array_map(array($writer, 'formatWord'), $words)) . ')'
186: : "{method_exists(\$_input, '{$method}Part')?'{$method}Part':'{$method}'}()",
187: array_fill_keys(array_keys($node->htmlNode->attrs), NULL)
188: );
189: }
190: }
191:
192:
193: public function macroName(MacroNode $node, PhpWriter $writer)
194: {
195: if (!$node->prefix) {
196: throw new CompileException("Unknown macro {{$node->name}}, use n:{$node->name} attribute.");
197: } elseif ($node->prefix !== MacroNode::PREFIX_NONE) {
198: throw new CompileException("Unknown attribute n:{$node->prefix}-{$node->name}, use n:{$node->name} attribute.");
199: }
200: }
201:
202:
203: public function macroNameEnd(MacroNode $node, PhpWriter $writer)
204: {
205: preg_match('#^(.*? n:\w+>)(.*)(<[^?].*)\z#s', $node->content, $parts);
206: $tagName = strtolower($node->htmlNode->name);
207: if ($tagName === 'form') {
208: $node->content = $parts[1] . $parts[2] . '<?php echo Nette\Bridges\FormsLatte\Runtime::renderFormEnd($_form, FALSE) ?>' . $parts[3];
209: } elseif ($tagName === 'label') {
210: if ($node->htmlNode->isEmpty) {
211: $node->content = $parts[1] . "<?php echo \$_input->{method_exists(\$_input, 'getLabelPart')?'getLabelPart':'getLabel'}()->getHtml() ?>" . $parts[3];
212: }
213: } elseif ($tagName === 'button') {
214: if ($node->htmlNode->isEmpty) {
215: $node->content = $parts[1] . '<?php echo htmlspecialchars($_input->caption) ?>' . $parts[3];
216: }
217: } else {
218: $node->content = $parts[1] . '<?php echo $_input->getControl()->getHtml() ?>' . $parts[3];
219: }
220: }
221:
222:
223: 224: 225:
226: public function macroInputError(MacroNode $node, PhpWriter $writer)
227: {
228: if ($node->modifiers) {
229: trigger_error("Modifiers are not allowed in {{$node->name}}", E_USER_WARNING);
230: }
231: $name = $node->tokenizer->fetchWord();
232: if (!$name) {
233: return $writer->write('echo %escape($_input->getError())');
234: } elseif ($name[0] === '$') {
235: return $writer->write('$_input = is_object(%0.word) ? %0.word : $_form[%0.word]; echo %escape($_input->getError())', $name);
236: } else {
237: return $writer->write('echo %escape($_form[%0.word]->getError())', $name);
238: }
239: }
240:
241:
242:
243: public static function renderFormBegin(Form $form, array $attrs, $withTags = TRUE)
244: {
245: echo Runtime::renderFormBegin($form, $attrs, $withTags);
246: }
247:
248:
249:
250: public static function renderFormEnd(Form $form, $withTags = TRUE)
251: {
252: echo Runtime::renderFormEnd($form, $withTags);
253: }
254:
255: }
256: