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

  • BaseControl
  • Button
  • Checkbox
  • CheckboxList
  • ChoiceControl
  • CsrfProtection
  • HiddenField
  • ImageButton
  • MultiChoiceControl
  • MultiSelectBox
  • RadioList
  • SelectBox
  • SubmitButton
  • TextArea
  • TextBase
  • TextInput
  • UploadControl
  • 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\Controls;
  9: 
 10: use Nette;
 11: use Nette\Forms\Form;
 12: use Nette\Forms\IControl;
 13: use Nette\Forms\Rules;
 14: use Nette\Utils\Html;
 15: 
 16: 
 17: /**
 18:  * Base class that implements the basic functionality common to form controls.
 19:  *
 20:  * @property-read Form $form
 21:  * @property-read string $htmlName
 22:  * @property   string $htmlId
 23:  * @property   mixed $value
 24:  * @property   bool $disabled
 25:  * @property   bool $omitted
 26:  * @property-read Html $control
 27:  * @property-read Html $label
 28:  * @property-read Html $controlPrototype
 29:  * @property-read Html $labelPrototype
 30:  * @property   bool $required
 31:  * @property-read bool $filled
 32:  * @property-read array $errors
 33:  * @property-read array $options
 34:  * @property-read string $error
 35:  */
 36: abstract class BaseControl extends Nette\ComponentModel\Component implements IControl
 37: {
 38:     /** @var string */
 39:     public static $idMask = 'frm-%s';
 40: 
 41:     /** @var string textual caption or label */
 42:     public $caption;
 43: 
 44:     /** @var mixed current control value */
 45:     protected $value;
 46: 
 47:     /** @var Html  control element template */
 48:     protected $control;
 49: 
 50:     /** @var Html  label element template */
 51:     protected $label;
 52: 
 53:     /** @var array */
 54:     private $errors = [];
 55: 
 56:     /** @var bool */
 57:     protected $disabled = FALSE;
 58: 
 59:     /** @var bool|NULL */
 60:     private $omitted;
 61: 
 62:     /** @var Rules */
 63:     private $rules;
 64: 
 65:     /** @var Nette\Localization\ITranslator */
 66:     private $translator = TRUE; // means autodetect
 67: 
 68:     /** @var array user options */
 69:     private $options = [];
 70: 
 71:     /** @var bool */
 72:     private static $autoOptional = FALSE;
 73: 
 74: 
 75:     /**
 76:      * @param  string  caption
 77:      */
 78:     public function __construct($caption = NULL)
 79:     {
 80:         $this->monitor(Form::class);
 81:         parent::__construct();
 82:         $this->control = Html::el('input', ['type' => NULL, 'name' => NULL]);
 83:         $this->label = Html::el('label');
 84:         $this->caption = $caption;
 85:         $this->rules = new Rules($this);
 86:         if (self::$autoOptional) {
 87:             $this->setRequired(FALSE);
 88:         }
 89:         $this->setValue(NULL);
 90:     }
 91: 
 92: 
 93:     /**
 94:      * This method will be called when the component becomes attached to Form.
 95:      * @param  Nette\ComponentModel\IComponent
 96:      * @return void
 97:      */
 98:     protected function attached($form)
 99:     {
100:         if (!$this->isDisabled() && $form instanceof Form && $form->isAnchored() && $form->isSubmitted()) {
101:             $this->loadHttpData();
102:         }
103:     }
104: 
105: 
106:     /**
107:      * Returns form.
108:      * @param  bool   throw exception if form doesn't exist?
109:      * @return Form
110:      */
111:     public function getForm($need = TRUE)
112:     {
113:         return $this->lookup(Form::class, $need);
114:     }
115: 
116: 
117:     /**
118:      * Loads HTTP data.
119:      * @return void
120:      */
121:     public function loadHttpData()
122:     {
123:         $this->setValue($this->getHttpData(Form::DATA_TEXT));
124:     }
125: 
126: 
127:     /**
128:      * Loads HTTP data.
129:      * @return mixed
130:      */
131:     protected function getHttpData($type, $htmlTail = NULL)
132:     {
133:         return $this->getForm()->getHttpData($type, $this->getHtmlName() . $htmlTail);
134:     }
135: 
136: 
137:     /**
138:      * Returns HTML name of control.
139:      * @return string
140:      */
141:     public function getHtmlName()
142:     {
143:         return Nette\Forms\Helpers::generateHtmlName($this->lookupPath(Form::class));
144:     }
145: 
146: 
147:     /********************* interface IControl ****************d*g**/
148: 
149: 
150:     /**
151:      * Sets control's value.
152:      * @return static
153:      * @internal
154:      */
155:     public function setValue($value)
156:     {
157:         $this->value = $value;
158:         return $this;
159:     }
160: 
161: 
162:     /**
163:      * Returns control's value.
164:      * @return mixed
165:      */
166:     public function getValue()
167:     {
168:         return $this->value;
169:     }
170: 
171: 
172:     /**
173:      * Is control filled?
174:      * @return bool
175:      */
176:     public function isFilled()
177:     {
178:         $value = $this->getValue();
179:         return $value !== NULL && $value !== [] && $value !== '';
180:     }
181: 
182: 
183:     /**
184:      * Sets control's default value.
185:      * @return static
186:      */
187:     public function setDefaultValue($value)
188:     {
189:         $form = $this->getForm(FALSE);
190:         if ($this->isDisabled() || !$form || !$form->isAnchored() || !$form->isSubmitted()) {
191:             $this->setValue($value);
192:         }
193:         return $this;
194:     }
195: 
196: 
197:     /**
198:      * Disables or enables control.
199:      * @param  bool
200:      * @return static
201:      */
202:     public function setDisabled($value = TRUE)
203:     {
204:         if ($this->disabled = (bool) $value) {
205:             $this->setValue(NULL);
206:         }
207:         return $this;
208:     }
209: 
210: 
211:     /**
212:      * Is control disabled?
213:      * @return bool
214:      */
215:     public function isDisabled()
216:     {
217:         return $this->disabled === TRUE;
218:     }
219: 
220: 
221:     /**
222:      * Sets whether control value is excluded from $form->getValues() result.
223:      * @param  bool
224:      * @return static
225:      */
226:     public function setOmitted($value = TRUE)
227:     {
228:         $this->omitted = (bool) $value;
229:         return $this;
230:     }
231: 
232: 
233:     /**
234:      * Is control value excluded from $form->getValues() result?
235:      * @return bool
236:      */
237:     public function isOmitted()
238:     {
239:         return $this->omitted || ($this->isDisabled() && $this->omitted === NULL);
240:     }
241: 
242: 
243:     /********************* rendering ****************d*g**/
244: 
245: 
246:     /**
247:      * Generates control's HTML element.
248:      * @return Html|string
249:      */
250:     public function getControl()
251:     {
252:         $this->setOption('rendered', TRUE);
253:         $el = clone $this->control;
254:         return $el->addAttributes([
255:             'name' => $this->getHtmlName(),
256:             'id' => $this->getHtmlId(),
257:             'required' => $this->isRequired(),
258:             'disabled' => $this->isDisabled(),
259:             'data-nette-rules' => Nette\Forms\Helpers::exportRules($this->rules) ?: NULL,
260:         ]);
261:     }
262: 
263: 
264:     /**
265:      * Generates label's HTML element.
266:      * @param  string
267:      * @return Html|string
268:      */
269:     public function getLabel($caption = NULL)
270:     {
271:         $label = clone $this->label;
272:         $label->for = $this->getHtmlId();
273:         $label->setText($this->translate($caption === NULL ? $this->caption : $caption));
274:         return $label;
275:     }
276: 
277: 
278:     /**
279:      * @return Nette\Utils\Html|NULL
280:      */
281:     public function getControlPart()
282:     {
283:         return $this->getControl();
284:     }
285: 
286: 
287:     /**
288:      * @return Nette\Utils\Html|NULL
289:      */
290:     public function getLabelPart()
291:     {
292:         return $this->getLabel();
293:     }
294: 
295: 
296:     /**
297:      * Returns control's HTML element template.
298:      * @return Html
299:      */
300:     public function getControlPrototype()
301:     {
302:         return $this->control;
303:     }
304: 
305: 
306:     /**
307:      * Returns label's HTML element template.
308:      * @return Html
309:      */
310:     public function getLabelPrototype()
311:     {
312:         return $this->label;
313:     }
314: 
315: 
316:     /**
317:      * Changes control's HTML id.
318:      * @param  string new ID, or FALSE or NULL
319:      * @return static
320:      */
321:     public function setHtmlId($id)
322:     {
323:         $this->control->id = $id;
324:         return $this;
325:     }
326: 
327: 
328:     /**
329:      * Returns control's HTML id.
330:      * @return string
331:      */
332:     public function getHtmlId()
333:     {
334:         if (!isset($this->control->id)) {
335:             $this->control->id = sprintf(self::$idMask, $this->lookupPath());
336:         }
337:         return $this->control->id;
338:     }
339: 
340: 
341:     /**
342:      * Changes control's HTML attribute.
343:      * @param  string name
344:      * @param  mixed  value
345:      * @return static
346:      */
347:     public function setHtmlAttribute($name, $value = TRUE)
348:     {
349:         return $this->setAttribute($name, $value);
350:     }
351: 
352: 
353:     /**
354:      * Alias for setHtmlAttribute()
355:      * @param  string name
356:      * @param  mixed  value
357:      * @return static
358:      */
359:     public function setAttribute($name, $value = TRUE)
360:     {
361:         $this->control->$name = $value;
362:         return $this;
363:     }
364: 
365: 
366:     /********************* translator ****************d*g**/
367: 
368: 
369:     /**
370:      * Sets translate adapter.
371:      * @return static
372:      */
373:     public function setTranslator(Nette\Localization\ITranslator $translator = NULL)
374:     {
375:         $this->translator = $translator;
376:         return $this;
377:     }
378: 
379: 
380:     /**
381:      * Returns translate adapter.
382:      * @return Nette\Localization\ITranslator|NULL
383:      */
384:     public function getTranslator()
385:     {
386:         if ($this->translator === TRUE) {
387:             return $this->getForm(FALSE) ? $this->getForm()->getTranslator() : NULL;
388:         }
389:         return $this->translator;
390:     }
391: 
392: 
393:     /**
394:      * Returns translated string.
395:      * @param  mixed
396:      * @param  int      plural count
397:      * @return string
398:      */
399:     public function translate($value, $count = NULL)
400:     {
401:         if ($translator = $this->getTranslator()) {
402:             $tmp = is_array($value) ? [& $value] : [[& $value]];
403:             foreach ($tmp[0] as & $v) {
404:                 if ($v != NULL && !$v instanceof Html) { // intentionally ==
405:                     $v = $translator->translate($v, $count);
406:                 }
407:             }
408:         }
409:         return $value;
410:     }
411: 
412: 
413:     /********************* rules ****************d*g**/
414: 
415: 
416:     /**
417:      * Adds a validation rule.
418:      * @param  mixed      rule type
419:      * @param  string     message to display for invalid data
420:      * @param  mixed      optional rule arguments
421:      * @return static
422:      */
423:     public function addRule($validator, $message = NULL, $arg = NULL)
424:     {
425:         $this->rules->addRule($validator, $message, $arg);
426:         return $this;
427:     }
428: 
429: 
430:     /**
431:      * Adds a validation condition a returns new branch.
432:      * @param  mixed     condition type
433:      * @param  mixed     optional condition arguments
434:      * @return Rules      new branch
435:      */
436:     public function addCondition($validator, $value = NULL)
437:     {
438:         return $this->rules->addCondition($validator, $value);
439:     }
440: 
441: 
442:     /**
443:      * Adds a validation condition based on another control a returns new branch.
444:      * @param  IControl form control
445:      * @param  mixed      condition type
446:      * @param  mixed      optional condition arguments
447:      * @return Rules      new branch
448:      */
449:     public function addConditionOn(IControl $control, $validator, $value = NULL)
450:     {
451:         return $this->rules->addConditionOn($control, $validator, $value);
452:     }
453: 
454: 
455:     /**
456:      * @return Rules
457:      */
458:     public function getRules()
459:     {
460:         return $this->rules;
461:     }
462: 
463: 
464:     /**
465:      * Makes control mandatory.
466:      * @param  mixed  state or error message
467:      * @return static
468:      */
469:     public function setRequired($value = TRUE)
470:     {
471:         $this->rules->setRequired($value);
472:         return $this;
473:     }
474: 
475: 
476:     /**
477:      * Is control mandatory?
478:      * @return bool
479:      */
480:     public function isRequired()
481:     {
482:         return $this->rules->isRequired();
483:     }
484: 
485: 
486:     /**
487:      * Performs the server side validation.
488:      * @return void
489:      */
490:     public function validate()
491:     {
492:         if ($this->isDisabled()) {
493:             return;
494:         }
495:         $this->cleanErrors();
496:         $this->rules->validate();
497:     }
498: 
499: 
500:     /**
501:      * Adds error message to the list.
502:      * @param  string  error message
503:      * @return void
504:      */
505:     public function addError($message)
506:     {
507:         $this->errors[] = $message;
508:     }
509: 
510: 
511:     /**
512:      * Returns errors corresponding to control.
513:      * @return string
514:      */
515:     public function getError()
516:     {
517:         return $this->errors ? implode(' ', array_unique($this->errors)) : NULL;
518:     }
519: 
520: 
521:     /**
522:      * Returns errors corresponding to control.
523:      * @return array
524:      */
525:     public function getErrors()
526:     {
527:         return array_unique($this->errors);
528:     }
529: 
530: 
531:     /**
532:      * @return bool
533:      */
534:     public function hasErrors()
535:     {
536:         return (bool) $this->errors;
537:     }
538: 
539: 
540:     /**
541:      * @return void
542:      */
543:     public function cleanErrors()
544:     {
545:         $this->errors = [];
546:     }
547: 
548: 
549:     /**
550:      * Globally enables new required/optional behavior.
551:      * This method will be deprecated in next version.
552:      */
553:     public static function enableAutoOptionalMode()
554:     {
555:         self::$autoOptional = TRUE;
556:     }
557: 
558: 
559:     /********************* user data ****************d*g**/
560: 
561: 
562:     /**
563:      * Sets user-specific option.
564:      * @return static
565:      */
566:     public function setOption($key, $value)
567:     {
568:         if ($value === NULL) {
569:             unset($this->options[$key]);
570:         } else {
571:             $this->options[$key] = $value;
572:         }
573:         return $this;
574:     }
575: 
576: 
577:     /**
578:      * Returns user-specific option.
579:      * @return mixed
580:      */
581:     public function getOption($key, $default = NULL)
582:     {
583:         return isset($this->options[$key]) ? $this->options[$key] : $default;
584:     }
585: 
586: 
587:     /**
588:      * Returns user-specific options.
589:      * @return array
590:      */
591:     public function getOptions()
592:     {
593:         return $this->options;
594:     }
595: 
596: 
597:     /********************* extension methods ****************d*g**/
598: 
599: 
600:     public function __call($name, $args)
601:     {
602:         if ($callback = Nette\Utils\ObjectMixin::getExtensionMethod(get_class($this), $name)) {
603:             return Nette\Utils\Callback::invoke($callback, $this, ...$args);
604:         }
605:         return parent::__call($name, $args);
606:     }
607: 
608: 
609:     public static function extensionMethod($name, $callback = NULL)
610:     {
611:         if (strpos($name, '::') !== FALSE) { // back compatibility
612:             list(, $name) = explode('::', $name);
613:         }
614:         Nette\Utils\ObjectMixin::setExtensionMethod(get_called_class(), $name, $callback);
615:     }
616: 
617: }
618: 
Nette 2.4-20170119 API API documentation generated by ApiGen 2.8.0