diff --git a/src/schema/_assoc/AssocResult.php b/src/schema/_assoc/AssocResult.php index d55f723..99dbc41 100644 --- a/src/schema/_assoc/AssocResult.php +++ b/src/schema/_assoc/AssocResult.php @@ -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;} } diff --git a/src/schema/_assoc/AssocSchema.php b/src/schema/_assoc/AssocSchema.php index e39e8e6..b5d6816 100644 --- a/src/schema/_assoc/AssocSchema.php +++ b/src/schema/_assoc/AssocSchema.php @@ -1,8 +1,8 @@ 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); } diff --git a/src/schema/types.php b/src/schema/types.php index 109e7bf..ae3a11f 100644 --- a/src/schema/types.php +++ b/src/schema/types.php @@ -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"); } diff --git a/src/schema/types/Registry.php b/src/schema/types/Registry.php index 61a65e7..be8fe0c 100644 --- a/src/schema/types/Registry.php +++ b/src/schema/types/Registry.php @@ -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]; diff --git a/src/schema/types/_tsimple.php b/src/schema/types/_tsimple.php index 9614125..a300743 100644 --- a/src/schema/types/_tsimple.php +++ b/src/schema/types/_tsimple.php @@ -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; } diff --git a/src/schema/types/trawstring.php b/src/schema/types/trawstring.php new file mode 100644 index 0000000..2ac0610 --- /dev/null +++ b/src/schema/types/trawstring.php @@ -0,0 +1,79 @@ +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); + } +} diff --git a/src/schema/types/tstring.php b/src/schema/types/tstring.php index 877707c..6f2138c 100644 --- a/src/schema/types/tstring.php +++ b/src/schema/types/tstring.php @@ -1,48 +1,6 @@ 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; } diff --git a/tests/wip/schema/_scalar/ScalarValueTest.php b/tests/wip/schema/_scalar/ScalarValueTest.php new file mode 100644 index 0000000..a8bdc70 --- /dev/null +++ b/tests/wip/schema/_scalar/ScalarValueTest.php @@ -0,0 +1,162 @@ +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); + }); + } +}