modifs.mineures sans commentaires

This commit is contained in:
Jephté Clain 2025-03-19 06:38:19 +04:00
parent d148850c12
commit 3608b02749
13 changed files with 186 additions and 136 deletions

View File

@ -2,9 +2,6 @@
namespace nur\sery\wip\schema; namespace nur\sery\wip\schema;
use IteratorAggregate; use IteratorAggregate;
use nur\sery\wip\schema\_assoc\AssocResult;
use nur\sery\wip\schema\_list\ListResult;
use nur\sery\wip\schema\_scalar\ScalarResult;
use Throwable; use Throwable;
/** /**
@ -37,10 +34,6 @@ abstract class Result implements IteratorAggregate {
$this->reset(); $this->reset();
} }
function isAssoc(?AssocResult &$result=null): bool { return false; }
function isList(?ListResult &$result=null): bool { return false; }
function isScalar(?ScalarResult &$result=null): bool { return false; }
/** /**
* Obtenir la liste des clés valides pour les valeurs accessibles via cet * Obtenir la liste des clés valides pour les valeurs accessibles via cet
* objet * objet

View File

@ -98,18 +98,18 @@ abstract class Schema implements ArrayAccess {
return false; return false;
} }
protected static function _normalize_definition(&$definition, $definitionKey=null): void { protected static function _normalize_definition(&$definition, $definitionKey=null, ?array $natureMetaschema=null): void {
if (!is_array($definition)) $definition = [$definition]; if (!is_array($definition)) $definition = [$definition];
# s'assurer que toutes les clés existent avec leur valeur par défaut # s'assurer que toutes les clés existent avec leur valeur par défaut
$index = 0; $index = 0;
foreach (array_keys(ref_schema::SCALAR_METASCHEMA) as $key) { foreach (array_keys(ref_schema::VALUE_METASCHEMA) as $key) {
if (!array_key_exists($key, $definition)) { if (!array_key_exists($key, $definition)) {
if (array_key_exists($index, $definition)) { if (array_key_exists($index, $definition)) {
$definition[$key] = $definition[$index]; $definition[$key] = $definition[$index];
unset($definition[$index]); unset($definition[$index]);
$index++; $index++;
} else { } else {
$definition[$key] = ref_schema::SCALAR_METASCHEMA[$key][1]; $definition[$key] = ref_schema::VALUE_METASCHEMA[$key][1];
} }
} }
} }
@ -161,6 +161,12 @@ abstract class Schema implements ArrayAccess {
# nature # nature
$nature = $definition[""]; $nature = $definition[""];
tarray::ensure_array($nature); tarray::ensure_array($nature);
$natureMetaschema ??= ref_schema::NATURE_METASCHEMA;
foreach (array_keys($natureMetaschema) as $key) {
if (!array_key_exists($key, $nature)) {
$nature[$key] = $natureMetaschema[$key][1];
}
}
$definition[""] = $nature; $definition[""] = $nature;
# name, pkey, header # name, pkey, header
$name = $definition["name"]; $name = $definition["name"];

View File

@ -2,8 +2,8 @@
* faire PropertyAccess * faire PropertyAccess
* si l'argument de Input() est un objet, utiliser PropertyAccess au lieu de KeyAccess * si l'argument de Input() est un objet, utiliser PropertyAccess au lieu de KeyAccess
* possibilité de forcer l'un ou l'autre * possibilité de forcer l'un ou l'autre (paramètre type=value|array|object)
* ensureKeys() et orderKeys() se fait au niveau de access * ensureKeys() et orderKeys() se fait au niveau de access (ou input?)
* valeurs composite/computed * valeurs composite/computed
* analyse / vérification de la valeur complète après calcul du résultat, si * analyse / vérification de la valeur complète après calcul du résultat, si

View File

@ -23,14 +23,17 @@ abstract class Wrapper implements ArrayAccess, IteratorAggregate {
$this->context->resetParams($params); $this->context->resetParams($params);
} }
protected function afterModify(?array $params, bool $reset=true): void { protected function resetContext($resetSelectedKey): void {
$context = $this->context; $context = $this->context;
if ($reset) { $context->type = null;
$context->type = null; $context->result->reset();
$context->result->reset(); $context->analyzed = false;
$context->analyzed = false; $context->normalized = false;
$context->normalized = false; }
}
protected function afterModify(?array $params, $resetSelectedKey=false): void {
$context = $this->context;
$this->resetContext($resetSelectedKey);
if ($params["analyze"] ?? $context->analyze) { if ($params["analyze"] ?? $context->analyze) {
$this->analyze($params); $this->analyze($params);
} }
@ -51,7 +54,15 @@ abstract class Wrapper implements ArrayAccess, IteratorAggregate {
* @param ?array $params paramètres spécifique à cet appel, qui peuvent être * @param ?array $params paramètres spécifique à cet appel, qui peuvent être
* différent des paramètres par défaut * différent des paramètres par défaut
*/ */
abstract function reset(&$value, $valueKey=null, ?array $params=null): self; function reset(&$value, $valueKey=null, ?array $params=null): Wrapper {
$context = $this->context;
if ($value instanceof Input) $input = $value;
else $input = $this->newInput($value);
$context->input = $input;
$context->valueKey = $valueKey;
$this->afterModify($params, true);
return $this;
}
/** analyser la valeur */ /** analyser la valeur */
abstract protected function _analyze(?array $params): int; abstract protected function _analyze(?array $params): int;
@ -119,50 +130,50 @@ abstract class Wrapper implements ArrayAccess, IteratorAggregate {
* cette fonction doit être appelée après {@link set()} ou {@link unset()} et * cette fonction doit être appelée après {@link set()} ou {@link unset()} et
* après que le wrapper aie été sélectionné avec {@link select()} * après que le wrapper aie été sélectionné avec {@link select()}
*/ */
function getResult(): Result { function getResult($key=false): Result {
return $this->context->result; return $this->context->result;
} }
/** retourner true si la valeur existe */ /** retourner true si la valeur existe */
function isPresent(): bool { function isPresent($key=false): bool {
return $this->context->result->present; return $this->getResult()->present;
} }
/** retourner le type associé à la valeur */ /** retourner le type associé à la valeur */
function getType(): IType { function getType($key=false): IType {
return $this->context->type; return $this->context->type;
} }
/** retourner true si la valeur est disponible */ /** retourner true si la valeur est disponible */
function isAvailable(): bool { function isAvailable($key=false): bool {
return $this->context->result->available; return $this->getResult()->available;
} }
/** retourner true si la valeur est valide */ /** retourner true si la valeur est valide */
function isValid(): bool { function isValid($key=false): bool {
return $this->context->result->valid; return $this->getResult()->valid;
} }
/** retourner true si la valeur est dans sa forme normalisée */ /** retourner true si la valeur est dans sa forme normalisée */
function isNormalized(): bool { function isNormalized($key=false): bool {
return $this->context->result->normalized; return $this->getResult()->normalized;
} }
function get($default=null) { function get($default=null, $key=false) {
$context = $this->context; $context = $this->context;
if ($context->result->available) return $context->input->get($context->valueKey); if (!$context->result->available) return $default;
else return $default; return $context->input->get($context->valueKey);
} }
function set($value, ?array $params=null): self { function set($value, ?array $params=null, $key=false): self {
$context = $this->context; $context = $this->context;
$context->input->set($value, $context->valueKey); $context->input->set($value, $context->valueKey);
$this->afterModify($params); $this->afterModify($params);
return $this; return $this;
} }
function unset(?array $params=null): self { function unset(?array $params=null, $key=false): self {
$context = $this->context; $context = $this->context;
$context->input->unset($context->valueKey); $context->input->unset($context->valueKey);
$this->afterModify($params); $this->afterModify($params);
@ -186,7 +197,7 @@ abstract class Wrapper implements ArrayAccess, IteratorAggregate {
} }
/** formatter la valeur pour affichage */ /** formatter la valeur pour affichage */
function format($format=null): string { function format($format=null, $key=false): string {
return $this->_format($this->context, $format); return $this->_format($this->context, $format);
} }
@ -198,14 +209,14 @@ abstract class Wrapper implements ArrayAccess, IteratorAggregate {
} }
function offsetGet($offset) { function offsetGet($offset) {
return $this->select($offset)->get(); return $this->get(null, $offset);
} }
function offsetSet($offset, $value): void { function offsetSet($offset, $value): void {
$this->select($offset)->set($value); $this->set($value, null, $offset);
} }
function offsetUnset($offset): void { function offsetUnset($offset): void {
$this->select($offset)->unset(); $this->unset(null, $offset);
} }
} }

