["string", null, "nom de la clé dans le schéma"], "name" => ["?string", null, "nom du paramètre"], "default" => [null, null, "valeur par défaut du paramètre"], "value" => [null, null, "valeur du paramètre à forcer"], "label" => [null, null, "label du contrôle de formulaire"], "control" => ["?string", null, "classe de contrôle de formulaire à utiliser"], ]; /** @var ?array paramètres de formulaire à récupérer */ const PARAMS = null; /** @var ?array paramètres à exclure de la liste calculée automatiquement */ const PARAMS_EXCLUDES = null; /** * @var ?array paramètres de formulaire à récupérer. cette valeur est mergée * avec PARAMS. cela permet d'augmenter le paramétrage calculé automatiquement */ const PARAMS_OVERRIDES = null; const INVALID_MSG = null; /** @var ?array paramètres du bouton submit automatique */ const SUBMIT = "Envoyer"; const CONTROL_PREFIX = "\n"; const CONTROL_SUFFIX = null; const SUBMITTED_KEY = null; const CONTROL_CLASSES = [ "hidden" => ControlHidden::class, "fixed" => ControlFixed::class, "text" => ControlText::class, "number" => ControlNumber::class, "date" => ControlDate::class, "time" => ControlTime::class, "password" => ControlPassword::class, "select" => ControlSelect::class, "checkbox" => ControlCheckbox::class, "radiobutton" => ControlRadiobutton::class, "textarea" => ControlTextarea::class, "file" => ControlFile::class, "submit" => ControlSubmit::class, "reset" => ControlReset::class, ]; /** @var int type de contrôle: name, name+value ou name+value+checked */ const N = 1, NV = 2, NVC = 3; const CONTROL_TYPES = [ ControlHidden::class => [self::NV, null], ControlFixed::class => [self::NV, "label"], ControlText::class => [self::NV, "label"], ControlNumber::class => [self::NV, "label"], ControlDate::class => [self::NV, "label"], ControlTime::class => [self::NV, "label"], ControlPassword::class => [self::NV, "label"], ControlSelect::class => [self::NV, "label"], ControlCheckbox::class => [self::NVC, "text"], ControlRadiobutton::class => [self::NVC, "text"], ControlTextarea::class => [self::NV, "label"], ControlFile::class => [self::N, "label"], ControlSubmit::class => [self::NV, "submit"], ControlReset::class => [self::NV, "reset"], ]; const PARAMETRABLE_PARAMS_SCHEMA = [ "action" => ["?string", null, "url destination du formulaire"], "method" => ["?string", "get", "méthode du formulaire (post, get)"], "enctype" => ["?string", null, "type d'encodage du formulaire"], "upload" => ["bool", null, "ce formulaire est-il utilisé pour uploader des fichiers?"], "class" => ["?array", null, "classes CSS du formulaire"], "attrs" => ["?array", null, "attributs HTML supplémentaires"], "autohide_label" => ["bool", true, "faut-il cacher le label s'il y a le placeholder?"], "schema" => ["?array", null, "schéma des données du formulaire"], "params" => ["?array", null, "paramètres de formulaire à récupérer"], "params_excludes" => ["?array", null, "paramètres à exclure de la liste calculée automatiquement"], "params_overrides" => ["?array", null, "paramètres de formulaire à récupérer à merger avec [params]"], "alerter" => [Alerter::class, null, "instance utilisée pour afficher un message avant le bouton submit"], "invalid_msg" => ["?content", null, "message à afficher si le formulaire est invalide"], "submit" => ["?array", null, "paramètres du bouton submit automatique"], "submits" => ["?array", null, "boutons submit supplémentaires"], "autoadd_submit" => ["bool", true, "Faut-il rajouter le bouton submit automatique?"], "control_prefix" => [null, null, "valeur à afficher avant chaque contrôle"], "control_suffix" => [null, null, "valeur à afficher après chaque contrôle"], "submitted_key" => ["?string", null, "nom d'un champ du formulaire qui, s'il existe, indique que le formulaire a été soumis"], "autoload_params" => ["bool", false, "faut-il charger les paramètres de formulaire de suite?"], "autoprint" => ["bool", false, "faut-il afficher le formulaire de suite?"], ]; function __construct(?array $params=null) { self::set_parametrable_params_defaults($params, [ "schema" => static::SCHEMA, "params_exclude" => static::PARAMS_EXCLUDES, "params_overrides" => static::PARAMS_OVERRIDES, "params" => static::PARAMS, "invalid_msg" => q(static::INVALID_MSG), "submit" => A::with(static::SUBMIT), "control_prefix" => q(static::CONTROL_PREFIX), "control_suffix" => q(static::CONTROL_SUFFIX), "submitted_key" => static::SUBMITTED_KEY, ]); [$params, $attrs] = $this->splitParametrableParams($params); if ($attrs) A::merge($params["attrs"], $attrs); $this->initParametrableParams($params); if ($this->ppAutoloadParams) $this->loadParams(); if ($this->ppAutoprint) $this->print(); } /** @var ?string */ protected $ppAction; /** @var ?string */ protected $ppMethod; /** @var ?string */ protected $ppEnctype; function pp_setUpload(bool $upload=true): void { if ($upload) { $this->ppMethod = "post"; $this->ppEnctype = "multipart/form-data"; } } /** @var ?array */ protected $ppClass; /** @var ?array */ protected $ppAttrs; /** @var ?bool */ protected $ppAutohideLabel; function isAutohideLabel(): bool { return static::ALLOW_AUTOHIDE_LABEL && $this->ppAutohideLabel; } /** @var ?Metadata */ protected $md; function pp_setSchema(?array $schema): void { $md = null; if ($schema !== null) $md = new Metadata($schema); $this->md = $md; } private static $params_md; protected static function params_md(): Metadata { return md_utils::ensure_md(self::$params_md, self::PARAMS_SCHEMA); } protected static function params_ensure_schema(array &$params, ?Metadata $md=null): void { $params_md = self::params_md(); foreach ($params as $key => &$param) { $params_md->ensureSchema($param, $key); A::replace_n($param, "name", $key); if ($md !== null) { $sfield = A::get($md->getSfields(), $key); if ($sfield !== null) { A::replace_n($param, "default", $sfield["default"]); } } $controlClass = $param["control"]; if ($controlClass !== null) { $controlClass = A::get(static::CONTROL_CLASSES, $controlClass, $controlClass); $param["control"] = $controlClass; } }; unset($param); } /** @var ?array */ protected $ppParamsExcludes; /** @var ?array */ protected $ppParamsOverrides; /** @var ?array */ protected $ppParams; /** @var bool des valeurs ont-elle été attribuées à des paramètres? */ protected $paramsValuesSet; /** @var array fusion de $ppParams, $ppParamsExcludes et $ppParamsOverrides */ protected $params; /** @var ?Alerter */ protected $ppAlerter; function al(): ?Alerter { $al = $this->ppAlerter; if ($al === null) $al = al::get(); return $al; } /** @var array|string|null */ protected $ppInvalidMsg; /** @var ?array */ protected $ppSubmit; /** @var ?array */ protected $ppSubmits; /** @var bool */ protected $ppAutoaddSubmit; /** @var array contenu à afficher avant chaque élément de formulaire */ protected $ppControlPrefix; function getControlPrefix(): ?array { return $this->ppControlPrefix; } /** @var array contenu à afficher après chaque élément de formulaire */ protected $ppControlSuffix; function getControlSuffix(): ?array { return $this->ppControlSuffix; } /** @var bool */ protected $ppAutoprint; /** @var ?string */ protected $ppSubmittedKey; /** @var bool */ protected $ppAutoloadParams; protected function afterSetParametrableParams(array $modifiedKeys, ?Metadata $md=null): void { if (self::was_parametrable_param_modified($modifiedKeys, "submits") && !self::was_parametrable_param_modified($modifiedKeys, "autoadd_submit") ) { $this->ppAutoaddSubmit = false; } if (self::was_parametrable_param_modified($modifiedKeys, "params", "params_excludes", "params_overrides")) { $params = []; if ($this->ppParams !== null) { $paramsExcludes = $this->ppParamsExcludes; $index = 0; foreach ($this->ppParams as $key => $param) { if ($key === $index) { $index++; $key = $param; } if ($paramsExcludes === null || !in_array($key, $paramsExcludes)) { $params[$key] = $param; } } self::params_ensure_schema($params, $md); } $paramsOverrides = $this->ppParamsOverrides; if ($paramsOverrides !== null) { $oparams = []; $index = 0; foreach ($paramsOverrides as $key => $param) { if ($key === $index) { $index++; $key = $param; } $oparams[$key] = $param; } self::params_ensure_schema($oparams, $md); foreach ($oparams as $key => $param) { if (!A::has($params, $key)) { $params[$key] = $param; } else { A::merge_nn($params[$key], $param); } } } $this->paramsValuesSet = false; $this->params = $params; } } ############################################################################# ## Params private function resolveName($key, ?string &$name, &$value=null): bool { $params = $this->params; if (A::has($params, $key)) { $param = $params[$key]; $name = $param["name"]; $value = $param["default"]; return true; } else { $name = $key; $value = null; return false; } } private function resolveNameType($key, ?string $name=null): array { if ($name === null) $this->resolveName($key, $name); $md = $this->md; $type = $md !== null? $md->getType($key, false): null; return [$name, $type]; } function set($key, $value, ?string $name=null): self { $unset = false; /** @var IType $type */ [$name, $type] = $this->resolveNameType($key, $name); if ($type !== null) { if ($type->isUndef($value)) $unset = true; else $type->verifix($value, $this->results[$name]); } $this->paramsValuesSet = true; if ($unset) $this->_del($key); else $this->_set($key, $value); return $this; } protected function paramExists(string $name): bool { return F::has($name); } protected function paramGet($key, ?string $name, &$value): bool { /** @var IType $type */ [$name, $type] = $this->resolveNameType($key, $name); $value = F::get($name); if ($value === null) return false; if ($type !== null) { if ($type->isTrim()) $value = trim($value); if ($value === "") $type->verifixReplaceEmpty($value); if ($value === false) $type->verifixReplaceFalse($value); if ($value === null) $type->verifixReplaceNull($value); if ($type->isUndef($value)) return false; elseif ($value === null && !$type->isAllowNull()) return false; elseif ($value === false && !$type->isAllowFalse()) return false; elseif ($value === "" && !$type->isAllowEmpty()) $value = null; } return true; } protected $submitted; protected function checkSubmitted(): ?bool { $submittedKey = $this->ppSubmittedKey; if ($submittedKey !== null) { if ($this->paramGet($submittedKey, null, $value)) { return true; } } $submitted = null; foreach (A::keys($this->params) as $key) { if ($this->paramGet($key, null, $value)) { if ($submitted === null) $submitted = true; } else { $submitted = false; break; } } return $submitted; } /** tester si le formulaire a été soumis */ function isSubmitted(): bool { if ($this->submitted === null) { $this->submitted = boolval($this->checkSubmitted()); } return $this->submitted; } function setSubmitted(bool $submitted=true): void { $this->submitted = $submitted; } function loadParams(?array $keys=null): self { $md = $this->md; if ($this->ppParams === null && $md !== null) { $this->ppParams = $md->getKeys(); $this->afterSetParametrableParams(["params"], $md); } $params = $this->params; if ($keys === null && $params !== null) { $keys = array_keys($params); } $submitted = $this->submitted; if ($keys !== null) { $submitted = $this->checkSubmitted(); foreach ($keys as $key) { $this->resolveName($key, $name, $value); if ($this->paramExists($name)) { if ($submitted === null) $submitted = true; if ($this->paramGet($key, $name, $value)) { $this->set($key, $value, $name); } else { #XXX? #$this->del($key); } } elseif ($value !== null) { $this->set($key, $value, $name); } else { #XXX #$this->del($key); } } if ($submitted === null) $submitted = false; } $this->paramsValuesSet = true; $this->submitted = $submitted; return $this; } function autoloadParams(): self { if (!$this->paramsValuesSet) $this->loadParams(); return $this; } function resetParams(string ...$keys): void { foreach ($keys as $key) { $this->_del($key); } } /** retourner $params avec les $key traduits en $name */ function bp(?array $params=null): array { $result = []; if ($params !== null) { $index = 0; foreach ($params as $key => $value) { if ($key === $index) { $index++; $key = $value; $value = $this->get($key); } $this->resolveName($key, $name); $result[$name] = $value; } } return $result; } ############################################################################# ## Validation /** @var array */ protected $results; function setInvalid(string $key, ?string $message=null): void { if ($message === null) $message = "Cette valeur est invalide"; $this->resolveName($key, $name); $value = A::get($this->data, $key); $this->results[$name] = [ "valid" => false, "value" => $value, "error" => $message, "exception" => null, "orig" => $value, "parsed" => null, "remains" => null, ]; } function _getResult(string $name): ?array { return A::get($this->results, $name); } function getFirstInvalid(): ?string { if ($this->results !== null) { foreach ($this->results as $name => $result) { if (!$result["valid"]) return $name; } } return null; } function isValidForm(): bool { # si le formulaire n'a pas été soumis, il ne peut pas être valide $valid = false; if ($this->isSubmitted() && $this->results !== null) { foreach ($this->results as $result) { if (!$result["valid"]) return false; $valid = true; } } return $valid; } function isValid(string $key, ?array &$result=null): bool { $this->resolveName($key, $name); $result = A::get($this->results, $name); return $result === null || $result["valid"]; } ############################################################################# ## Form function printAlert(): void { $alerter = $this->ppAlerter; if ($alerter !== null) $alerter->print(); $invalidMsg = $this->ppInvalidMsg; if ($invalidMsg && $this->isSubmitted() && !$this->isValidForm()) { if ($alerter !== null) $alerter->pwarning($invalidMsg); else msg::warning($invalidMsg); } } function printStart(): void { vo::write($this->getStart()); } function getStart(): array { return v::start("form", [ "action" => $this->ppAction, "method" => $this->ppMethod, "enctype" => $this->ppEnctype, "class" => [static::FORM_CLASS, $this->ppClass], $this->ppAttrs, $this->form(), ]); } protected function form(): ?array { return null; } function printEnd(): void { vo::write($this->getEnd()); } function getEnd(): array { return v::end("form"); } ############################################################################# ## Controls /** @var ?array */ protected $hiddenControls; function addHiddenControl($control, ?string $name=null): self { A::set($this->hiddenControls, $name, $control); return $this; } /** @var ?array */ protected $controls; function addControl($control, ?string $name=null): self { A::set($this->controls, $name, $control); return $this; } protected function buildControl(?array $param, ?string $key=null, ?string $controlClass=null, ?array $params=null): array { if ($param === null) $param = A::get($this->params, $key); if ($param !== null) { [$key, $name, $default, $value, $label, $defaultControlClass, ] = A::getdels($param, array_keys(self::PARAMS_SCHEMA)); if ($controlClass === null && $defaultControlClass !== null) { $controlClass = $defaultControlClass; } } else { $name = $key; $default = $value = null; $label = null; if ($controlClass === null) $controlClass = ControlText::class; } $md = $this->md; $type = $md !== null? $md->getType($key, false): null; $sfields = $md !== null? $md->getSfields(): null; if ($controlClass === null) { $haveItems = A::has($param, "items") || A::has($param, "items_func"); $is2States = $type !== null && $type->is2States(); if ($haveItems) $controlClass = ControlSelect::class; elseif ($is2States) $controlClass = ControlCheckbox::class; else $controlClass = ControlText::class; } [$controlType, $firstKey] = A::get(static::CONTROL_TYPES, $controlClass, self::NV); if ($label === null && $md !== null) { $label = A::_pget($sfields, [$key, "title"]); } if ($label === null) $label = $key; if ($firstKey !== null) $param[$firstKey] = $label; switch ($controlType) { case self::NVC: $param["name"] = $name; if ($value === null) $value = $default; if ($value === null) $value = 1; $currentValue = $this->get($key); if ($type !== null) { #XXX la nécessité de formatter la valeur dépend-elle du contrôle utilisé?! $value = $type->format($value); $currentValue = $type->format($currentValue); } $param["value"] = $value; #XXX en attendant le formattage ci-dessus, forcer la format texte pour que # la comparaison puisse se faire $param["checked"] = strval($currentValue) === strval($value); break; case self::NV: if ($value === null) $value = $this->get($key, $default); if ($type !== null) $value = $type->format($value); $param["value"] = $value; case self::N: $param["name"] = $name; } if ($params === null) $params = $param; else A::update_n($params, $param); return [new $controlClass($this, $params), $name]; } private function _prepareControls(): ?array { if ($this->params === null) $this->loadParams(); A::ensure_array($this->controls); return $this->params; } function autoaddControl(string $key): self { $params = $this->_prepareControls(); if ($key == "") { # submit $this->addSubmit(null, $this->ppSubmit); } elseif (A::has($this->ppSubmits, $key)) { $submit = $this->ppSubmits[$key]; A::replace_n($submit, "id", $key); $this->addSubmit(null, $submit); } else { $param = A::get($params, $key); if ($param !== null) { [$control, $name] = $this->buildControl($param); $this->addControl($control, $name); } } return $this; } function autoaddControls(?bool $autoaddSubmit=null): self { $params = $this->_prepareControls(); if ($params !== null) { foreach ($params as $param) { [$control, $name] = $this->buildControl($param); if (A::has($this->hiddenControls, $name)) continue; if (A::has($this->controls, $name)) continue; $this->addControl($control, $name); } } if ($autoaddSubmit === null) $autoaddSubmit = $this->ppAutoaddSubmit; if ($autoaddSubmit && !A::has($this->controls, "")) { $this->addSubmit(null, $this->ppSubmit); } $submits = $this->ppSubmits; if ($submits !== null) { foreach ($submits as $key => $submit) { if (!A::has($this->controls, $key)) { A::replace_n($submit, "id", $key); $this->addSubmit(null, $submit); } } } return $this; } function printControls(): void { if ($this->controls === null) $this->autoaddControls(); vo::write($this->hiddenControls); vo::write($this->controls); } protected function fixControlParams(?array &$params): void { } protected function fixControl(Control $control): Control { return $control; } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # section /** @var Section */ protected $section; function startSection(?array $params=null): void { } function endSection(): void { } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # group /** @var Group */ protected $group; function startGroup(?array $params=null): void { } function endGroup(): void { } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # title function title($title, ?array $params=null): ControlTitle { A::set_nz($params, "title", $title); $this->fixControlParams($params); return new ControlTitle($this, $params); } function addTitle($title, ?array $params=null): self { $this->addControl($this->title($title, $params)); return $this; } function printTitle($title, ?array $params=null): void { vo::write($this->title($title, $params)); } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # hidden function hidden(string $name, $value, ?array $params=null): ControlHidden { A::set_nz($params, "name", $name); A::set_nz($params, "value", $value); return new ControlHidden($this, $params); } function addHidden(string $name, $value, ?array $params=null): self { $this->addHiddenControl($this->hidden($name, $value, $params), $name); return $this; } function autoaddHidden(string $key, ?array $params=null): self { $this->addHiddenControl(...$this->buildControl(null, $key, ControlHidden::class, $params)); return $this; } function printHidden(string $name, $value, ?array $params=null): void { vo::write($this->hidden($name, $value, $params)); } function hiddens(?array $values, ?array $names=null): array { if ($values === null) return []; if ($names === null) $names = array_keys($values); $vs = []; foreach ($names as $name) { $value = A::get($values, $name); $vs[] = $this->hidden($name, $value); } return $vs; } function addHiddens(?array $values, ?array $names=null): self { if ($values !== null) { if ($names === null) $names = array_keys($values); foreach ($names as $name) { $value = A::get($values, $name); $this->addHiddenControl($this->hidden($name, $value), $name); } } return $this; } function printHiddens(?array $values, ?array $names=null): void { vo::write($this->hiddens($values, $names)); } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # fixed function fixed($label, string $name, $value, ?array $params=null): ControlFixed { A::set_nz($params, "label", $label); A::set_nz($params, "name", $name); A::set_nz($params, "value", $value); $this->fixControlParams($params); return $this->fixControl(new ControlFixed($this, $params)); } function addFixed($label, string $name, $value, ?array $params=null): self { $this->addControl($this->fixed($label, $name, $value, $params), $name); return $this; } function autoaddFixed(string $key, ?array $params=null): self { $this->addControl(...$this->buildControl(null, $key, ControlFixed::class, $params)); return $this; } function printFixed($label, string $name, $value, ?array $params=null): void { vo::write($this->fixed($label, $name, $value, $params)); } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # input function text($label, string $name, $value, ?array $params=null): ControlText { A::set_nz($params, "label", $label); A::set_nz($params, "name", $name); A::set_nz($params, "value", $value); $this->fixControlParams($params); return $this->fixControl(new ControlText($this, $params)); } function addText($label, string $name, $value, ?array $params=null): self { $this->addControl($this->text($label, $name, $value, $params), $name); return $this; } function autoaddText(string $key, ?array $params=null): self { $this->addControl(...$this->buildControl(null, $key, ControlText::class, $params)); return $this; } function printText($label, string $name, $value, ?array $params=null): void { vo::write($this->text($label, $name, $value, $params)); } function password($label, string $name, $value, ?array $params=null): ControlPassword { A::set_nz($params, "label", $label); A::set_nz($params, "name", $name); A::set_nz($params, "value", $value); $this->fixControlParams($params); return $this->fixControl(new ControlPassword($this, $params)); } function addPassword($label, string $name, $value, ?array $params=null): self { $this->addControl($this->password($label, $name, $value, $params), $name); return $this; } function autoaddPassword(string $key, ?array $params=null): self { $this->addControl(...$this->buildControl(null, $key, ControlPassword::class, $params)); return $this; } function printPassword($label, string $name, $value, ?array $params=null): void { vo::write($this->password($label, $name, $value, $params)); } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # select function select($label, string $name, $value, ?array $params=null): ControlSelect { A::set_nz($params, "label", $label); A::set_nz($params, "name", $name); A::set_nz($params, "value", $value); $this->fixControlParams($params); return $this->fixControl(new ControlSelect($this, $params)); } function addSelect($label, string $name, $value, ?array $params=null): self { $this->addControl($this->select($label, $name, $value, $params), $name); return $this; } function autoaddSelect(string $key, ?array $params=null): self { $this->addControl(...$this->buildControl(null, $key, ControlSelect::class, $params)); return $this; } function printSelect($label, string $name, $value, ?array $params=null): void { vo::write($this->select($label, $name, $value, $params)); } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # checkbox function checkbox($text, string $name, $value, ?bool $checked=null, ?array $params=null): ControlCheckbox { A::set_nz($params, "text", $text); A::set_nz($params, "name", $name); A::set_nz($params, "value", $value); A::set_nz($params, "checked", $checked); $this->fixControlParams($params); return $this->fixControl(new ControlCheckbox($this, $params)); } function addCheckbox($text, string $name, $value, ?bool $checked=null, ?array $params=null): self { $this->addControl($this->checkbox($text, $name, $value, $checked, $params), $name); return $this; } function autoaddCheckbox(string $key, ?array $params=null): self { $this->addControl(...$this->buildControl(null, $key, ControlCheckbox::class, $params)); return $this; } function printCheckbox($text, string $name, $value, ?bool $checked=null, ?array $params=null): void { vo::write($this->checkbox($text, $name, $value, $checked, $params)); } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # radiobutton function radiobutton($text, string $name, $value, ?bool $checked=null, ?array $params=null): ControlRadiobutton { A::set_nz($params, "text", $text); A::set_nz($params, "name", $name); A::set_nz($params, "value", $value); A::set_nz($params, "checked", $checked); $this->fixControlParams($params); return $this->fixControl(new ControlRadiobutton($this, $params)); } function addRadiobutton($text, string $name, $value, ?bool $checked=null, ?array $params=null): self { $this->addControl($this->radiobutton($text, $name, $value, $checked, $params), $name); return $this; } function autoaddRadiobutton(string $key, ?array $params=null): self { $this->addControl(...$this->buildControl(null, $key, ControlRadiobutton::class, $params)); return $this; } function printRadiobutton($text, string $name, $value, ?bool $checked=null, ?array $params=null): void { vo::write($this->radiobutton($text, $name, $value, $checked, $params)); } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # textarea function textarea($label, string $name, $value, ?array $params=null): ControlTextarea { A::set_nz($params, "label", $label); A::set_nz($params, "name", $name); A::set_nz($params, "value", $value); $this->fixControlParams($params); return $this->fixControl(new ControlTextarea($this, $params)); } function addTextarea($label, string $name, $value, ?array $params=null): self { $this->addControl($this->textarea($label, $name, $value, $params), $name); return $this; } function autoaddTextarea(string $key, ?array $params=null): self { $this->addControl(...$this->buildControl(null, $key, ControlTextarea::class, $params)); return $this; } function printTextarea($label, string $name, $value, ?array $params=null): void { vo::write($this->textarea($label, $name, $value, $params)); } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # file function file($label, string $name, ?array $params=null): ControlFile { A::set_nz($params, "label", $label); A::set_nz($params, "name", $name); $this->fixControlParams($params); return $this->fixControl(new ControlFile($this, $params)); } function addFile($label, string $name, ?array $params=null): self { $this->addControl($this->file($label, $name, $params), $name); return $this; } function autoaddFile(string $key, ?array $params=null): self { $this->addControl(...$this->buildControl(null, $key, ControlFile::class, $params)); return $this; } function printFile($label, string $name, ?array $params=null): void { vo::write($this->file($label, $name, $params)); } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # submit function submit($submit, ?array $params=null): ControlSubmit { A::set_nz($params, "submit", $submit); $this->fixControlParams($params); return $this->fixControl(new ControlSubmit($this, $params)); } function addSubmit($submit, ?array $params=null): self { $name = A::get($params, "id"); if ($name === null) A::get($params, "name"); if ($name === null) $name = ""; $this->addControl($this->submit($submit, $params), $name); return $this; } function autoaddSubmit(string $key, ?array $params=null): self { $this->addControl(...$this->buildControl(null, $key, ControlSubmit::class, $params)); return $this; } function printSubmit($submit, ?array $params=null): void { vo::write($this->submit($submit, $params)); } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # reset function reset($reset, ?array $params=null): ControlReset { A::set_nz($params, "reset", $reset); $this->fixControlParams($params); return $this->fixControl(new ControlReset($this, $params)); } function addReset($reset, ?array $params=null): self { $name = A::get($params, "name", ""); $this->addControl($this->reset($reset, $params), $name); return $this; } function autoaddReset(string $key, ?array $params=null): self { $this->addControl(...$this->buildControl(null, $key, ControlReset::class, $params)); return $this; } function printReset($reset, ?array $params=null): void { vo::write($this->reset($reset, $params)); } ############################################################################# function print(): void { $this->autoloadParams(); $this->printAlert(); $this->printStart(); $this->printControls(); $this->printEnd(); } }