Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationDI
      • ApplicationLatte
      • ApplicationTracy
      • CacheDI
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsDI
      • FormsLatte
      • Framework
      • HttpDI
      • HttpTracy
      • MailDI
      • ReflectionDI
      • SecurityDI
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Conventions
      • Drivers
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
    • Reflection
    • Security
    • Utils
  • none
  • Tracy
    • Bridges
      • Nette

Classes

  • Container
  • ControlGroup
  • Form
  • Helpers
  • Rule
  • Rules
  • Validator

Interfaces

  • IControl
  • IFormRenderer
  • ISubmitterControl
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://nette.org)
  5:  * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
  6:  */
  7: 
  8: namespace Nette\Forms;
  9: 
 10: use Nette;
 11: 
 12: 
 13: /**
 14:  * Container for form controls.
 15:  *
 16:  * @property   Nette\Utils\ArrayHash $values
 17:  * @property-read \ArrayIterator $controls
 18:  * @property-read Form $form
 19:  */
 20: class Container extends Nette\ComponentModel\Container implements \ArrayAccess
 21: {
 22:     /** @var callable[]  function (Container $sender); Occurs when the form is validated */
 23:     public $onValidate;
 24: 
 25:     /** @var ControlGroup */
 26:     protected $currentGroup;
 27: 
 28:     /** @var bool */
 29:     private $validated;
 30: 
 31: 
 32:     /********************* data exchange ****************d*g**/
 33: 
 34: 
 35:     /**
 36:      * Fill-in with default values.
 37:      * @param  array|\Traversable  values used to fill the form
 38:      * @param  bool     erase other default values?
 39:      * @return static
 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:      * Fill-in with values.
 53:      * @param  array|\Traversable  values used to fill the form
 54:      * @param  bool     erase other controls?
 55:      * @return static
 56:      * @internal
 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([], $erase);
 82:                 }
 83:             }
 84:         }
 85:         return $this;
 86:     }
 87: 
 88: 
 89:     /**
 90:      * Returns the values submitted by the form.
 91:      * @param  bool  return values as an array?
 92:      * @return Nette\Utils\ArrayHash|array
 93:      */
 94:     public function getValues($asArray = FALSE)
 95:     {
 96:         $values = $asArray ? [] : 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:     /********************* validation ****************d*g**/
110: 
111: 
112:     /**
113:      * Is form valid?
114:      * @return bool
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:      * Performs the server side validation.
130:      * @param  IControl[]
131:      * @return void
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:      * Returns all validation errors.
156:      * @return array
157:      */
158:     public function getErrors()
159:     {
160:         $errors = [];
161:         foreach ($this->getControls() as $control) {
162:             $errors = array_merge($errors, $control->getErrors());
163:         }
164:         return array_unique($errors);
165:     }
166: 
167: 
168:     /********************* form building ****************d*g**/
169: 
170: 
171:     /**
172:      * @return static
173:      */
174:     public function setCurrentGroup(ControlGroup $group = NULL)
175:     {
176:         $this->currentGroup = $group;
177:         return $this;
178:     }
179: 
180: 
181:     /**
182:      * Returns current group.
183:      * @return ControlGroup
184:      */
185:     public function getCurrentGroup()
186:     {
187:         return $this->currentGroup;
188:     }
189: 
190: 
191:     /**
192:      * Adds the specified component to the IContainer.
193:      * @param  Nette\ComponentModel\IComponent
194:      * @param  string
195:      * @param  string
196:      * @return static
197:      * @throws Nette\InvalidStateException
198:      */
199:     public function addComponent(Nette\ComponentModel\IComponent $component, $name, $insertBefore = NULL)
200:     {
201:         parent::addComponent($component, $name, $insertBefore);
202:         if ($this->currentGroup !== NULL) {
203:             $this->currentGroup->add($component);
204:         }
205:         return $this;
206:     }
207: 
208: 
209:     /**
210:      * Iterates over all form controls.
211:      * @return \ArrayIterator
212:      */
213:     public function getControls()
214:     {
215:         return $this->getComponents(TRUE, IControl::class);
216:     }
217: 
218: 
219:     /**
220:      * Returns form.
221:      * @param  bool   throw exception if form doesn't exist?
222:      * @return Form
223:      */
224:     public function getForm($need = TRUE)
225:     {
226:         return $this->lookup(Form::class, $need);
227:     }
228: 
229: 
230:     /********************* control factories ****************d*g**/
231: 
232: 
233:     /**
234:      * Adds single-line text input control to the form.
235:      * @param  string  control name
236:      * @param  string  label
237:      * @param  int  width of the control (deprecated)
238:      * @param  int  maximum number of characters the user may enter
239:      * @return Controls\TextInput
240:      */
241:     public function addText($name, $label = NULL, $cols = NULL, $maxLength = NULL)
242:     {
243:         return $this[$name] = (new Controls\TextInput($label, $maxLength))
244:             ->setHtmlAttribute('size', $cols);
245:     }
246: 
247: 
248:     /**
249:      * Adds single-line text input control used for sensitive input such as passwords.
250:      * @param  string  control name
251:      * @param  string  label
252:      * @param  int  width of the control (deprecated)
253:      * @param  int  maximum number of characters the user may enter
254:      * @return Controls\TextInput
255:      */
256:     public function addPassword($name, $label = NULL, $cols = NULL, $maxLength = NULL)
257:     {
258:         return $this[$name] = (new Controls\TextInput($label, $maxLength))
259:             ->setHtmlAttribute('size', $cols)
260:             ->setHtmlType('password');
261:     }
262: 
263: 
264:     /**
265:      * Adds multi-line text input control to the form.
266:      * @param  string  control name
267:      * @param  string  label
268:      * @param  int  width of the control
269:      * @param  int  height of the control in text lines
270:      * @return Controls\TextArea
271:      */
272:     public function addTextArea($name, $label = NULL, $cols = NULL, $rows = NULL)
273:     {
274:         return $this[$name] = (new Controls\TextArea($label))
275:             ->setHtmlAttribute('cols', $cols)->setHtmlAttribute('rows', $rows);
276:     }
277: 
278: 
279:     /**
280:      * Adds input for email.
281:      * @param  string  control name
282:      * @param  string  label
283:      * @return Controls\TextInput
284:      */
285:     public function addEmail($name, $label = NULL)
286:     {
287:         return $this[$name] = (new Controls\TextInput($label))
288:             ->setRequired(FALSE)
289:             ->addRule(Form::EMAIL);
290:     }
291: 
292: 
293:     /**
294:      * Adds input for integer.
295:      * @param  string  control name
296:      * @param  string  label
297:      * @return Controls\TextInput
298:      */
299:     public function addInteger($name, $label = NULL)
300:     {
301:         return $this[$name] = (new Controls\TextInput($label))
302:             ->setNullable()
303:             ->setRequired(FALSE)
304:             ->addRule(Form::INTEGER);
305:     }
306: 
307: 
308:     /**
309:      * Adds control that allows the user to upload files.
310:      * @param  string  control name
311:      * @param  string  label
312:      * @param  bool  allows to upload multiple files
313:      * @return Controls\UploadControl
314:      */
315:     public function addUpload($name, $label = NULL, $multiple = FALSE)
316:     {
317:         return $this[$name] = new Controls\UploadControl($label, $multiple);
318:     }
319: 
320: 
321:     /**
322:      * Adds control that allows the user to upload multiple files.
323:      * @param  string  control name
324:      * @param  string  label
325:      * @return Controls\UploadControl
326:      */
327:     public function addMultiUpload($name, $label = NULL)
328:     {
329:         return $this[$name] = new Controls\UploadControl($label, TRUE);
330:     }
331: 
332: 
333:     /**
334:      * Adds hidden form control used to store a non-displayed value.
335:      * @param  string  control name
336:      * @param  mixed   default value
337:      * @return Controls\HiddenField
338:      */
339:     public function addHidden($name, $default = NULL)
340:     {
341:         return $this[$name] = (new Controls\HiddenField)
342:             ->setDefaultValue($default);
343:     }
344: 
345: 
346:     /**
347:      * Adds check box control to the form.
348:      * @param  string  control name
349:      * @param  string  caption
350:      * @return Controls\Checkbox
351:      */
352:     public function addCheckbox($name, $caption = NULL)
353:     {
354:         return $this[$name] = new Controls\Checkbox($caption);
355:     }
356: 
357: 
358:     /**
359:      * Adds set of radio button controls to the form.
360:      * @param  string  control name
361:      * @param  string  label
362:      * @param  array   options from which to choose
363:      * @return Controls\RadioList
364:      */
365:     public function addRadioList($name, $label = NULL, array $items = NULL)
366:     {
367:         return $this[$name] = new Controls\RadioList($label, $items);
368:     }
369: 
370: 
371:     /**
372:      * Adds set of checkbox controls to the form.
373:      * @return Controls\CheckboxList
374:      */
375:     public function addCheckboxList($name, $label = NULL, array $items = NULL)
376:     {
377:         return $this[$name] = new Controls\CheckboxList($label, $items);
378:     }
379: 
380: 
381:     /**
382:      * Adds select box control that allows single item selection.
383:      * @param  string  control name
384:      * @param  string  label
385:      * @param  array   items from which to choose
386:      * @param  int     number of rows that should be visible
387:      * @return Controls\SelectBox
388:      */
389:     public function addSelect($name, $label = NULL, array $items = NULL, $size = NULL)
390:     {
391:         return $this[$name] = (new Controls\SelectBox($label, $items))
392:             ->setHtmlAttribute('size', $size > 1 ? (int) $size : NULL);
393:     }
394: 
395: 
396:     /**
397:      * Adds select box control that allows multiple item selection.
398:      * @param  string  control name
399:      * @param  string  label
400:      * @param  array   options from which to choose
401:      * @param  int     number of rows that should be visible
402:      * @return Controls\MultiSelectBox
403:      */
404:     public function addMultiSelect($name, $label = NULL, array $items = NULL, $size = NULL)
405:     {
406:         return $this[$name] = (new Controls\MultiSelectBox($label, $items))
407:             ->setHtmlAttribute('size', $size > 1 ? (int) $size : NULL);
408:     }
409: 
410: 
411:     /**
412:      * Adds button used to submit form.
413:      * @param  string  control name
414:      * @param  string  caption
415:      * @return Controls\SubmitButton
416:      */
417:     public function addSubmit($name, $caption = NULL)
418:     {
419:         return $this[$name] = new Controls\SubmitButton($caption);
420:     }
421: 
422: 
423:     /**
424:      * Adds push buttons with no default behavior.
425:      * @param  string  control name
426:      * @param  string  caption
427:      * @return Controls\Button
428:      */
429:     public function addButton($name, $caption = NULL)
430:     {
431:         return $this[$name] = new Controls\Button($caption);
432:     }
433: 
434: 
435:     /**
436:      * Adds graphical button used to submit form.
437:      * @param  string  control name
438:      * @param  string  URI of the image
439:      * @param  string  alternate text for the image
440:      * @return Controls\ImageButton
441:      */
442:     public function addImage($name, $src = NULL, $alt = NULL)
443:     {
444:         return $this[$name] = new Controls\ImageButton($src, $alt);
445:     }
446: 
447: 
448:     /**
449:      * Adds naming container to the form.
450:      * @param  string  name
451:      * @return self
452:      */
453:     public function addContainer($name)
454:     {
455:         $control = new self;
456:         $control->currentGroup = $this->currentGroup;
457:         if ($this->currentGroup !== NULL) {
458:             $this->currentGroup->add($control);
459:         }
460:         return $this[$name] = $control;
461:     }
462: 
463: 
464:     /********************* extension methods ****************d*g**/
465: 
466: 
467:     public function __call($name, $args)
468:     {
469:         if ($callback = Nette\Utils\ObjectMixin::getExtensionMethod(__CLASS__, $name)) {
470:             return Nette\Utils\Callback::invoke($callback, $this, ...$args);
471:         }
472:         return parent::__call($name, $args);
473:     }
474: 
475: 
476:     public static function extensionMethod($name, $callback = NULL)
477:     {
478:         if (strpos($name, '::') !== FALSE) { // back compatibility
479:             list(, $name) = explode('::', $name);
480:         }
481:         Nette\Utils\ObjectMixin::setExtensionMethod(__CLASS__, $name, $callback);
482:     }
483: 
484: 
485:     /********************* interface \ArrayAccess ****************d*g**/
486: 
487: 
488:     /**
489:      * Adds the component to the container.
490:      * @param  string  component name
491:      * @param  Nette\ComponentModel\IComponent
492:      * @return void
493:      */
494:     public function offsetSet($name, $component)
495:     {
496:         $this->addComponent($component, $name);
497:     }
498: 
499: 
500:     /**
501:      * Returns component specified by name. Throws exception if component doesn't exist.
502:      * @param  string  component name
503:      * @return Nette\ComponentModel\IComponent
504:      * @throws Nette\InvalidArgumentException
505:      */
506:     public function offsetGet($name)
507:     {
508:         return $this->getComponent($name, TRUE);
509:     }
510: 
511: 
512:     /**
513:      * Does component specified by name exists?
514:      * @param  string  component name
515:      * @return bool
516:      */
517:     public function offsetExists($name)
518:     {
519:         return $this->getComponent($name, FALSE) !== NULL;
520:     }
521: 
522: 
523:     /**
524:      * Removes component from the container.
525:      * @param  string  component name
526:      * @return void
527:      */
528:     public function offsetUnset($name)
529:     {
530:         $component = $this->getComponent($name, FALSE);
531:         if ($component !== NULL) {
532:             $this->removeComponent($component);
533:         }
534:     }
535: 
536: 
537:     /**
538:      * Prevents cloning.
539:      */
540:     public function __clone()
541:     {
542:         throw new Nette\NotImplementedException('Form cloning is not supported yet.');
543:     }
544: 
545: }
546: 
Nette 2.4-20170221 API API documentation generated by ApiGen 2.8.0