modifs.mineures sans commentaires

This commit is contained in:
Jephté Clain 2025-03-07 19:59:23 +04:00
parent c5c4119e69
commit bb5b30480e
20 changed files with 186 additions and 39 deletions

View File

@ -1,6 +1,5 @@
# nulib\schema # nulib\schema
* tester type===null --> implémenter traw et tmixed
* ScalarSchema::from_property() * ScalarSchema::from_property()
* dans AssocSchema, support `[key_prefix]` qui permet de spécifier un préfixe * dans AssocSchema, support `[key_prefix]` qui permet de spécifier un préfixe
@ -32,38 +31,6 @@
$wrapper->reset($value); $wrapper->reset($value);
# $value vaut ["x_a" => "5", "x_b" => 10]; # $value vaut ["x_a" => "5", "x_b" => 10];
~~~ ~~~
* implémenter l'instanciation de types avec des paramètres particuliers. *si*
des paramètres sont fournis, le type est instancié avec la signature
`IType($typeDefinition, $schemaDefinition)` e.g
~~~php
const SCHEMA = ["type", default, "required" => true];
# le type est instancié comme suit:
$type = new ttype();
const SCHEMA = [[["type", ...]], default, "required" => true];
// ou
const SCHEMA = [["type" => [...]], default, "required" => true];
# le type est instancié comme suit:
# le tableau peut être une liste ou associatif, c'est au type de décider ce
# qu'il en fait
$type = new ttype(["type", ...], SCHEMA);
~~~
* ajouter à IType les méthodes getName() pour le nom officiel du type,
getAliases() pour les alias supportés, et getClass() pour la définition de la
classe dans les méthodes et propriétés
getName() et getAliases() sont juste pour information, ils ne sont pas utilisés
lors de la résolution du type effectif.
* si cela a du sens, dans AssocSchema, n'instancier les schémas de chaque clé qu'à la demande.
l'idée est de ne pas perdre du temps à instancier un schéma qui ne serait pas utilisé
on pourrait avoir d'une manière générale quelque chose comme:
~~~
Schema::ensure(&$schema, ?array $def=null, $defKey=null): Schema;
~~~
* si $schema est une instance de Schema, la retourner
* si c'est un array, c'est une définition et il faut la remplacer par l'instance de Schema correspondant
* sinon, prendre $def comme définition
$key est la clé si $schema est dans un autre schema
* actuellement, pour un schéma associatif, si on normalise un tableau séquentiel, * actuellement, pour un schéma associatif, si on normalise un tableau séquentiel,
chaque valeur correspond à la clé de même rang, eg. pour un schéma chaque valeur correspond à la clé de même rang, eg. pour un schéma
~~~php ~~~php

View File

