nur-sery/nur_src/v/bs3/fo/Form.php

1053 lines
33 KiB
PHP

<?php
namespace nur\v\bs3\fo;
use ArrayAccess;
use Countable;
use nur\A;
use nur\b\coll\TArrayTools;
use nur\b\coll\TBaseArray;
use nur\b\coll\TGenericArray;
use nur\b\params\IParametrable;
use nur\b\params\Tparametrable1;
use nur\data\types\IType;
use nur\data\types\md_utils;
use nur\data\types\Metadata;
use nur\F;
use nur\msg;
use nur\v\al;
use nur\v\base\Alerter;
use nur\v\base\ComponentPrintable;
use nur\v\v;
use nur\v\vo;
class Form extends ComponentPrintable implements IParametrable, ArrayAccess, Countable {
use Tparametrable1, TBaseArray, TGenericArray, TArrayTools;
/** @return bool est-ce un formulaire de type "horizontal" par opposition à "inline" */
function HORIZONTAL(): bool {
return static::HORIZONTAL;
} const HORIZONTAL = false;
/** @return ?string classe pour les boutons submit en form horizontal */
function FGS_CLASS(): ?string { return null; }
/** @return ?string classe pour les labels en form horizontal */
function FGL_CLASS(): ?string { return null; }
/** @return ?string classe pour les contrôle en form horizontal */
function FGC_CLASS(): ?string { return null; }
function SHOW_HELP(): bool {
return static::SHOW_HELP;
} const SHOW_HELP = true;
/** @var ?string|?array classes spécifiques à ce formulaire */
const FORM_CLASS = null;
/** @var bool faut-il tenir compte du paramètre [autohide_label]? */
const ALLOW_AUTOHIDE_LABEL = false;
/** @var ?array schéma des données du formulaire */
const SCHEMA = null;
/** @var array[] schéma de la définition des paramètres de formulaire */
const PARAMS_SCHEMA = [
"key" => ["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;
$param["checked"] = $currentValue === $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 {
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 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();
}
}