1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Nette\Forms;
13:
14: use Nette,
15: Nette\Web\Html;
16:
17:
18:
19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39:
40: abstract class FormControl extends Nette\Component implements IFormControl
41: {
42:
43: public static $idMask = 'frm%s-%s';
44:
45:
46: public $caption;
47:
48:
49: protected $value;
50:
51:
52: protected $control;
53:
54:
55: protected $label;
56:
57:
58: private $errors = array();
59:
60:
61: private $disabled = FALSE;
62:
63:
64: private $htmlId;
65:
66:
67: private $htmlName;
68:
69:
70: private $rules;
71:
72:
73: private $translator = TRUE;
74:
75:
76: private $options = array();
77:
78:
79:
80: 81: 82:
83: public function __construct($caption = NULL)
84: {
85: $this->monitor('Nette\Forms\Form');
86: parent::__construct();
87: $this->control = Html::el('input');
88: $this->label = Html::el('label');
89: $this->caption = $caption;
90: $this->rules = new Rules($this);
91: }
92:
93:
94:
95: 96: 97: 98: 99:
100: protected function attached($form)
101: {
102: if (!$this->disabled && $form instanceof Form && $form->isAnchored() && $form->isSubmitted()) {
103: $this->htmlName = NULL;
104: $this->loadHttpData();
105: }
106: }
107:
108:
109:
110: 111: 112: 113: 114:
115: public function getForm($need = TRUE)
116: {
117: return $this->lookup('Nette\Forms\Form', $need);
118: }
119:
120:
121:
122: 123: 124: 125:
126: public function getHtmlName()
127: {
128: if ($this->htmlName === NULL) {
129: $s = '';
130: $name = $this->getName();
131: $obj = $this->lookup('Nette\Forms\INamingContainer', TRUE);
132: while (!($obj instanceof Form)) {
133: $s = "[$name]$s";
134: $name = $obj->getName();
135: $obj = $obj->lookup('Nette\Forms\INamingContainer', TRUE);
136: }
137: $name .= $s;
138: if ($name === 'submit') {
139: throw new \InvalidArgumentException("Form control name 'submit' is not allowed due to JavaScript limitations.");
140: }
141: $this->htmlName = $name;
142: }
143: return $this->htmlName;
144: }
145:
146:
147:
148: 149: 150: 151: 152:
153: public function setHtmlId($id)
154: {
155: $this->htmlId = $id;
156: return $this;
157: }
158:
159:
160:
161: 162: 163: 164:
165: public function getHtmlId()
166: {
167: if ($this->htmlId === FALSE) {
168: return NULL;
169:
170: } elseif ($this->htmlId === NULL) {
171: $this->htmlId = sprintf(self::$idMask, $this->getForm()->getName(), $this->getHtmlName());
172: $this->htmlId = str_replace(array('[]', '[', ']'), array('', '-', ''), $this->htmlId);
173: }
174: return $this->htmlId;
175: }
176:
177:
178:
179: 180: 181: 182: 183: 184: 185: 186: 187: 188:
189: public function setOption($key, $value)
190: {
191: if ($value === NULL) {
192: unset($this->options[$key]);
193:
194: } else {
195: $this->options[$key] = $value;
196: }
197: return $this;
198: }
199:
200:
201:
202: 203: 204: 205: 206: 207:
208: final public function getOption($key, $default = NULL)
209: {
210: return isset($this->options[$key]) ? $this->options[$key] : $default;
211: }
212:
213:
214:
215: 216: 217: 218:
219: final public function getOptions()
220: {
221: return $this->options;
222: }
223:
224:
225:
226:
227:
228:
229:
230: 231: 232: 233: 234:
235: public function setTranslator(Nette\ITranslator $translator = NULL)
236: {
237: $this->translator = $translator;
238: return $this;
239: }
240:
241:
242:
243: 244: 245: 246:
247: final public function getTranslator()
248: {
249: if ($this->translator === TRUE) {
250: return $this->getForm(FALSE) ? $this->getForm()->getTranslator() : NULL;
251: }
252: return $this->translator;
253: }
254:
255:
256:
257: 258: 259: 260: 261: 262:
263: public function translate($s, $count = NULL)
264: {
265: $translator = $this->getTranslator();
266: return $translator === NULL || $s == NULL ? $s : $translator->translate($s, $count);
267: }
268:
269:
270:
271:
272:
273:
274:
275: 276: 277: 278: 279:
280: public function setValue($value)
281: {
282: $this->value = $value;
283: return $this;
284: }
285:
286:
287:
288: 289: 290: 291:
292: public function getValue()
293: {
294: return $this->value;
295: }
296:
297:
298:
299: 300: 301: 302: 303:
304: public function setDefaultValue($value)
305: {
306: $form = $this->getForm(FALSE);
307: if (!$form || !$form->isAnchored() || !$form->isSubmitted()) {
308: $this->setValue($value);
309: }
310: return $this;
311: }
312:
313:
314:
315: 316: 317: 318:
319: public function loadHttpData()
320: {
321: $path = explode('[', strtr(str_replace(array('[]', ']'), '', $this->getHtmlName()), '.', '_'));
322: $this->setValue(Nette\ArrayTools::get($this->getForm()->getHttpData(), $path));
323: }
324:
325:
326:
327: 328: 329: 330: 331:
332: public function setDisabled($value = TRUE)
333: {
334: $this->disabled = (bool) $value;
335: return $this;
336: }
337:
338:
339:
340: 341: 342: 343:
344: public function isDisabled()
345: {
346: return $this->disabled;
347: }
348:
349:
350:
351:
352:
353:
354:
355: 356: 357: 358:
359: public function getControl()
360: {
361: $this->setOption('rendered', TRUE);
362: $control = clone $this->control;
363: $control->name = $this->getHtmlName();
364: $control->disabled = $this->disabled;
365: $control->id = $this->getHtmlId();
366: return $control;
367: }
368:
369:
370:
371: 372: 373: 374: 375:
376: public function getLabel($caption = NULL)
377: {
378: $label = clone $this->label;
379: $label->for = $this->getHtmlId();
380: if ($caption !== NULL) {
381: $label->setText($this->translate($caption));
382:
383: } elseif ($this->caption instanceof Html) {
384: $label->add($this->caption);
385:
386: } else {
387: $label->setText($this->translate($this->caption));
388: }
389: return $label;
390: }
391:
392:
393:
394: 395: 396: 397:
398: final public function getControlPrototype()
399: {
400: return $this->control;
401: }
402:
403:
404:
405: 406: 407: 408:
409: final public function getLabelPrototype()
410: {
411: return $this->label;
412: }
413:
414:
415:
416: 417: 418: 419: 420: 421:
422: public function setRendered($value = TRUE)
423: {
424: $this->setOption('rendered', $value);
425: return $this;
426: }
427:
428:
429:
430: 431: 432: 433: 434:
435: public function isRendered()
436: {
437: return !empty($this->options['rendered']);
438: }
439:
440:
441:
442:
443:
444:
445:
446: 447: 448: 449: 450: 451: 452:
453: public function addRule($operation, $message = NULL, $arg = NULL)
454: {
455: $this->rules->addRule($operation, $message, $arg);
456: return $this;
457: }
458:
459:
460:
461: 462: 463: 464: 465: 466:
467: public function addCondition($operation, $value = NULL)
468: {
469: return $this->rules->addCondition($operation, $value);
470: }
471:
472:
473:
474: 475: 476: 477: 478: 479: 480:
481: public function addConditionOn(IFormControl $control, $operation, $value = NULL)
482: {
483: return $this->rules->addConditionOn($control, $operation, $value);
484: }
485:
486:
487:
488: 489: 490:
491: final public function getRules()
492: {
493: return $this->rules;
494: }
495:
496:
497:
498: 499: 500: 501: 502: 503:
504: final public function setRequired($message = NULL)
505: {
506: $this->rules->addRule(Form::FILLED, $message);
507: return $this;
508: }
509:
510:
511:
512: 513: 514: 515: 516:
517: final public function isRequired()
518: {
519: return !empty($this->options['required']);
520: }
521:
522:
523:
524: 525: 526: 527: 528:
529: public function notifyRule(Rule $rule)
530: {
531: if (is_string($rule->operation) && strcasecmp($rule->operation, ':filled') === 0) {
532: $this->setOption('required', TRUE);
533: }
534: }
535:
536:
537:
538:
539:
540:
541:
542: 543: 544: 545: 546: 547:
548: public static function validateEqual(IFormControl $control, $arg)
549: {
550: $value = $control->getValue();
551: foreach ((is_array($value) ? $value : array($value)) as $val) {
552: foreach ((is_array($arg) ? $arg : array($arg)) as $item) {
553: if ((string) $val === (string) ($item instanceof IFormControl ? $item->value : $item)) {
554: return TRUE;
555: }
556: }
557: }
558: return FALSE;
559: }
560:
561:
562:
563: 564: 565: 566: 567:
568: public static function validateFilled(IFormControl $control)
569: {
570: return (string) $control->getValue() !== '';
571: }
572:
573:
574:
575: 576: 577: 578: 579:
580: public static function validateValid(IFormControl $control)
581: {
582: return $control->rules->validate(TRUE);
583: }
584:
585:
586:
587: 588: 589: 590: 591:
592: public function addError($message)
593: {
594: if (!in_array($message, $this->errors, TRUE)) {
595: $this->errors[] = $message;
596: }
597: $this->getForm()->addError($message);
598: }
599:
600:
601:
602: 603: 604: 605:
606: public function getErrors()
607: {
608: return $this->errors;
609: }
610:
611:
612:
613: 614: 615:
616: public function hasErrors()
617: {
618: return (bool) $this->errors;
619: }
620:
621:
622:
623: 624: 625:
626: public function cleanErrors()
627: {
628: $this->errors = array();
629: }
630:
631: }
632: