%PDF- %PDF-
Direktori : /www/varak.net/losik.varak.net/vendor/nette/forms/src/Forms/Controls/ |
Current File : /www/varak.net/losik.varak.net/vendor/nette/forms/src/Forms/Controls/BaseControl.php |
<?php /** * This file is part of the Nette Framework (https://nette.org) * Copyright (c) 2004 David Grudl (https://davidgrudl.com) */ declare(strict_types=1); namespace Nette\Forms\Controls; use Nette; use Nette\Forms\Control; use Nette\Forms\Form; use Nette\Forms\Rules; use Nette\Utils\Html; /** * Base class that implements the basic functionality common to form controls. * * @property-read Form $form * @property-read string $htmlName * @property mixed $htmlId * @property mixed $value * @property string|object $caption * @property bool $disabled * @property bool $omitted * @property-read Html $control * @property-read Html $label * @property-read Html $controlPrototype * @property-read Html $labelPrototype * @property bool $required * @property-read bool $filled * @property-read array $errors * @property-read array $options * @property-read string $error */ abstract class BaseControl extends Nette\ComponentModel\Component implements Control { /** @var string */ public static $idMask = 'frm-%s'; /** @var mixed current control value */ protected $value; /** @var Html control element template */ protected $control; /** @var Html label element template */ protected $label; /** @var bool|bool[] */ protected $disabled = false; /** @var callable[][] extension methods */ private static $extMethods = []; /** @var string|object textual caption or label */ private $caption; /** @var array */ private $errors = []; /** @var bool|null */ private $omitted; /** @var Rules */ private $rules; /** @var Nette\Localization\Translator|bool|null */ private $translator = true; // means autodetect /** @var array user options */ private $options = []; /** * @param string|object $caption */ public function __construct($caption = null) { $this->control = Html::el('input', ['type' => null, 'name' => null]); $this->label = Html::el('label'); $this->caption = $caption; $this->rules = new Rules($this); $this->setValue(null); $this->monitor(Form::class, function (Form $form): void { if (!$this->isDisabled() && $form->isAnchored() && $form->isSubmitted()) { $this->loadHttpData(); } }); } /** * Sets textual caption or label. * @param object|string $caption * @return static */ public function setCaption($caption) { $this->caption = $caption; return $this; } /** @return object|string */ public function getCaption() { return $this->caption; } /** * Returns form. */ public function getForm(bool $throw = true): ?Form { return $this->lookup(Form::class, $throw); } /** * Loads HTTP data. */ public function loadHttpData(): void { $this->setValue($this->getHttpData(Form::DataText)); } /** * Loads HTTP data. * @return mixed */ protected function getHttpData($type, ?string $htmlTail = null) { return $this->getForm()->getHttpData($type, $this->getHtmlName() . $htmlTail); } /** * Returns HTML name of control. */ public function getHtmlName(): string { return $this->control->name ?? Nette\Forms\Helpers::generateHtmlName($this->lookupPath(Form::class)); } /********************* interface Control ****************d*g**/ /** * Sets control's value. * @return static * @internal */ public function setValue($value) { $this->value = $value; return $this; } /** * Returns control's value. * @return mixed */ public function getValue() { return $this->value; } /** * Is control filled? */ public function isFilled(): bool { $value = $this->getValue(); return $value !== null && $value !== [] && $value !== ''; } /** * Sets control's default value. * @return static */ public function setDefaultValue($value) { $form = $this->getForm(false); if ($this->isDisabled() || !$form || !$form->isAnchored() || !$form->isSubmitted()) { $this->setValue($value); } return $this; } /** * Disables or enables control. * @param bool $value * @return static */ public function setDisabled($value = true) { if ($this->disabled = (bool) $value) { $this->setValue(null); } elseif (($form = $this->getForm(false)) && $form->isAnchored() && $form->isSubmitted()) { $this->loadHttpData(); } return $this; } /** * Is control disabled? */ public function isDisabled(): bool { return $this->disabled === true; } /** * Sets whether control value is excluded from $form->getValues() result. * @return static */ public function setOmitted(bool $value = true) { $this->omitted = $value; return $this; } /** * Is control value excluded from $form->getValues() result? */ public function isOmitted(): bool { return $this->omitted || ($this->isDisabled() && $this->omitted === null); } /********************* rendering ****************d*g**/ /** * Generates control's HTML element. * @return Html|string */ public function getControl() { $this->setOption('rendered', true); $el = clone $this->control; return $el->addAttributes([ 'name' => $this->getHtmlName(), 'id' => $this->getHtmlId(), 'required' => $this->isRequired(), 'disabled' => $this->isDisabled(), 'data-nette-rules' => Nette\Forms\Helpers::exportRules($this->rules) ?: null, ]); } /** * Generates label's HTML element. * @param string|object $caption * @return Html|string|null */ public function getLabel($caption = null) { $label = clone $this->label; $label->for = $this->getHtmlId(); $caption = $caption ?? $this->caption; $translator = $this->getForm()->getTranslator(); $label->setText($translator && !$caption instanceof Nette\HtmlStringable ? $translator->translate($caption) : $caption); return $label; } public function getControlPart(): ?Html { return $this->getControl(); } public function getLabelPart(): ?Html { return $this->getLabel(); } /** * Returns control's HTML element template. */ public function getControlPrototype(): Html { return $this->control; } /** * Returns label's HTML element template. */ public function getLabelPrototype(): Html { return $this->label; } /** * Changes control's HTML id. * @param string|bool|null $id * @return static */ public function setHtmlId($id) { $this->control->id = $id; return $this; } /** * Returns control's HTML id. * @return mixed */ public function getHtmlId() { if (!isset($this->control->id)) { $form = $this->getForm(); $prefix = $form instanceof Nette\Application\UI\Form || $form->getName() === null ? '' : $form->getName() . '-'; $this->control->id = sprintf(self::$idMask, $prefix . $this->lookupPath()); } return $this->control->id; } /** * Changes control's HTML attribute. * @return static */ public function setHtmlAttribute(string $name, $value = true) { $this->control->$name = $value; if ( $name === 'name' && ($form = $this->getForm(false)) && !$this->isDisabled() && $form->isAnchored() && $form->isSubmitted() ) { $this->loadHttpData(); } return $this; } /** * @deprecated use setHtmlAttribute() * @return static */ public function setAttribute(string $name, $value = true) { return $this->setHtmlAttribute($name, $value); } /********************* translator ****************d*g**/ /** * Sets translate adapter. * @return static */ public function setTranslator(?Nette\Localization\Translator $translator) { $this->translator = $translator; return $this; } /** * Returns translate adapter. */ public function getTranslator(): ?Nette\Localization\Translator { if ($this->translator === true) { return $this->getForm(false) ? $this->getForm()->getTranslator() : null; } return $this->translator; } /** * Returns translated string. * @return mixed */ public function translate($value, ...$parameters) { if ($translator = $this->getTranslator()) { $tmp = is_array($value) ? [&$value] : [[&$value]]; foreach ($tmp[0] as &$v) { if ($v != null && !$v instanceof Nette\HtmlStringable) { // intentionally == $v = $translator->translate($v, ...$parameters); } } } return $value; } /********************* rules ****************d*g**/ /** * Adds a validation rule. * @param callable|string $validator * @param string|object $errorMessage * @return static */ public function addRule($validator, $errorMessage = null, $arg = null) { $this->rules->addRule($validator, $errorMessage, $arg); return $this; } /** * Adds a validation condition a returns new branch. */ public function addCondition($validator, $value = null): Rules { return $this->rules->addCondition($validator, $value); } /** * Adds a validation condition based on another control a returns new branch. */ public function addConditionOn(Control $control, $validator, $value = null): Rules { return $this->rules->addConditionOn($control, $validator, $value); } /** * Adds a input filter callback. * @return static */ public function addFilter(callable $filter) { $this->getRules()->addFilter($filter); return $this; } public function getRules(): Rules { return $this->rules; } /** * Makes control mandatory. * @param bool|string|object $value * @return static */ public function setRequired($value = true) { $this->rules->setRequired($value); return $this; } /** * Is control mandatory? */ public function isRequired(): bool { return $this->rules->isRequired(); } /** * Performs the server side validation. */ public function validate(): void { if ($this->isDisabled()) { return; } $this->cleanErrors(); $this->rules->validate(); } /** * Adds error message to the list. * @param string|object $message */ public function addError($message, bool $translate = true): void { $this->errors[] = $translate ? $this->translate($message) : $message; } /** * Returns errors corresponding to control. */ public function getError(): ?string { return $this->errors ? implode(' ', array_unique($this->errors)) : null; } /** * Returns errors corresponding to control. */ public function getErrors(): array { return array_unique($this->errors); } public function hasErrors(): bool { return (bool) $this->errors; } public function cleanErrors(): void { $this->errors = []; } /********************* user data ****************d*g**/ /** * Sets user-specific option. * @return static */ public function setOption($key, $value) { if ($value === null) { unset($this->options[$key]); } else { $this->options[$key] = $value; } return $this; } /** * Returns user-specific option. * @return mixed */ public function getOption($key) { if (func_num_args() > 1) { $default = func_get_arg(1); } return $this->options[$key] ?? $default ?? null; } /** * Returns user-specific options. */ public function getOptions(): array { return $this->options; } /********************* extension methods ****************d*g**/ public function __call(string $name, array $args) { $class = static::class; do { if (isset(self::$extMethods[$name][$class])) { return (self::$extMethods[$name][$class])($this, ...$args); } $class = get_parent_class($class); } while ($class); return parent::__call($name, $args); } public static function extensionMethod(string $name, /*callable*/ $callback): void { if (strpos($name, '::') !== false) { // back compatibility [, $name] = explode('::', $name); } self::$extMethods[$name][static::class] = $callback; } }