tstring et trawstring

This commit is contained in:
Jephté Clain 2025-03-04 09:52:23 +04:00
parent 1685a40906
commit 1aa266b509
14 changed files with 275 additions and 58 deletions

View File

@ -3,6 +3,6 @@ namespace nur\sery\wip\schema\_assoc;
use nur\sery\wip\schema\Result;
class AssocResult extends Result {
abstract/*XXX*/ class AssocResult extends Result {
function isAssoc(?AssocResult &$assoc=null): bool { $assoc = $this; return true;}
}

View File

@ -1,8 +1,8 @@
<?php
namespace nur\sery\wip\schema\_assoc;
use nur\sery\cl;
use nur\sery\ref\schema\ref_schema;
use nulib\cl;
use nulib\ref\schema\ref_schema;
use nur\sery\wip\schema\Schema;
use nur\sery\wip\schema\Value;

View File

@ -4,7 +4,7 @@ namespace nur\sery\wip\schema\_assoc;
use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Value;
class AssocValue extends Value {
abstract/*XXX*/ class AssocValue extends Value {
function isAssoc(?AssocValue &$assoc=null): bool { $assoc = $this; return true; }
function ensureKeys(): bool {

View File

@ -3,6 +3,6 @@ namespace nur\sery\wip\schema\_list;
use nur\sery\wip\schema\Result;
class ListResult extends Result {
abstract/*XXX*/ class ListResult extends Result {
function isList(?ListResult &$list=null): bool { $list = $this; return true;}
}

View File

@ -1,7 +1,7 @@
<?php
namespace nur\sery\wip\schema\_list;
use nur\sery\ref\schema\ref_schema;
use nulib\ref\schema\ref_schema;
use nur\sery\wip\schema\Schema;
use nur\sery\wip\schema\Value;

View File

@ -4,7 +4,7 @@ namespace nur\sery\wip\schema\_list;
use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Value;
class ListValue extends Value {
abstract/*XXX*/ class ListValue extends Value {
function isList(?ListValue &$list=null): bool { $list = $this; return true; }
function ensureKeys(): bool {

View File

@ -11,7 +11,7 @@ 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\tpkey;
use nur\sery\wip\schema\types\tstring;
use nur\sery\wip\schema\types\trawstring;
use nur\sery\wip\schema\Value;
/**
@ -31,6 +31,7 @@ use nur\sery\wip\schema\Value;
* @property-read callable|null $formatterFunc
* @property-read mixed $format
* @property-read array $nature
* @property-read array|null $schema
* @property-read string|int|null $name
* @property-read string|array|null $pkey
* @property-read string|null $header
@ -142,9 +143,9 @@ class ScalarSchema extends Schema {
$pkey = $definition["pkey"];
$header = $definition["header"];
if ($name === null) $name = $definitionKey;
tstring::ensure_nstring($name);
trawstring::ensure_nstring($name);
tpkey::ensure_npkey($pkey);
tstring::ensure_nstring($header);
trawstring::ensure_nstring($header);
if ($pkey === null) $pkey = $name;
if ($header === null) $header = $name;
$definition["name"] = $name;
@ -152,7 +153,7 @@ class ScalarSchema extends Schema {
$definition["header"] = $header;
# autres éléments
tarray::ensure_narray($definition["schema"]);
tstring::ensure_nstring($definition["title"]);
trawstring::ensure_nstring($definition["title"]);
tbool::ensure_bool($definition["required"]);
tbool::ensure_bool($definition["nullable"]);
tcontent::ensure_ncontent($definition["desc"]);

View File

@ -53,7 +53,7 @@ class ScalarValue extends Value {
$this->destKey = $destKey;
$this->type = null;
$this->_analyze();
if ($verifix == null) $verifix = $this->defaultVerifix;
if ($verifix === null) $verifix = $this->defaultVerifix;
if ($verifix) $this->verifix();
return $this;
}
@ -75,6 +75,7 @@ class ScalarValue extends Value {
$result = $this->result;
$result->reset();
if (!$input->isPresent($destKey)) return $result->setMissing($schema);
$haveType = false;
$types = [];
$type = $firstType = null;
@ -107,15 +108,18 @@ class ScalarValue extends Value {
}
}
}
# sinon prendre le premier type
if (!$haveType) $type = $this->type = $firstType;
if (!$type->isAvailable($input, $destKey)) return $result->setUnavailable($schema);
$value = $input->get($destKey);
if ($type->isNull($value)) return $result->setNull($schema);
if ($type->isValid($value, $normalized)) {
if ($normalized) return $result->setNormalized();
else return $result->setValid();
}
if (is_string($value)) return ref_analyze::STRING;
else return $result->setInvalid($value, $schema);
}

View File

@ -8,7 +8,7 @@ use nur\sery\wip\schema\types\tbool;
use nur\sery\wip\schema\types\tcallable;
use nur\sery\wip\schema\types\tfloat;
use nur\sery\wip\schema\types\tint;
use nur\sery\wip\schema\types\tstring;
use nur\sery\wip\schema\types\trawstring;
/**
* Class types: classe outil pour gérer le registre de types
@ -28,6 +28,7 @@ class types {
return self::registry()->get($name);
}
static function rawstring(): trawstring { return self::get("rawstring"); }
static function string(): tstring { return self::get("string"); }
static function bool(): tbool { return self::get("bool"); }
static function int(): tint { return self::get("int"); }

View File

@ -2,9 +2,11 @@
namespace nur\sery\wip\schema\types;
use nulib\cl;
use nulib\php\func;
class Registry {
const TYPES = [
"rawstring" => trawstring::class,
"string" => tstring::class,
"bool" => tbool::class, "boolean" => tbool::class,
"int" => tint::class, "integer" => tint::class,
@ -25,7 +27,11 @@ class Registry {
/** @var IType[] */
protected $types;
function get(string $name): IType {
function get(string $name, ?array $params=null): IType {
if ($params !== null) {
$class = self::TYPES[$name];
return func::with([$class, false, $params])->invoke();
}
$type = cl::get($this->types, $name);
if ($type === null) {
$class = self::TYPES[$name];

View File

@ -4,6 +4,12 @@ namespace nur\sery\wip\schema\types;
use nur\sery\wip\schema\input\Input;
abstract class _tsimple implements IType {
function __construct(?array $params=null) {
$this->params = $params;
}
protected ?array $params;
function isAvailable(Input $input, $destKey): bool {
return $input->isAvailable($destKey) && $input->get($destKey) !== false;
}

View File

@ -0,0 +1,79 @@
<?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\Result;
use nur\sery\wip\schema\Schema;
class trawstring extends _tsimple {
const TRIM = false;
static function ensure_string(&$string): void {
if (!is_string($string)) $string = strval($string);
if (static::TRIM) $string = trim($string);
}
static function ensure_nstring(&$string): void {
if ($string !== null) self::ensure_string($string);
}
function __construct(?array $params=null) {
parent::__construct($params);
$this->trim = boolval($this->params["trim"] ?? static::TRIM);
}
protected bool $trim;
function isNull($value): bool {
return $value === null;
}
protected function check_normalized(string $value, bool $trim): bool {
if ($trim && $value !== "") {
if (preg_match('/^\s+/', $value)) {
return false;
} elseif (preg_match('/\s+$/', $value)) {
return false;
}
}
return true;
}
function isValid($value, ?bool &$normalized=null): bool {
if (is_string($value)) {
$normalized = self::check_normalized($value, $this->trim);
return true;
}
return is_scalar($value);
}
/**
* @var ScalarResult $result
* @var ScalarSchema $schema
*/
function verifix(&$value, Result &$result, Schema $schema): bool {
if (is_string($value)) {
$normalized = false;
if ($this->trim) {
$orig = $value;
$value = trim($value);
$normalized = $value !== $orig;
}
$result->setNormalized();
return $normalized;
} elseif (is_scalar($value)) {
$value = strval($value);
if ($this->trim) $value = trim($value);
$result->setNormalized();
return true;
} else {
$result->setInvalid($value, $schema);
return false;
}
}
function format($value, $format=null): string {
return strval($value);
}
}

View File

@ -1,48 +1,6 @@
<?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\Result;
use nur\sery\wip\schema\Schema;
class tstring extends _tsimple {
static function ensure_string(&$string): void {
if (!is_string($string)) $string = strval($string);
}
static function ensure_nstring(&$string): void {
if ($string !== null) self::ensure_string($string);
}
function isNull($value): bool {
return $value === null;
}
function isValid($value, ?bool &$normalized=null): bool {
$normalized = is_string($value);
return is_scalar($value);
}
/**
* @var ScalarResult $result
* @var ScalarSchema $schema
*/
function verifix(&$value, Result &$result, Schema $schema): bool {
if (is_string($value)) {
$result->setNormalized();
return false;
} elseif (is_scalar($value)) {
$value = strval($value);
$result->setValid();
return true;
} else {
$result->setInvalid($value, $schema);
return false;
}
}
function format($value, $format=null): string {
return strval($value);
}
class tstring extends trawstring {
const TRIM = true;
}

View File

@ -0,0 +1,162 @@
<?php
namespace nur\sery\wip\schema\_scalar;
use nulib\tests\TestCase;
use nulib\ValueException;
class ScalarValueTest extends TestCase {
function checkValue(ScalarValue $value, $dest, bool $present, bool $available, bool $valid, bool $normalized): void {
self::assertSame($dest, $value->get(), "value");
self::assertSame($present, $value->isPresent(), "present");
self::assertSame($available, $value->isAvailable(), "available");
self::assertSame($valid, $value->isValid(), "valid");
self::assertSame($normalized, $value->isNormalized(), "normalized");
}
function testRawstring() {
$schema = new ScalarSchema("rawstring");
$value = $schema->newValue();
$string = null;
$value->reset($string, null, false);
$this->checkValue($value, null, true, true, false, false);
self::assertException(ValueException::class, function() use (&$value) {
$string = null;
$value->reset($string);
});
$string = ""; $value->reset($string, null, false);
$this->checkValue($value, "", true, true, true, true);
$string = ""; $value->reset($string);
$this->checkValue($value, "", true, true, true, true);
$string = " "; $value->reset($string, null, false);
$this->checkValue($value, " ", true, true, true, true);
$string = " "; $value->reset($string);
$this->checkValue($value, " ", true, true, true, true);
$string = "value"; $value->reset($string, null, false);
$this->checkValue($value, "value", true, true, true, true);
$string = "value"; $value->reset($string);
$this->checkValue($value, "value", true, true, true, true);
$string = " value "; $value->reset($string, null, false);
$this->checkValue($value, " value ", true, true, true, true);
$string = " value "; $value->reset($string);
$this->checkValue($value, " value ", true, true, true, true);
$string = true; $value->reset($string, null, false);
$this->checkValue($value, true, true, true, true, false);
$string = true; $value->reset($string);
$this->checkValue($value, "1", true, true, true, true);
$string = false; $value->reset($string, null, false);
$this->checkValue($value, null, true, false, true, true);
$string = false; $value->reset($string);
$this->checkValue($value, null, true, false, true, true);
$string = 42; $value->reset($string, null, false);
$this->checkValue($value, 42, true, true, true, false);
$string = 42; $value->reset($string);
$this->checkValue($value, "42", true, true, true, true);
$string = []; $value->reset($string, null, false);
$this->checkValue($value, [], true, true, false, false);
self::assertException(ValueException::class, function() use (&$value) {
$string = null;
$value->reset($string);
});
## Tester nullable
$schema = new ScalarSchema("?rawstring");
$value = $schema->newValue();
$string = null; $value->reset($string, null, false);
$this->checkValue($value, null, true, true, true, true);
$string = null; $value->reset($string, null);
$this->checkValue($value, null, true, true, true, true);
## Tester required
$schema = new ScalarSchema(["rawstring", "required" => true]);
$value = $schema->newValue();
$string = false; $value->reset($string, null, false);
$this->checkValue($value, null, true, false, false, false);
self::assertException(ValueException::class, function() use (&$value) {
$string = false; $value->reset($string);
});
}
function testString() {
$schema = new ScalarSchema("string");
$value = $schema->newValue();
$string = null; $value->reset($string, null, false);
$this->checkValue($value, null, true, true, false, false);
self::assertException(ValueException::class, function() use (&$value) {
$string = null;
$value->reset($string);
});
$string = ""; $value->reset($string, null, false);
$this->checkValue($value, "", true, true, true, true);
$string = ""; $value->reset($string);
$this->checkValue($value, "", true, true, true, true);
$string = " "; $value->reset($string, null, false);
$this->checkValue($value, " ", true, true, true, false);
$string = " "; $value->reset($string);
$this->checkValue($value, "", true, true, true, true);
$string = "value"; $value->reset($string, null, false);
$this->checkValue($value, "value", true, true, true, true);
$string = "value"; $value->reset($string);
$this->checkValue($value, "value", true, true, true, true);
$string = " value "; $value->reset($string, null, false);
$this->checkValue($value, " value ", true, true, true, false);
$string = " value "; $value->reset($string);
$this->checkValue($value, "value", true, true, true, true);
$string = true; $value->reset($string, null, false);
$this->checkValue($value, true, true, true, true, false);
$string = true; $value->reset($string);
$this->checkValue($value, "1", true, true, true, true);
$string = false; $value->reset($string, null, false);
$this->checkValue($value, null, true, false, true, true);
$string = false; $value->reset($string);
$this->checkValue($value, null, true, false, true, true);
$string = 42; $value->reset($string, null, false);
$this->checkValue($value, 42, true, true, true, false);
$string = 42; $value->reset($string);
$this->checkValue($value, "42", true, true, true, true);
$string = []; $value->reset($string, null, false);
$this->checkValue($value, [], true, true, false, false);
self::assertException(ValueException::class, function() use (&$value) {
$string = null;
$value->reset($string);
});
## Tester nullable
$schema = new ScalarSchema("?string");
$value = $schema->newValue();
$string = null; $value->reset($string, null, false);
$this->checkValue($value, null, true, true, true, true);
$string = null; $value->reset($string, null);
$this->checkValue($value, null, true, true, true, true);
## Tester required
$schema = new ScalarSchema(["string", "required" => true]);
$value = $schema->newValue();
$string = false; $value->reset($string, null, false);
$this->checkValue($value, null, true, false, false, false);
self::assertException(ValueException::class, function() use (&$value) {
$string = false; $value->reset($string);
});
}
}