View File

@ -12,6 +12,7 @@ class WrapperContext {
$this->valueKey = $valueKey; $this->valueKey = $valueKey;
$this->origValue = null; $this->origValue = null;
$this->value = null; $this->value = null;
$this->selectedKey = null;
$this->type = null; $this->type = null;
$this->result = null; $this->result = null;
} }

View File

@ -1,50 +0,0 @@
<?php
namespace nur\sery\wip\schema\_assoc;
use nulib\ValueException;
use nur\sery\wip\schema\Result;
class AssocResult extends Result {
function __construct(AssocWrapperContext $context) {
$this->context = $context;
parent::__construct();
}
function isAssoc(?AssocResult &$result=null): bool { $result = $this; return true;}
protected AssocWrapperContext $context;
function getKeys(): array {
return $this->context->keys;
}
protected Result $result;
function select($key): AssocResult {
$context = $this->context;
if ($key === null) {
$this->result = $context->arrayResult;
return $this;
}
$wrapper = $context->keyWrappers[$key] ?? null;
if ($wrapper === null) throw ValueException::invalid_key($key);
$this->result = $wrapper->getResult();
return $this;
}
function reset(): void {
$context = $this->context;
$context->arrayResult->reset();
foreach ($context->keyWrappers as $wrapper) {
$wrapper->getResult()->reset();
}
}
function __get(string $name) {
return $this->result[$name];
}
function __set(string $name, $value): void {
$this->result[$name] = $value;
}
}

