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