1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Forms;
9:
10: use Nette;
11:
12:
13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
23: class Container extends Nette\ComponentModel\Container implements \ArrayAccess
24: {
25:
26: public $onValidate;
27:
28:
29: protected $currentGroup;
30:
31:
32: private $validated;
33:
34:
35:
36:
37:
38: 39: 40: 41: 42: 43:
44: public function setDefaults($values, $erase = FALSE)
45: {
46: $form = $this->getForm(FALSE);
47: if (!$form || !$form->isAnchored() || !$form->isSubmitted()) {
48: $this->setValues($values, $erase);
49: }
50: return $this;
51: }
52:
53:
54: 55: 56: 57: 58: 59:
60: public function setValues($values, $erase = FALSE)
61: {
62: if ($values instanceof \Traversable) {
63: $values = iterator_to_array($values);
64:
65: } elseif (!is_array($values)) {
66: throw new Nette\InvalidArgumentException(sprintf('First parameter must be an array, %s given.', gettype($values)));
67: }
68:
69: foreach ($this->getComponents() as $name => $control) {
70: if ($control instanceof IControl) {
71: if (array_key_exists($name, $values)) {
72: $control->setValue($values[$name]);
73:
74: } elseif ($erase) {
75: $control->setValue(NULL);
76: }
77:
78: } elseif ($control instanceof self) {
79: if (array_key_exists($name, $values)) {
80: $control->setValues($values[$name], $erase);
81:
82: } elseif ($erase) {
83: $control->setValues(array(), $erase);
84: }
85: }
86: }
87: return $this;
88: }
89:
90:
91: 92: 93: 94: 95:
96: public function getValues($asArray = FALSE)
97: {
98: $values = $asArray ? array() : new Nette\Utils\ArrayHash;
99: foreach ($this->getComponents() as $name => $control) {
100: if ($control instanceof IControl && !$control->isOmitted()) {
101: $values[$name] = $control->getValue();
102:
103: } elseif ($control instanceof self) {
104: $values[$name] = $control->getValues($asArray);
105: }
106: }
107: return $values;
108: }
109:
110:
111:
112:
113:
114: 115: 116: 117:
118: public function isValid()
119: {
120: if (!$this->validated) {
121: if ($this->getErrors()) {
122: return FALSE;
123: }
124: $this->validate();
125: }
126: return !$this->getErrors();
127: }
128:
129:
130: 131: 132: 133: 134:
135: public function validate(array $controls = NULL)
136: {
137: foreach ($controls === NULL ? $this->getComponents() : $controls as $control) {
138: $control->validate();
139: }
140: foreach ($this->onValidate ?: array() as $handler) {
141: $params = Nette\Utils\Callback::toReflection($handler)->getParameters();
142: $values = isset($params[1]) ? $this->getValues($params[1]->isArray()) : NULL;
143: Nette\Utils\Callback::invoke($handler, $this, $values);
144: }
145: $this->validated = TRUE;
146: }
147:
148:
149: 150: 151: 152:
153: public function getErrors()
154: {
155: $errors = array();
156: foreach ($this->getControls() as $control) {
157: $errors = array_merge($errors, $control->getErrors());
158: }
159: return array_unique($errors);
160: }
161:
162:
163:
164:
165:
166: 167: 168:
169: public function setCurrentGroup(ControlGroup $group = NULL)
170: {
171: $this->currentGroup = $group;
172: return $this;
173: }
174:
175:
176: 177: 178: 179:
180: public function getCurrentGroup()
181: {
182: return $this->currentGroup;
183: }
184:
185:
186: 187: 188: 189: 190: 191: 192: 193:
194: public function addComponent(Nette\ComponentModel\IComponent $component, $name, $insertBefore = NULL)
195: {
196: parent::addComponent($component, $name, $insertBefore);
197: if ($this->currentGroup !== NULL && $component instanceof IControl) {
198: $this->currentGroup->add($component);
199: }
200: return $this;
201: }
202:
203:
204: 205: 206: 207:
208: public function getControls()
209: {
210: return $this->getComponents(TRUE, 'Nette\Forms\IControl');
211: }
212:
213:
214: 215: 216: 217: 218:
219: public function getForm($need = TRUE)
220: {
221: return $this->lookup('Nette\Forms\Form', $need);
222: }
223:
224:
225:
226:
227:
228: 229: 230: 231: 232: 233: 234: 235:
236: public function addText($name, $label = NULL, $cols = NULL, $maxLength = NULL)
237: {
238: $control = new Controls\TextInput($label, $maxLength);
239: $control->setAttribute('size', $cols);
240: return $this[$name] = $control;
241: }
242:
243:
244: 245: 246: 247: 248: 249: 250: 251:
252: public function addPassword($name, $label = NULL, $cols = NULL, $maxLength = NULL)
253: {
254: $control = new Controls\TextInput($label, $maxLength);
255: $control->setAttribute('size', $cols);
256: return $this[$name] = $control->setType('password');
257: }
258:
259:
260: 261: 262: 263: 264: 265: 266: 267:
268: public function addTextArea($name, $label = NULL, $cols = NULL, $rows = NULL)
269: {
270: $control = new Controls\TextArea($label);
271: $control->setAttribute('cols', $cols)->setAttribute('rows', $rows);
272: return $this[$name] = $control;
273: }
274:
275:
276: 277: 278: 279: 280: 281: 282:
283: public function addUpload($name, $label = NULL, $multiple = FALSE)
284: {
285: return $this[$name] = new Controls\UploadControl($label, $multiple);
286: }
287:
288:
289: 290: 291: 292: 293: 294:
295: public function addMultiUpload($name, $label = NULL)
296: {
297: return $this[$name] = new Controls\UploadControl($label, TRUE);
298: }
299:
300:
301: 302: 303: 304: 305: 306:
307: public function addHidden($name, $default = NULL)
308: {
309: $control = new Controls\HiddenField;
310: $control->setDefaultValue($default);
311: return $this[$name] = $control;
312: }
313:
314:
315: 316: 317: 318: 319: 320:
321: public function addCheckbox($name, $caption = NULL)
322: {
323: return $this[$name] = new Controls\Checkbox($caption);
324: }
325:
326:
327: 328: 329: 330: 331: 332: 333:
334: public function addRadioList($name, $label = NULL, array $items = NULL)
335: {
336: return $this[$name] = new Controls\RadioList($label, $items);
337: }
338:
339:
340: 341: 342: 343:
344: public function addCheckboxList($name, $label = NULL, array $items = NULL)
345: {
346: return $this[$name] = new Controls\CheckboxList($label, $items);
347: }
348:
349:
350: 351: 352: 353: 354: 355: 356: 357:
358: public function addSelect($name, $label = NULL, array $items = NULL, $size = NULL)
359: {
360: $control = new Controls\SelectBox($label, $items);
361: if ($size > 1) {
362: $control->setAttribute('size', (int) $size);
363: }
364: return $this[$name] = $control;
365: }
366:
367:
368: 369: 370: 371: 372: 373: 374: 375:
376: public function addMultiSelect($name, $label = NULL, array $items = NULL, $size = NULL)
377: {
378: $control = new Controls\MultiSelectBox($label, $items);
379: if ($size > 1) {
380: $control->setAttribute('size', (int) $size);
381: }
382: return $this[$name] = $control;
383: }
384:
385:
386: 387: 388: 389: 390: 391:
392: public function addSubmit($name, $caption = NULL)
393: {
394: return $this[$name] = new Controls\SubmitButton($caption);
395: }
396:
397:
398: 399: 400: 401: 402: 403:
404: public function addButton($name, $caption = NULL)
405: {
406: return $this[$name] = new Controls\Button($caption);
407: }
408:
409:
410: 411: 412: 413: 414: 415: 416:
417: public function addImage($name, $src = NULL, $alt = NULL)
418: {
419: return $this[$name] = new Controls\ImageButton($src, $alt);
420: }
421:
422:
423: 424: 425: 426: 427:
428: public function addContainer($name)
429: {
430: $control = new self;
431: $control->currentGroup = $this->currentGroup;
432: return $this[$name] = $control;
433: }
434:
435:
436:
437:
438:
439: 440: 441: 442: 443: 444:
445: public function offsetSet($name, $component)
446: {
447: $this->addComponent($component, $name);
448: }
449:
450:
451: 452: 453: 454: 455: 456:
457: public function offsetGet($name)
458: {
459: return $this->getComponent($name, TRUE);
460: }
461:
462:
463: 464: 465: 466: 467:
468: public function offsetExists($name)
469: {
470: return $this->getComponent($name, FALSE) !== NULL;
471: }
472:
473:
474: 475: 476: 477: 478:
479: public function offsetUnset($name)
480: {
481: $component = $this->getComponent($name, FALSE);
482: if ($component !== NULL) {
483: $this->removeComponent($component);
484: }
485: }
486:
487:
488: 489: 490:
491: public function __clone()
492: {
493: throw new Nette\NotImplementedException('Form cloning is not supported yet.');
494: }
495:
496: }
497: