Namespaces

  • Nette
    • Application
      • Diagnostics
      • Responses
      • Routers
      • UI
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Diagnostics
      • Drivers
      • Reflection
      • Table
    • DI
      • Config
        • Adapters
      • Diagnostics
      • Extensions
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
      • Diagnostics
    • Iterators
    • Latte
      • Macros
    • Loaders
    • Localization
    • Mail
    • PhpGenerator
    • Reflection
    • Security
      • Diagnostics
    • Templating
    • Utils
  • NetteModule
  • none

Classes

  • CacheMacro
  • CoreMacros
  • FormMacros
  • MacroSet
  • UIMacros
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Other releases
  • Nette homepage
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://nette.org)
  5:  * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
  6:  */
  7: 
  8: namespace Nette\Latte\Macros;
  9: 
 10: use Nette;
 11: use Nette\Latte;
 12: use Nette\Latte\MacroNode;
 13: use Nette\Latte\PhpWriter;
 14: use Nette\Latte\CompileException;
 15: use Nette\Forms\Form;
 16: 
 17: 
 18: /**
 19:  * Macros for Nette\Forms.
 20:  *
 21:  * - {form name} ... {/form}
 22:  * - {input name}
 23:  * - {label name /} or {label name}... {/label}
 24:  * - {inputError name}
 25:  * - {formContainer name} ... {/formContainer}
 26:  *
 27:  * @author     David Grudl
 28:  */
 29: class FormMacros extends MacroSet
 30: {
 31: 
 32:     public static function install(Latte\Compiler $compiler)
 33:     {
 34:         $me = new static($compiler);
 35:         $me->addMacro('form', array($me, 'macroForm'), 'Nette\Latte\Macros\FormMacros::renderFormEnd($_form)');
 36:         $me->addMacro('formContainer', array($me, 'macroFormContainer'), '$formContainer = $_form = array_pop($_formStack)');
 37:         $me->addMacro('label', array($me, 'macroLabel'), array($me, 'macroLabelEnd'));
 38:         $me->addMacro('input', array($me, 'macroInput'), NULL, array($me, 'macroInputAttr'));
 39:         $me->addMacro('name', array($me, 'macroName'), array($me, 'macroNameEnd'), array($me, 'macroNameAttr'));
 40:         $me->addMacro('inputError', array($me, 'macroInputError'));
 41:     }
 42: 
 43: 
 44:     /********************* macros ****************d*g**/
 45: 
 46: 
 47:     /**
 48:      * {form ...}
 49:      */
 50:     public function macroForm(MacroNode $node, PhpWriter $writer)
 51:     {
 52:         if ($node->htmlNode && strtolower($node->htmlNode->name) === 'form') {
 53:             throw new CompileException('Did you mean <form n:name=...> ?');
 54:         }
 55:         $name = $node->tokenizer->fetchWord();
 56:         if ($name === FALSE) {
 57:             throw new CompileException("Missing form name in {{$node->name}}.");
 58:         }
 59:         $node->tokenizer->reset();
 60:         return $writer->write(
 61:             'Nette\Latte\Macros\FormMacros::renderFormBegin($form = $_form = '
 62:             . ($name[0] === '$' ? 'is_object(%node.word) ? %node.word : ' : '')
 63:             . '$_control[%node.word], %node.array)'
 64:         );
 65:     }
 66: 
 67: 
 68:     /**
 69:      * {formContainer ...}
 70:      */
 71:     public function macroFormContainer(MacroNode $node, PhpWriter $writer)
 72:     {
 73:         $name = $node->tokenizer->fetchWord();
 74:         if ($name === FALSE) {
 75:             throw new CompileException("Missing form name in {{$node->name}}.");
 76:         }
 77:         $node->tokenizer->reset();
 78:         return $writer->write(
 79:             '$_formStack[] = $_form; $formContainer = $_form = ' . ($name[0] === '$' ? 'is_object(%node.word) ? %node.word : ' : '') . '$_form[%node.word]'
 80:         );
 81:     }
 82: 
 83: 
 84:     /**
 85:      * {label ...}
 86:      */
 87:     public function macroLabel(MacroNode $node, PhpWriter $writer)
 88:     {
 89:         $words = $node->tokenizer->fetchWords();
 90:         if (!$words) {
 91:             throw new CompileException("Missing name in {{$node->name}}.");
 92:         }
 93:         $name = array_shift($words);
 94:         return $writer->write(
 95:             ($name[0] === '$' ? '$_input = is_object(%0.word) ? %0.word : $_form[%0.word]; if ($_label = $_input' : 'if ($_label = $_form[%0.word]')
 96:                 . '->%1.raw) echo $_label'
 97:                 . ($node->tokenizer->isNext() ? '->addAttributes(%node.array)' : ''),
 98:             $name,
 99:             $words ? ('getLabelPart(' . implode(', ', array_map(array($writer, 'formatWord'), $words)) . ')') : 'getLabel()'
100:         );
101:     }
102: 
103: 
104:     /**
105:      * {/label}
106:      */
107:     public function macroLabelEnd(MacroNode $node, PhpWriter $writer)
108:     {
109:         if ($node->content != NULL) {
110:             $node->openingCode = rtrim($node->openingCode, '?> ') . '->startTag() ?>';
111:             return $writer->write('if ($_label) echo $_label->endTag()');
112:         }
113:     }
114: 
115: 
116:     /**
117:      * {input ...}
118:      */
119:     public function macroInput(MacroNode $node, PhpWriter $writer)
120:     {
121:         $words = $node->tokenizer->fetchWords();
122:         if (!$words) {
123:             throw new CompileException("Missing name in {{$node->name}}.");
124:         }
125:         $name = array_shift($words);
126:         return $writer->write(
127:             ($name[0] === '$' ? '$_input = is_object(%0.word) ? %0.word : $_form[%0.word]; echo $_input' : 'echo $_form[%0.word]')
128:                 . '->%1.raw'
129:                 . ($node->tokenizer->isNext() ? '->addAttributes(%node.array)' : ''),
130:             $name,
131:             $words ? 'getControlPart(' . implode(', ', array_map(array($writer, 'formatWord'), $words)) . ')' : 'getControl()'
132:         );
133:     }
134: 
135: 
136:     /**
137:      * deprecated n:input
138:      */
139:     public function macroInputAttr(MacroNode $node, PhpWriter $writer)
140:     {
141:         if (strtolower($node->htmlNode->name) === 'input') {
142:             return $this->macroNameAttr($node, $writer);
143:         } else {
144:             throw new CompileException("Use n:name instead of n:input.");
145:         }
146:     }
147: 
148: 
149:     /**
150:      * <form n:name>, <input n:name>, <select n:name>, <textarea n:name> and <label n:name>
151:      */
152:     public function macroNameAttr(MacroNode $node, PhpWriter $writer)
153:     {
154:         $words = $node->tokenizer->fetchWords();
155:         if (!$words) {
156:             throw new CompileException("Missing name in n:{$node->name}.");
157:         }
158:         $name = array_shift($words);
159:         $tagName = strtolower($node->htmlNode->name);
160:         $node->isEmpty = !in_array($tagName, array('form', 'select', 'textarea'), TRUE);
161: 
162:         if ($tagName === 'form') {
163:             return $writer->write(
164:                 'Nette\Latte\Macros\FormMacros::renderFormBegin($form = $_form = '
165:                     . ($name[0] === '$' ? 'is_object(%0.word) ? %0.word : ' : '')
166:                     . '$_control[%0.word], %1.var, FALSE)',
167:                 $name,
168:                 array_fill_keys(array_keys($node->htmlNode->attrs), NULL)
169:             );
170:         } else {
171:             $method = $tagName === 'label' ? 'getLabel' : 'getControl';
172:             return $writer->write(
173:                 '$_input = ' . ($name[0] === '$' ? 'is_object(%0.word) ? %0.word : ' : '')
174:                     . '$_form[%0.word]; echo $_input->%1.raw'
175:                     . ($node->htmlNode->attrs ? '->addAttributes(%2.var)' : '') . '->attributes()',
176:                 $name,
177:                 $words
178:                     ? $method . 'Part(' . implode(', ', array_map(array($writer, 'formatWord'), $words)) . ')'
179:                     : "{method_exists(\$_input, '{$method}Part')?'{$method}Part':'{$method}'}()",
180:                 array_fill_keys(array_keys($node->htmlNode->attrs), NULL)
181:             );
182:         }
183:     }
184: 
185: 
186:     public function macroName(MacroNode $node, PhpWriter $writer)
187:     {
188:         if (!$node->htmlNode) {
189:             throw new CompileException("Unknown macro {{$node->name}}, use n:{$node->name} attribute.");
190:         } elseif ($node->prefix !== MacroNode::PREFIX_NONE) {
191:             throw new CompileException("Unknown attribute n:{$node->prefix}-{$node->name}, use n:{$node->name} attribute.");
192:         }
193:     }
194: 
195: 
196:     public function macroNameEnd(MacroNode $node, PhpWriter $writer)
197:     {
198:         preg_match('#^(.*? n:\w+>)(.*)(<[^?].*)\z#s', $node->content, $parts);
199:         if (strtolower($node->htmlNode->name) === 'form') {
200:             $node->content = $parts[1] . $parts[2] . '<?php Nette\Latte\Macros\FormMacros::renderFormEnd($_form, FALSE) ?>' . $parts[3];
201:         } else { // select, textarea
202:             $node->content = $parts[1] . '<?php echo $_input->getControl()->getHtml() ?>' . $parts[3];
203:         }
204:     }
205: 
206: 
207:     /**
208:      * {inputError ...}
209:      */
210:     public function macroInputError(MacroNode $node, PhpWriter $writer)
211:     {
212:         $name = $node->tokenizer->fetchWord();
213:         if (!$name) {
214:             return $writer->write('echo %escape($_input->getError())');
215:         } elseif ($name[0] === '$') {
216:             return $writer->write('$_input = is_object(%0.word) ? %0.word : $_form[%0.word]; echo %escape($_input->getError())', $name);
217:         } else {
218:             return $writer->write('echo %escape($_form[%0.word]->getError())', $name);
219:         }
220:     }
221: 
222: 
223:     /********************* run-time writers ****************d*g**/
224: 
225: 
226:     /**
227:      * Renders form begin.
228:      * @return void
229:      */
230:     public static function renderFormBegin(Form $form, array $attrs, $withTags = TRUE)
231:     {
232:         foreach ($form->getControls() as $control) {
233:             $control->setOption('rendered', FALSE);
234:         }
235:         $el = $form->getElementPrototype();
236:         $el->action = (string) $el->action;
237:         $el = clone $el;
238:         if (strcasecmp($form->getMethod(), 'get') === 0) {
239:             $el->action = preg_replace('~\?[^#]*~', '', $el->action, 1);
240:         }
241:         $el->addAttributes($attrs);
242:         echo $withTags ? $el->startTag() : $el->attributes();
243:     }
244: 
245: 
246:     /**
247:      * Renders form end.
248:      * @return string
249:      */
250:     public static function renderFormEnd(Form $form, $withTags = TRUE)
251:     {
252:         $s = '';
253:         if (strcasecmp($form->getMethod(), 'get') === 0) {
254:             foreach (preg_split('#[;&]#', parse_url($form->getElementPrototype()->action, PHP_URL_QUERY), NULL, PREG_SPLIT_NO_EMPTY) as $param) {
255:                 $parts = explode('=', $param, 2);
256:                 $name = urldecode($parts[0]);
257:                 if (!isset($form[$name])) {
258:                     $s .= Nette\Utils\Html::el('input', array('type' => 'hidden', 'name' => $name, 'value' => urldecode($parts[1])));
259:                 }
260:             }
261:         }
262: 
263:         foreach ($form->getComponents(TRUE, 'Nette\Forms\Controls\HiddenField') as $control) {
264:             if (!$control->getOption('rendered')) {
265:                 $s .= $control->getControl();
266:             }
267:         }
268: 
269:         if (iterator_count($form->getComponents(TRUE, 'Nette\Forms\Controls\TextInput')) < 2) {
270:             $s .= '<!--[if IE]><input type=IEbug disabled style="display:none"><![endif]-->';
271:         }
272: 
273:         echo ($s ? "<div>$s</div>\n" : '') . ($withTags ? $form->getElementPrototype()->endTag() . "\n" : '');
274:     }
275: 
276: }
277: 
Nette 2.1 API documentation generated by ApiGen 2.8.0