@ -115,6 +115,7 @@ class ScalarSchema extends Schema {
$deftype = explode("|", $deftype); $deftype = explode("|", $deftype);
} }
foreach ($deftype as $type) { foreach ($deftype as $type) {
if ($type !== null) $type = trim($type);
if ($type === null || $type === "null") { if ($type === null || $type === "null") {
$nullable = true; $nullable = true;
continue; continue;

View File

@ -6,8 +6,13 @@ use nur\sery\wip\schema\types\Registry;
use nur\sery\wip\schema\types\tarray; use nur\sery\wip\schema\types\tarray;
use nur\sery\wip\schema\types\tbool; use nur\sery\wip\schema\types\tbool;
use nur\sery\wip\schema\types\tcallable; use nur\sery\wip\schema\types\tcallable;
use nur\sery\wip\schema\types\tcontent;
use nur\sery\wip\schema\types\tfloat; use nur\sery\wip\schema\types\tfloat;
use nur\sery\wip\schema\types\tint; use nur\sery\wip\schema\types\tint;
use nur\sery\wip\schema\types\tkey;
use nur\sery\wip\schema\types\tmixed;
use nur\sery\wip\schema\types\tpkey;
use nur\sery\wip\schema\types\traw;
use nur\sery\wip\schema\types\trawstring; use nur\sery\wip\schema\types\trawstring;
use nur\sery\wip\schema\types\tstring; use nur\sery\wip\schema\types\tstring;
use nur\sery\wip\schema\types\ttext; use nur\sery\wip\schema\types\ttext;
@ -26,7 +31,7 @@ class types {
return self::$registry; return self::$registry;
} }
static function get(bool $nullable, string $name, ?array $params=null, ?array $definition=null): IType { static function get(bool $nullable, ?string $name, ?array $params=null, ?array $definition=null): IType {
return self::registry()->get($nullable, $name, $params, $definition); return self::registry()->get($nullable, $name, $params, $definition);
} }
@ -38,4 +43,9 @@ class types {
static function float(bool $nullable=true): tfloat { return self::get($nullable, "float"); } static function float(bool $nullable=true): tfloat { return self::get($nullable, "float"); }
static function array(bool $nullable=true): tarray { return self::get($nullable, "array"); } static function array(bool $nullable=true): tarray { return self::get($nullable, "array"); }
static function callable(bool $nullable=true): tcallable { return self::get($nullable, "callable"); } static function callable(bool $nullable=true): tcallable { return self::get($nullable, "callable"); }
static function raw(bool $nullable=true): traw { return self::get($nullable, "raw"); }
static function mixed(bool $nullable=true): tmixed { return self::get($nullable, "mixed"); }
static function key(bool $nullable=true): tkey { return self::get($nullable, "key"); }
static function pkey(bool $nullable=true): tpkey { return self::get($nullable, "pkey"); }
static function content(bool $nullable=true): tcontent { return self::get($nullable, "content"); }
} }

View File

@ -10,6 +10,15 @@ use nur\sery\wip\schema\Schema;
* Interface IType: un type de données * Interface IType: un type de données
*/ */
interface IType { interface IType {
/**
* obtenir, pour information, le nom officiel de ce type, utilisable dans une
* définition de schéma
*/
function getName(): string;
/** obtenir la liste des aliases valides pour ce type */
function getAliases(): array;
/** /**
* @return string la classe des objets gérés par ce format: le type attendu * @return string la classe des objets gérés par ce format: le type attendu
* par {@link format()} et le type retourné par {@link verifix()} * par {@link format()} et le type retourné par {@link verifix()}

View File

@ -16,6 +16,8 @@ class Registry {
"array" => tarray::class, "array" => tarray::class,
"callable" => tcallable::class, "callable" => tcallable::class,
# types spéciaux # types spéciaux
"raw" => tmixed::class,
"mixed" => tmixed::class,
"key" => tkey::class, "key" => tkey::class,
"pkey" => tpkey::class, "pkey" => tpkey::class,
"content" => tcontent::class, "content" => tcontent::class,
@ -28,7 +30,8 @@ class Registry {
/** @var IType[] */ /** @var IType[] */
protected $types; protected $types;
function get(bool $nullable, string $name, ?array $params=null, ?array $definition=null): IType { function get(bool $nullable, ?string $name, ?array $params=null, ?array $definition=null): IType {
$name ??= "raw";
$class = self::TYPES[$name]; $class = self::TYPES[$name];
$params = cl::merge($class::get_params_from_definition($definition), $params); $params = cl::merge($class::get_params_from_definition($definition), $params);
if ($params !== null) { if ($params !== null) {

View File

@ -7,6 +7,10 @@ use nur\sery\wip\schema\input\Input;
use nur\str; use nur\str;
abstract class _tsimple implements IType { abstract class _tsimple implements IType {
const NAME = null;
const ALIASES = [];
static function get_params_from_definition(?array $definition): ?array { static function get_params_from_definition(?array $definition): ?array {
return null; return null;
} }
@ -20,6 +24,14 @@ abstract class _tsimple implements IType {
protected ?array $params; protected ?array $params;
function getName(): string {
return static::NAME;
}
function getAliases(): array {
return static::ALIASES;
}
function getPhpType(bool $allowNullable=true): ?string { function getPhpType(bool $allowNullable=true): ?string {
$phpType = $this->getClass(); $phpType = $this->getClass();
if ($phpType === "mixed") return null; if ($phpType === "mixed") return null;
@ -27,6 +39,10 @@ abstract class _tsimple implements IType {
return $phpType; return $phpType;
} }
function is2States(): bool {
return false;
}
function get2States(): array { function get2States(): array {
throw StateException::not_implemented(); throw StateException::not_implemented();
} }
@ -51,10 +67,6 @@ abstract class _tsimple implements IType {
return $value; return $value;
} }
function is2States(): bool {
return false;
}
############################################################################# #############################################################################
function getGetterName(string $name): string { function getGetterName(string $name): string {

View File

@ -9,6 +9,8 @@ use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Schema; use nur\sery\wip\schema\Schema;
class tarray extends _tstring { class tarray extends _tstring {
const NAME = "array";
const SPLIT_PATTERN = '/\s+/'; const SPLIT_PATTERN = '/\s+/';
const FORMAT = " "; const FORMAT = " ";

View File

@ -11,6 +11,10 @@ use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Schema; use nur\sery\wip\schema\Schema;
class tbool extends _tformatable { class tbool extends _tformatable {
const NAME = "bool";
const ALIASES = ["boolean"];
/** liste de valeurs chaines à considérer comme 'OUI' */ /** liste de valeurs chaines à considérer comme 'OUI' */
const YES_VALUES = [ const YES_VALUES = [
"true", "vrai", "yes", "oui", "true", "vrai", "yes", "oui",

View File

@ -10,6 +10,10 @@ use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Schema; use nur\sery\wip\schema\Schema;
class tcallable extends _tsimple { class tcallable extends _tsimple {
const NAME = "callable";
const ALIASES = ["func", "function"];
static function ensure_callable(&$callable): void { static function ensure_callable(&$callable): void {
$callable = func::ensure($callable); $callable = func::ensure($callable);
} }

View File

@ -8,6 +8,8 @@ use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Schema; use nur\sery\wip\schema\Schema;
abstract class tcontent extends _tunion { abstract class tcontent extends _tunion {
const NAME = "content";
static function ensure_content(&$content): void { static function ensure_content(&$content): void {
if ($content === null || $content === false) $content = []; if ($content === null || $content === false) $content = [];
elseif (!is_string($content) && !is_array($content)) $content = strval($content); elseif (!is_string($content) && !is_array($content)) $content = strval($content);

View File

@ -8,6 +8,10 @@ use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Schema; use nur\sery\wip\schema\Schema;
class tfloat extends _tformatable { class tfloat extends _tformatable {
const NAME = "float";
const ALIASES = ["flt", "double", "dbl"];
static function ensure_float(&$float): void { static function ensure_float(&$float): void {
if (!is_float($float)) $float = floatval($float); if (!is_float($float)) $float = floatval($float);
} }

View File

@ -8,6 +8,10 @@ use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Schema; use nur\sery\wip\schema\Schema;
class tint extends _tformatable { class tint extends _tformatable {
const NAME = "int";
const ALIASES = ["integer"];
static function ensure_int(&$int): void { static function ensure_int(&$int): void {
if (!is_int($int)) $int = intval($int); if (!is_int($int)) $int = intval($int);
} }

View File

@ -7,6 +7,8 @@ use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Schema; use nur\sery\wip\schema\Schema;
class tkey extends _tunion { class tkey extends _tunion {
const NAME = "key";
static function ensure_key(&$key): void { static function ensure_key(&$key): void {
if ($key === null) $key = ""; if ($key === null) $key = "";
elseif ($key === false) $key = 0; elseif ($key === false) $key = 0;

View File

@ -0,0 +1,46 @@
<?php
namespace nur\sery\wip\schema\types;
use nur\sery\wip\schema\_scalar\ScalarResult;
use nur\sery\wip\schema\_scalar\ScalarSchema;
use nur\sery\wip\schema\input\Input;
use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Schema;
class tmixed extends _tsimple {
const NAME = "mixed";
function getClass(): string {
return "mixed";
}
function isAvailable(Input $input, $valueKey): bool {
return $input->isAvailable($valueKey);
}
public function isNull($value): bool {
return $value === null;
}
function isValid($value, ?bool &$normalized=null): bool {
$normalized = true;
return true;
}
function parse(string $value) {
return $value;
}
/**
* @var ScalarResult $result
* @var ScalarSchema $schema
*/
function verifix(&$value, Result $result, Schema $schema): bool {
$result->setNormalized();
return false;
}
function format($value, $format=null): string {
return var_export($value, true);
}
}

View File

@ -7,6 +7,8 @@ use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Schema; use nur\sery\wip\schema\Schema;
class tpkey extends _tunion { class tpkey extends _tunion {
const NAME = "pkey";
static function ensure_pkey(&$pkey): void { static function ensure_pkey(&$pkey): void {
if ($pkey === null) $pkey = ""; if ($pkey === null) $pkey = "";
elseif ($pkey === false) $pkey = 0; elseif ($pkey === false) $pkey = 0;

16
src/schema/types/traw.php Normal file
View File

@ -0,0 +1,16 @@
<?php
namespace nur\sery\wip\schema\types;
use nur\sery\wip\schema\input\Input;
class traw extends tmixed {
const NAME = "raw";
function isAvailable(Input $input, $valueKey): bool {
return true;
}
public function isNull($value): bool {
return false;
}
}

View File

@ -8,6 +8,8 @@ use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Schema; use nur\sery\wip\schema\Schema;
class trawstring extends _tstring { class trawstring extends _tstring {
const NAME = "rawstring";
static function ensure_string(&$string): void { static function ensure_string(&$string): void {
if (!is_string($string)) $string = strval($string); if (!is_string($string)) $string = strval($string);
if (static::TRIM) $string = trim($string); if (static::TRIM) $string = trim($string);

View File

@ -2,5 +2,7 @@
namespace nur\sery\wip\schema\types; namespace nur\sery\wip\schema\types;
class tstring extends trawstring { class tstring extends trawstring {
const NAME = "string";
const TRIM = true; const TRIM = true;
} }

View File

@ -2,6 +2,8 @@
namespace nur\sery\wip\schema\types; namespace nur\sery\wip\schema\types;
class ttext extends trawstring { class ttext extends trawstring {
const NAME = "text";
const TRIM = true; const TRIM = true;
const NORM_NL = true; const NORM_NL = true;
} }

View File

@ -4,6 +4,7 @@ namespace nur\sery\wip\schema\_scalar;
use nulib\tests\TestCase; use nulib\tests\TestCase;
use nulib\ValueException; use nulib\ValueException;
use nur\sery\wip\schema\input\Input; use nur\sery\wip\schema\input\Input;
use stdClass;
class ScalarValueTest extends TestCase { class ScalarValueTest extends TestCase {
function checkValue(ScalarWrapper $wrapper, $dest, bool $present, bool $available, bool $valid, bool $normalized): void { function checkValue(ScalarWrapper $wrapper, $dest, bool $present, bool $available, bool $valid, bool $normalized): void {
@ -30,6 +31,58 @@ class ScalarValueTest extends TestCase {
}); });
} }
function testRaw() {
$schema = new ScalarSchema();
$this->checkVerifix($schema, false, false, false, true, true, true, true);
$this->checkVerifix($schema, false, true, false, true, true, true, true);
$this->checkVerifix($schema, null, false, null, true, true, true, true);
$this->checkVerifix($schema, null, true, null, true, true, true, true);
$obj = new stdClass();
$this->checkVerifix($schema, $obj, false, $obj, true, true, true, true);
$this->checkVerifix($schema, $obj, true, $obj, true, true, true, true);
$schema = new ScalarSchema("raw");
$this->checkVerifix($schema, false, false, false, true, true, true, true);
$this->checkVerifix($schema, false, true, false, true, true, true, true);
$this->checkVerifix($schema, null, false, null, true, true, true, true);
$this->checkVerifix($schema, null, true, null, true, true, true, true);
$obj = new stdClass();
$this->checkVerifix($schema, $obj, false, $obj, true, true, true, true);
$this->checkVerifix($schema, $obj, true, $obj, true, true, true, true);
}
function testMixed() {
$schema = new ScalarSchema("mixed");
$this->checkVerifix($schema, false, false, false, true, true, true, true);
$this->checkVerifix($schema, false, true, false, true, true, true, true);
$this->checkVerifix($schema, null, false, null, true, true, false, false);
$this->checkException($schema, null, true, ValueException::class);
$obj = new stdClass();
$this->checkVerifix($schema, $obj, false, $obj, true, true, true, true);
$this->checkVerifix($schema, $obj, true, $obj, true, true, true, true);
$schema = new ScalarSchema("?mixed");
$this->checkVerifix($schema, false, false, false, true, true, true, true);
$this->checkVerifix($schema, false, true, false, true, true, true, true);
$this->checkVerifix($schema, null, false, null, true, true, true, true);
$this->checkVerifix($schema, null, true, null, true, true, true, true);
$obj = new stdClass();
$this->checkVerifix($schema, $obj, false, $obj, true, true, true, true);
$this->checkVerifix($schema, $obj, true, $obj, true, true, true, true);
}
function testRawstring() { function testRawstring() {
$schema = new ScalarSchema("rawstring"); $schema = new ScalarSchema("rawstring");