View File

@ -11,8 +11,11 @@ use nur\sery\wip\schema\Wrapper;
* Class AssocSchema * Class AssocSchema
*/ */
class AssocSchema extends Schema { class AssocSchema extends Schema {
/** @var array meta-schema d'un schéma de nature tableau associatif */ //const METASCHEMA = ref_schema::VALUE_METASCHEMA;
const METASCHEMA = ref_schema::ASSOC_METASCHEMA; //const NATURE_METASCHEMA = [
// ...ref_schema::NATURE_METASCHEMA,
// ...ref_schema::ASSOC_NATURE_METASCHEMA,
//];
/** /**
* indiquer si $definition est une définition de schéma de nature tableau * indiquer si $definition est une définition de schéma de nature tableau
@ -37,7 +40,8 @@ class AssocSchema extends Schema {
"schema" => $definition, "schema" => $definition,
]; ];
} }
self::_normalize_definition($definition, $definitionKey); $natureMetaschema = array_merge(ref_schema::NATURE_METASCHEMA, ref_schema::ASSOC_NATURE_METASCHEMA);
self::_normalize_definition($definition, $definitionKey, $natureMetaschema);
self::_ensure_nature($definition, "assoc", "array"); self::_ensure_nature($definition, "assoc", "array");
return $definition; return $definition;
} }
@ -83,9 +87,9 @@ class AssocSchema extends Schema {
function getWrapper(&$value=null, $valueKey=null, ?array $params=null, ?Wrapper &$wrapper=null): AssocWrapper { function getWrapper(&$value=null, $valueKey=null, ?array $params=null, ?Wrapper &$wrapper=null): AssocWrapper {
# si pas de valeur ni de wrapper, pas de vérification et donc pas d'exception # si pas de valeur ni de wrapper, pas de vérification et donc pas d'exception
# cf le code similaire dans ScalarWrapper::__construct() # cf le code similaire dans ScalarWrapper::__construct()
$verifix = $value !== null || $wrapper !== null; $dontNormalize = $value === null && $wrapper === null;
if (!($wrapper instanceof AssocWrapper)) $wrapper = $this->newWrapper(); if (!($wrapper instanceof AssocWrapper)) $wrapper = $this->newWrapper();
if ($params !== null) $wrapper->resetParams($params); if ($params !== null) $wrapper->resetParams($params);
return $wrapper->reset($value, $valueKey, $verifix); return $wrapper->reset($value, $valueKey, $dontNormalize? ["normalize" => false]: null);
} }
} }

View File

@ -4,12 +4,13 @@ namespace nur\sery\wip\schema\_assoc;
use nulib\ValueException; use nulib\ValueException;
use nur\sery\wip\schema\_scalar\ScalarResult; use nur\sery\wip\schema\_scalar\ScalarResult;
use nur\sery\wip\schema\input\Input; use nur\sery\wip\schema\input\Input;
use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\types\IType; use nur\sery\wip\schema\types\IType;
use nur\sery\wip\schema\Wrapper; use nur\sery\wip\schema\Wrapper;
use nur\sery\wip\schema\WrapperContext; use nur\sery\wip\schema\WrapperContext;
class AssocWrapper extends Wrapper { class AssocWrapper extends Wrapper {
function __construct(AssocSchema $schema, &$array=null, $arrayKey=null, ?array $params=null) { function __construct(AssocSchema $schema, &$value=null, $valueKey=null, ?array $params=null) {
$keys = $schema->getKeys(); $keys = $schema->getKeys();
$keyTypes = []; $keyTypes = [];
$keyWrappers = []; $keyWrappers = [];
@ -22,16 +23,17 @@ class AssocWrapper extends Wrapper {
$context->keys = $keys; $context->keys = $keys;
$context->keyTypes = $keyTypes; $context->keyTypes = $keyTypes;
$context->keyWrappers = $keyWrappers; $context->keyWrappers = $keyWrappers;
$context->result = new AssocResult($context); $context->result = $context->arrayResult;
$throw = $context->throw; # calculer manuellemet throw ici parce que WrapperContext le met à true par
if ($array !== null && $throw === null) { # défaut. on veut pouvoir mettre temporairement throw à false si jamais il
# Si $value est null, ne pas lancer d'exception, parce qu'on considère que # n'est pas spécifié par l'utilisateur
# c'est une initialisation sans conséquences $throw = $params["throw"] ?? null;
$throw = true; # Si $value est null, ne pas lancer d'exception, parce qu'on considère que
} # c'est une initialisation sans conséquences
if ($throw === null && $value !== null) $throw = true;
$context->throw = $throw ?? false; $context->throw = $throw ?? false;
$this->reset($array, $arrayKey); $this->reset($value, $valueKey);
$context->throw = $throw ?? true; $context->throw = $throw ?? true;
} }
@ -40,35 +42,103 @@ class AssocWrapper extends Wrapper {
/** @var AssocWrapperContext */ /** @var AssocWrapperContext */
protected WrapperContext $context; protected WrapperContext $context;
function reset(&$array, $arrayKey=null, ?array $params=null): Wrapper { protected function resetContext($resetSelectedKey): void {
if ($array instanceof Input) $input = $array;
else $input = $this->newInput($array);
$context = $this->context; $context = $this->context;
$context->input = $input; $context->arrayResult->reset();
$context->valueKey = $arrayKey; foreach ($context->keyWrappers as $wrapper) {
$this->afterModify($params); $wrapper->getResult()->reset();
return $this; }
$context->analyzed = false;
$context->normalized = false;
if ($resetSelectedKey) {
$context->selectedKey = null;
$context->type = $context->arrayType;
$context->result = $context->arrayResult;
}
} }
function getKeys(): array { function getKeys(): array {
return $this->context->keys; return $this->context->keys;
} }
/** @param string|int|null $key */ protected function _getWrapper($key): Wrapper {
function select($key=null): Wrapper { $wrapper = $context->keyWrappers[$key] ?? null;
#XXX il faut que context contiennent les informations pour la clé sélectionnée
if ($key === null) return $this;
$wrapper = $this->context->keyWrappers[$key] ?? null;
if ($wrapper === null) throw ValueException::invalid_key($key); if ($wrapper === null) throw ValueException::invalid_key($key);
return $wrapper; return $wrapper;
} }
function isNormalized(): bool { /** @param string|int|null $key */
return $this->context->result->normalized; function select($key=null): Wrapper {
$context = $this->context;
if ($key === null) {
$context->selectedKey = null;
$context->type = $context->arrayType;
$context->result = $context->arrayResult;
return $this;
}
$wrapper = $this->_getWrapper($key);
$context->selectedKey = $key;
$context->type = $wrapper->getType();
$context->result = $wrapper->getResult();
return $wrapper;
} }
function ensureKeys(): bool { protected function _analyze(?array $params): int {
return -1;
} }
function orderKeys(): bool {
protected function _normalize(?array $params): bool {
return false;
}
function getResult($key=false): Result {
if ($key === false) return $this->context->result;
elseif ($key === null) return $this->context->arrayResult;
else return $this->_getWrapper($key)->getResult();
}
function getType($key=false): IType {
if ($key === false) return $this->context->type;
elseif ($key === null) return $this->context->arrayType;
else return $this->_getWrapper($key)->getType();
}
function get($default=null, $key=false) {
$context = $this->context;
if (!$context->arrayResult->available) return $default;
if ($key === false) $key = $context->selectedKey;
if ($key === null) return $context->input->get($context->valueKey);
else return $this->_getWrapper($key)->get($default);
}
function set($value, ?array $params=null, $key=false): Wrapper {
$context = $this->context;
if ($key === false) $key = $context->selectedKey;
if ($key === null) {
$context->input->set($value, $context->valueKey);
$this->afterModify($params);
} else {
$this->_getWrapper($key)->set($value);
}
return $this;
}
function unset(?array $params=null, $key=false): Wrapper {
$context = $this->context;
if ($key === false) $key = $context->selectedKey;
if ($key === null) {
$context->input->unset($context->valueKey);
$this->afterModify($params);
} else {
$this->_getWrapper($key)->unset();
}
return $this;
}
function format($format=null, $key=false): string {
$context = $this->context;
if ($key === false) $key = $context->selectedKey;
if ($key === null) return $this->_format($context, $format);
else return $this->_getWrapper($key)->format($format);
} }
} }

