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