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
* tester type===null --> implémenter traw et tmixed
* ScalarSchema::from_property()
* dans AssocSchema, support `[key_prefix]` qui permet de spécifier un préfixe
@ -32,38 +31,6 @@
$wrapper->reset($value);
# $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,
chaque valeur correspond à la clé de même rang, eg. pour un schéma
~~~php

View File

@ -115,6 +115,7 @@ class ScalarSchema extends Schema {
$deftype = explode("|", $deftype);
}
foreach ($deftype as $type) {
if ($type !== null) $type = trim($type);
if ($type === null || $type === "null") {
$nullable = true;
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\tbool;
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\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\tstring;
use nur\sery\wip\schema\types\ttext;
@ -26,7 +31,7 @@ class types {
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);
}
@ -38,4 +43,9 @@ class types {
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 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 {
/**
* 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
* par {@link format()} et le type retourné par {@link verifix()}

View File

@ -16,6 +16,8 @@ class Registry {
"array" => tarray::class,
"callable" => tcallable::class,
# types spéciaux
"raw" => tmixed::class,
"mixed" => tmixed::class,
"key" => tkey::class,
"pkey" => tpkey::class,
"content" => tcontent::class,
@ -28,7 +30,8 @@ class Registry {
/** @var IType[] */
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];
$params = cl::merge($class::get_params_from_definition($definition), $params);
if ($params !== null) {

View File

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

View File

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

View File

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

View File

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

View File

@ -8,6 +8,8 @@ use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Schema;
abstract class tcontent extends _tunion {
const NAME = "content";
static function ensure_content(&$content): void {
if ($content === null || $content === false) $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;
class tfloat extends _tformatable {
const NAME = "float";
const ALIASES = ["flt", "double", "dbl"];
static function ensure_float(&$float): void {
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;
class tint extends _tformatable {
const NAME = "int";
const ALIASES = ["integer"];
static function ensure_int(&$int): void {
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;
class tkey extends _tunion {
const NAME = "key";
static function ensure_key(&$key): void {
if ($key === null) $key = "";
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;
class tpkey extends _tunion {
const NAME = "pkey";
static function ensure_pkey(&$pkey): void {
if ($pkey === null) $pkey = "";
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;
class trawstring extends _tstring {
const NAME = "rawstring";
static function ensure_string(&$string): void {
if (!is_string($string)) $string = strval($string);
if (static::TRIM) $string = trim($string);

View File

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

View File

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

View File

@ -4,6 +4,7 @@ namespace nur\sery\wip\schema\_scalar;
use nulib\tests\TestCase;
use nulib\ValueException;
use nur\sery\wip\schema\input\Input;
use stdClass;
class ScalarValueTest extends TestCase {
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() {
$schema = new ScalarSchema("rawstring");