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