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