View File

@ -2,13 +2,22 @@
namespace nur\sery\wip\schema\_assoc; namespace nur\sery\wip\schema\_assoc;
use nur\sery\wip\schema\_scalar\ScalarResult; use nur\sery\wip\schema\_scalar\ScalarResult;
use nur\sery\wip\schema\input\Input;
use nur\sery\wip\schema\Schema;
use nur\sery\wip\schema\types\IType; use nur\sery\wip\schema\types\IType;
use nur\sery\wip\schema\Wrapper; use nur\sery\wip\schema\Wrapper;
use nur\sery\wip\schema\WrapperContext; use nur\sery\wip\schema\WrapperContext;
class AssocWrapperContext extends WrapperContext { class AssocWrapperContext extends WrapperContext {
function __construct(Schema $schema, ?Input $input, $valueKey, ?array $params) {
parent::__construct($schema, $input, $valueKey, $params);
$this->arrayType = null;
$this->arrayResult = null;
}
public ?IType $arrayType;
/** résultat de l'analyse du tableau */ /** résultat de l'analyse du tableau */
public ScalarResult $arrayResult; public ?ScalarResult $arrayResult;
/** liste des clés valides */ /** liste des clés valides */
public array $keys; public array $keys;

View File

@ -1,6 +1,7 @@
<?php <?php
namespace nur\sery\wip\schema\_scalar; namespace nur\sery\wip\schema\_scalar;
use nulib\cl;
use nulib\ref\schema\ref_schema; use nulib\ref\schema\ref_schema;
use nulib\ValueException; use nulib\ValueException;
use nur\sery\wip\schema\Schema; use nur\sery\wip\schema\Schema;
@ -10,8 +11,11 @@ use nur\sery\wip\schema\Wrapper;
* Class ScalarSchema * Class ScalarSchema
*/ */
class ScalarSchema extends Schema { class ScalarSchema extends Schema {
/** @var array meta-schema d'un schéma de nature scalaire */ //const METASCHEMA = ref_schema::VALUE_METASCHEMA;
const METASCHEMA = ref_schema::SCALAR_METASCHEMA; //const NATURE_METASCHEMA = [
// ...ref_schema::NATURE_METASCHEMA,
// ...ref_schema::SCALAR_NATURE_METASCHEMA,
//];
/** /**
* indiquer si $definition est une définition de schéma scalaire que * indiquer si $definition est une définition de schéma scalaire que
@ -45,7 +49,8 @@ class ScalarSchema extends Schema {
} }
static function normalize_definition($definition, $definitionKey=null): array { static function normalize_definition($definition, $definitionKey=null): array {
self::_normalize_definition($definition, $definitionKey); $natureMetaschema = array_merge(ref_schema::NATURE_METASCHEMA, ref_schema::SCALAR_NATURE_METASCHEMA);
self::_normalize_definition($definition, $definitionKey, $natureMetaschema);
self::_ensure_nature($definition, "scalar"); self::_ensure_nature($definition, "scalar");
return $definition; return $definition;
} }

View File

@ -4,7 +4,6 @@ namespace nur\sery\wip\schema\_scalar;
use nulib\php\func; use nulib\php\func;
use nulib\ref\schema\ref_analyze; use nulib\ref\schema\ref_analyze;
use nulib\ValueException; use nulib\ValueException;
use nur\sery\wip\schema\input\Input;
use nur\sery\wip\schema\types; use nur\sery\wip\schema\types;
use nur\sery\wip\schema\types\IType; use nur\sery\wip\schema\types\IType;
use nur\sery\wip\schema\Wrapper; use nur\sery\wip\schema\Wrapper;
@ -13,6 +12,7 @@ use nur\sery\wip\schema\WrapperContext;
/** /**
* Class ScalarWrapper * Class ScalarWrapper
* *
* @method ScalarWrapper reset()
* @method ScalarResult getResult() * @method ScalarResult getResult()
* @method self set() * @method self set()
* @method self unset() * @method self unset()
@ -38,16 +38,6 @@ class ScalarWrapper extends Wrapper {
protected WrapperContext $context; protected WrapperContext $context;
function reset(&$value, $valueKey=null, ?array $params=null): Wrapper {
$context = $this->context;
if ($value instanceof Input) $input = $value;
else $input = $this->newInput($value);
$context->input = $input;
$context->valueKey = $valueKey;
$this->afterModify($params);
return $this;
}
function getKeys(): array { function getKeys(): array {
return ScalarSchema::KEYS; return ScalarSchema::KEYS;
} }

View File

@ -7,7 +7,14 @@ use nur\sery\wip\schema\_scalar\ScalarSchemaTest;
class AssocSchemaTest extends TestCase { class AssocSchemaTest extends TestCase {
const NULL_SCHEMA = [ const NULL_SCHEMA = [
"" => ["assoc"], "" => [
"assoc",
"compute_func" => null,
"validate_func" => null,
"ensure_array" => false,
"ensure_keys" => true,
"ensure_order" => true,
],
"schema" => null, "schema" => null,
"type" => [null], "type" => [null],
"default" => null, "default" => null,

View File

@ -19,7 +19,11 @@ class ScalarSchemaTest extends TestCase {
"messages" => null, "messages" => null,
"formatter_func" => null, "formatter_func" => null,
"format" => null, "format" => null,
"" => ["scalar"], "" => [
"scalar",
"compute_func" => null,
"validate_func" => null,
],
"schema" => null, "schema" => null,
"name" => null, "name" => null,
"pkey" => null, "pkey" => null,