diff --git a/src/schema/types/tbool.php b/src/schema/types/tbool.php index 19fb060..6552e81 100644 --- a/src/schema/types/tbool.php +++ b/src/schema/types/tbool.php @@ -1,12 +1,127 @@ isAvailable($destKey); + } + + function isNull($value): bool { + return $value === null || (is_string($value) && trim($value) === ""); + } + + function isValid($value, ?bool &$normalized=null): bool { + if (is_string($value)) { + $value = trim($value); + $valid = self::is_yes($value) || self::is_no($value); + } else { + $valid = is_scalar($value); + } + $normalized = is_bool($value); + return $valid; + } + + /** + * @var ScalarResult $result + * @var ScalarSchema $schema + */ + function verifix(&$value, Result &$result, Schema $schema): bool { + if (is_bool($value)) { + $result->setNormalized(); + return false; + } elseif (is_string($value)) { + $bool = trim($value); + if (self::is_yes($bool)) $value = true; + elseif (self::is_no($bool)) $value = false; + else return $result->setInvalid($value, $schema); + } elseif (is_scalar($value)) { + $value = boolval($value); + } else { + return $result->setInvalid($value, $schema); + } + $result->setValid(); + return true; + } + + const OUINON_FORMAT = ["Oui", "Non", false]; + const OUINONNULL_FORMAT = ["Oui", "Non", ""]; + const ON_FORMAT = ["O", "N", false]; + const ONN_FORMAT = ["O", "N", ""]; + const XN_FORMAT = ["X", "", false]; + const OZ_FORMAT = ["1", "", false]; + const FORMATS = [ + "ouinon" => self::OUINON_FORMAT, + "ouinonnull" => self::OUINONNULL_FORMAT, + "on" => self::ON_FORMAT, + "onn" => self::ONN_FORMAT, + "xn" => self::XN_FORMAT, + "oz" => self::OZ_FORMAT, + ]; + + const DEFAULT_FORMAT = self::OUINON_FORMAT; + + function format($value, $format=null): string { + if ($format === null) $format = static::DEFAULT_FORMAT; + if (is_string($format)) { + $oformat = $format; + $format = cl::get(self::FORMATS, strtolower($oformat)); + if ($format === null) throw ValueException::invalid_kind($oformat, "format"); + } + if ($value === null) { + $null = $format[2]; + if ($null !== false) return $null; + } + return $value? $format[0]: $format[1]; + } } diff --git a/src/schema/types/tfloat.php b/src/schema/types/tfloat.php index 6c587a5..3b5c539 100644 --- a/src/schema/types/tfloat.php +++ b/src/schema/types/tfloat.php @@ -1,5 +1,59 @@ isAvailable($destKey) && $input->get($destKey) !== false; + } + + function isNull($value): bool { + return $value === null || (is_string($value) && trim($value) === ""); + } + + function isValid($value, ?bool &$normalized=null): bool { + if (is_string($value)) $valid = is_numeric(trim($value)); + else $valid = is_scalar($value); + $normalized = is_float($value); + return $valid; + } + + /** + * @var ScalarResult $result + * @var ScalarSchema $schema + */ + function verifix(&$value, Result &$result, Schema $schema): bool { + if (is_float($value)) { + $result->setNormalized(); + return false; + } elseif (is_string($value)) { + $float = trim($value); + if (is_numeric($float)) $value = floatval($float); + else return $result->setInvalid($value, $schema); + } elseif (is_scalar($value)) { + $value = floatval($value); + } else { + return $result->setInvalid($value, $schema); + } + $result->setValid(); + return true; + } + + function format($value, $format=null): string { + if ($format !== null) return sprintf($format, $value); + else return strval($value); + } } diff --git a/src/schema/types/tint.php b/src/schema/types/tint.php index 232a3cc..a5c52cd 100644 --- a/src/schema/types/tint.php +++ b/src/schema/types/tint.php @@ -27,11 +27,8 @@ class tint implements IType { const INT_PATTERN = '/^[-+]?[0-9]+(?:\.[0-9]*)?$/'; function isValid($value, ?bool &$normalized=null): bool { - if (is_string($value)) { - $valid = preg_match(self::INT_PATTERN, trim($value)); - } else { - $valid = is_scalar($value); - } + if (is_string($value)) $valid = is_numeric(trim($value)); + else $valid = is_scalar($value); $normalized = is_int($value); return $valid; } @@ -46,7 +43,7 @@ class tint implements IType { return false; } elseif (is_string($value)) { $int = trim($value); - if (preg_match(self::INT_PATTERN, $int)) $value = intval($int); + if (is_numeric($int)) $value = intval($int); else return $result->setInvalid($value, $schema); } elseif (is_scalar($value)) { $value = intval($value); diff --git a/src/schema/types/tstring.php b/src/schema/types/tstring.php index 3cd3663..e36203f 100644 --- a/src/schema/types/tstring.php +++ b/src/schema/types/tstring.php @@ -48,6 +48,6 @@ class tstring implements IType { } function format($value, $format=null): string { - return $value; + return strval($value); } } diff --git a/tests/schema/schemaTest.php b/tests/schema/schemaTest.php deleted file mode 100644 index 67f66ed..0000000 --- a/tests/schema/schemaTest.php +++ /dev/null @@ -1,203 +0,0 @@ -set($value); - }; - }; - - self::assertException(Exception::class, $intvSetter(null)); - self::assertException(Exception::class, $intvSetter("")); - self::assertException(Exception::class, $intvSetter(" ")); - - $intv->set(12); - self::assertSame(12, $intv->get()); - self::assertSame(12, $int); - self::assertSame("12", $intv->format()); - self::assertSame("0012", $intv->format("%04u")); - - $intv->set("12"); - self::assertSame(12, $intv->get()); - - $intv->set(" 12 "); - self::assertSame(12, $intv->get()); - - $intv->set(true); - self::assertSame(1, $intv->get()); - - // valeur non requise donc retourne null - $intv->set(false); - self::assertNull($intv->get()); - - self::assertException(Exception::class, $intvSetter("a")); - self::assertException(Exception::class, $intvSetter([])); - self::assertException(Exception::class, $intvSetter(["a"])); - } - - function testRequiredInt() { - /** @var ScalarValue $intv */ - Schema::nv($intv, $int, null, $schema, [ - "int", null, - "required" => true, - ]); - $intvSetter = function($value) use($intv) { - return function() use($intv, $value) { - $intv->set($value); - }; - }; - - self::assertException(Exception::class, $intvSetter(null)); - self::assertException(Exception::class, $intvSetter("")); - self::assertException(Exception::class, $intvSetter(" ")); - - $intv->set(12); - self::assertSame(12, $intv->get()); - self::assertSame(12, $int); - self::assertSame("12", $intv->format()); - self::assertSame("0012", $intv->format("%04u")); - - $intv->set("12"); - self::assertSame(12, $intv->get()); - - $intv->set(" 12 "); - self::assertSame(12, $intv->get()); - - $intv->set(true); - self::assertSame(1, $intv->get()); - - // valeur requise donc lance une exception - self::assertException(Exception::class, $intvSetter(false)); - - self::assertException(Exception::class, $intvSetter("a")); - self::assertException(Exception::class, $intvSetter([])); - self::assertException(Exception::class, $intvSetter(["a"])); - } - - function testNint() { - /** @var ScalarValue $intv */ - Schema::nv($intv, $int, null, $schema, "?int"); - $intvSetter = function($value) use($intv) { - return function() use($intv, $value) { - $intv->set($value); - }; - }; - - $intv->set(null); - self::assertNull($intv->get()); - self::assertNull($int); - self::assertSame("", $intv->format()); - - $intv->set(""); - self::assertNull($intv->get()); - self::assertNull($int); - self::assertSame("", $intv->format()); - - $intv->set(" "); - self::assertNull($intv->get()); - self::assertNull($int); - self::assertSame("", $intv->format()); - - $intv->set(12); - self::assertSame(12, $intv->get()); - self::assertSame(12, $int); - self::assertSame("12", $intv->format()); - self::assertSame("0012", $intv->format("%04u")); - - $intv->set("12"); - self::assertSame(12, $int); - - $intv->set(" 12 "); - self::assertSame(12, $int); - - $intv->set(true); - self::assertSame(1, $int); - - // valeur non requise donc retourne null - $intv->set(false); - self::assertNull($intv->get()); - - self::assertException(Exception::class, $intvSetter("a")); - self::assertException(Exception::class, $intvSetter([])); - self::assertException(Exception::class, $intvSetter(["a"])); - } - - function testRequiredNint() { - /** @var ScalarValue $intv */ - Schema::nv($intv, $int, null, $schema, [ - "?int", null, - "required" => true, - ]); - $intvSetter = function($value) use($intv) { - return function() use($intv, $value) { - $intv->set($value); - }; - }; - - $intv->set(null); - self::assertNull($intv->get()); - self::assertNull($int); - self::assertSame("", $intv->format()); - - $intv->set(""); - self::assertNull($intv->get()); - self::assertNull($int); - self::assertSame("", $intv->format()); - - $intv->set(" "); - self::assertNull($intv->get()); - self::assertNull($int); - self::assertSame("", $intv->format()); - - $intv->set(12); - self::assertSame(12, $intv->get()); - self::assertSame(12, $int); - self::assertSame("12", $intv->format()); - self::assertSame("0012", $intv->format("%04u")); - - $intv->set("12"); - self::assertSame(12, $int); - - $intv->set(" 12 "); - self::assertSame(12, $int); - - $intv->set(true); - self::assertSame(1, $int); - - // valeur requise donc lance une exception - self::assertException(Exception::class, $intvSetter(false)); - - self::assertException(Exception::class, $intvSetter("a")); - self::assertException(Exception::class, $intvSetter([])); - self::assertException(Exception::class, $intvSetter(["a"])); - } - - function testUnionTypes() { - ## l'ordre des types doit être respecté - - # string puis int - /** @var ScalarValue $siv */ - Schema::nv($siv, $si, null, $sis, "string|int"); - - $siv->set("12"); - self::assertSame("12", $si); - $siv->set(12); - self::assertSame(12, $si); - - # int puis string - Schema::nv($isv, $is, null, $iss, "int|string"); - - $isv->set("12"); - self::assertSame("12", $is); - $isv->set(12); - self::assertSame(12, $is); - } -} diff --git a/tests/schema/types/boolTest.php b/tests/schema/types/boolTest.php new file mode 100644 index 0000000..82dd766 --- /dev/null +++ b/tests/schema/types/boolTest.php @@ -0,0 +1,111 @@ +set(true); + self::assertSame(true, $destv->get()); + self::assertSame(true, $dest); + self::assertSame("Oui", $destv->format()); + self::assertSame("Oui", $destv->format("OuiNonNull")); + self::assertSame("O", $destv->format("ON")); + self::assertSame("O", $destv->format("ONN")); + + $destv->set(false); + self::assertSame(false, $destv->get()); + self::assertSame(false, $dest); + self::assertSame("Non", $destv->format()); + self::assertSame("Non", $destv->format("OuiNonNull")); + self::assertSame("N", $destv->format("ON")); + self::assertSame("N", $destv->format("ONN")); + + $destv->set("yes"); + self::assertSame(true, $destv->get()); + + $destv->set(" yes "); + self::assertSame(true, $destv->get()); + + $destv->set("12"); + self::assertSame(true, $destv->get()); + + $destv->set(12); + self::assertSame(true, $destv->get()); + + $destv->set("no"); + self::assertSame(false, $destv->get()); + + $destv->set(" no "); + self::assertSame(false, $destv->get()); + + $destv->set("0"); + self::assertSame(false, $destv->get()); + + $destv->set(0); + self::assertSame(false, $destv->get()); + + $destv->set(12.34); + self::assertSame(true, $destv->get()); + + self::assertException(Exception::class, $destvSetter("a")); + self::assertException(Exception::class, $destvSetter([])); + self::assertException(Exception::class, $destvSetter(["a"])); + + } + + function testBool() { + /** @var ScalarValue $destv */ + Schema::nv($destv, $dest, null, $schema, "bool"); + $destvSetter = function($value) use($destv) { + return function() use($destv, $value) { + $destv->set($value); + }; + }; + + self::assertException(Exception::class, $destvSetter(null)); + self::assertException(Exception::class, $destvSetter("")); + self::assertException(Exception::class, $destvSetter(" ")); + + $this->commonTests($destv, $dest, $destvSetter); + } + + function testNbool() { + /** @var ScalarValue $destv */ + Schema::nv($destv, $dest, null, $schema, "?bool"); + $destvSetter = function($value) use($destv) { + return function() use($destv, $value) { + $destv->set($value); + }; + }; + + $destv->set(null); + self::assertNull($destv->get()); + self::assertNull($dest); + self::assertSame("Non", $destv->format()); + self::assertSame("", $destv->format("OuiNonNull")); + self::assertSame("N", $destv->format("ON")); + self::assertSame("", $destv->format("ONN")); + + $destv->set(""); + self::assertNull($destv->get()); + self::assertNull($dest); + self::assertSame("Non", $destv->format()); + self::assertSame("", $destv->format("OuiNonNull")); + self::assertSame("N", $destv->format("ON")); + self::assertSame("", $destv->format("ONN")); + + $destv->set(" "); + self::assertNull($destv->get()); + self::assertNull($dest); + self::assertSame("Non", $destv->format()); + self::assertSame("", $destv->format("OuiNonNull")); + self::assertSame("N", $destv->format("ON")); + self::assertSame("", $destv->format("ONN")); + + $this->commonTests($destv, $dest, $destvSetter); + } +} diff --git a/tests/schema/types/floatTest.php b/tests/schema/types/floatTest.php new file mode 100644 index 0000000..225fb08 --- /dev/null +++ b/tests/schema/types/floatTest.php @@ -0,0 +1,139 @@ +set(12); + self::assertSame(12.0, $destv->get()); + self::assertSame(12.0, $dest); + self::assertSame("12", $destv->format()); + self::assertSame("0012", $destv->format("%04u")); + + $destv->set("12"); + self::assertSame(12.0, $destv->get()); + + $destv->set(" 12 "); + self::assertSame(12.0, $destv->get()); + + $destv->set(12.34); + self::assertSame(12.34, $destv->get()); + + $destv->set(true); + self::assertSame(1.0, $destv->get()); + + self::assertException(Exception::class, $destvSetter("a")); + self::assertException(Exception::class, $destvSetter([])); + self::assertException(Exception::class, $destvSetter(["a"])); + } + + function testFloat() { + /** @var ScalarValue $destv */ + Schema::nv($destv, $dest, null, $schema, "float"); + $destvSetter = function($value) use($destv) { + return function() use($destv, $value) { + $destv->set($value); + }; + }; + + self::assertException(Exception::class, $destvSetter(null)); + self::assertException(Exception::class, $destvSetter("")); + self::assertException(Exception::class, $destvSetter(" ")); + + // valeur non requise donc retourne null + $destv->set(false); + self::assertNull($destv->get()); + + $this->commonTests($destv, $dest, $destvSetter); + } + + function testRequiredFloat() { + /** @var ScalarValue $destv */ + Schema::nv($destv, $dest, null, $schema, [ + "float", null, + "required" => true, + ]); + $destvSetter = function($value) use($destv) { + return function() use($destv, $value) { + $destv->set($value); + }; + }; + + self::assertException(Exception::class, $destvSetter(null)); + self::assertException(Exception::class, $destvSetter("")); + self::assertException(Exception::class, $destvSetter(" ")); + + // valeur requise donc lance une exception + self::assertException(Exception::class, $destvSetter(false)); + + $this->commonTests($destv, $dest, $destvSetter); + } + + function testNfloat() { + /** @var ScalarValue $destv */ + Schema::nv($destv, $dest, null, $schema, "?float"); + $destvSetter = function($value) use($destv) { + return function() use($destv, $value) { + $destv->set($value); + }; + }; + + $destv->set(null); + self::assertNull($destv->get()); + self::assertNull($dest); + self::assertSame("", $destv->format()); + + $destv->set(""); + self::assertNull($destv->get()); + self::assertNull($dest); + self::assertSame("", $destv->format()); + + $destv->set(" "); + self::assertNull($destv->get()); + self::assertNull($dest); + self::assertSame("", $destv->format()); + + // valeur non requise donc retourne null + $destv->set(false); + self::assertNull($destv->get()); + + $this->commonTests($destv, $dest, $destvSetter); + } + + function testRequiredNfloat() { + /** @var ScalarValue $destv */ + Schema::nv($destv, $dest, null, $schema, [ + "?float", null, + "required" => true, + ]); + $destvSetter = function($value) use($destv) { + return function() use($destv, $value) { + $destv->set($value); + }; + }; + + $destv->set(null); + self::assertNull($destv->get()); + self::assertNull($dest); + self::assertSame("", $destv->format()); + + $destv->set(""); + self::assertNull($destv->get()); + self::assertNull($dest); + self::assertSame("", $destv->format()); + + $destv->set(" "); + self::assertNull($destv->get()); + self::assertNull($dest); + self::assertSame("", $destv->format()); + + // valeur requise donc lance une exception + self::assertException(Exception::class, $destvSetter(false)); + + $this->commonTests($destv, $dest, $destvSetter); + } +} diff --git a/tests/schema/types/intTest.php b/tests/schema/types/intTest.php new file mode 100644 index 0000000..4ca3b5a --- /dev/null +++ b/tests/schema/types/intTest.php @@ -0,0 +1,139 @@ +set(12); + self::assertSame(12, $destv->get()); + self::assertSame(12, $dest); + self::assertSame("12", $destv->format()); + self::assertSame("0012", $destv->format("%04u")); + + $destv->set("12"); + self::assertSame(12, $destv->get()); + + $destv->set(" 12 "); + self::assertSame(12, $destv->get()); + + $destv->set(12.34); + self::assertSame(12, $destv->get()); + + $destv->set(true); + self::assertSame(1, $destv->get()); + + self::assertException(Exception::class, $destvSetter("a")); + self::assertException(Exception::class, $destvSetter([])); + self::assertException(Exception::class, $destvSetter(["a"])); + } + + function testInt() { + /** @var ScalarValue $destv */ + Schema::nv($destv, $dest, null, $schema, "int"); + $destvSetter = function($value) use($destv) { + return function() use($destv, $value) { + $destv->set($value); + }; + }; + + self::assertException(Exception::class, $destvSetter(null)); + self::assertException(Exception::class, $destvSetter("")); + self::assertException(Exception::class, $destvSetter(" ")); + + // valeur non requise donc retourne null + $destv->set(false); + self::assertNull($destv->get()); + + $this->commonTests($destv, $dest, $destvSetter); + } + + function testRequiredInt() { + /** @var ScalarValue $destv */ + Schema::nv($destv, $dest, null, $schema, [ + "int", null, + "required" => true, + ]); + $destvSetter = function($value) use($destv) { + return function() use($destv, $value) { + $destv->set($value); + }; + }; + + self::assertException(Exception::class, $destvSetter(null)); + self::assertException(Exception::class, $destvSetter("")); + self::assertException(Exception::class, $destvSetter(" ")); + + // valeur requise donc lance une exception + self::assertException(Exception::class, $destvSetter(false)); + + $this->commonTests($destv, $dest, $destvSetter); + } + + function testNint() { + /** @var ScalarValue $destv */ + Schema::nv($destv, $dest, null, $schema, "?int"); + $destvSetter = function($value) use($destv) { + return function() use($destv, $value) { + $destv->set($value); + }; + }; + + $destv->set(null); + self::assertNull($destv->get()); + self::assertNull($dest); + self::assertSame("", $destv->format()); + + $destv->set(""); + self::assertNull($destv->get()); + self::assertNull($dest); + self::assertSame("", $destv->format()); + + $destv->set(" "); + self::assertNull($destv->get()); + self::assertNull($dest); + self::assertSame("", $destv->format()); + + // valeur non requise donc retourne null + $destv->set(false); + self::assertNull($destv->get()); + + $this->commonTests($destv, $dest, $destvSetter); + } + + function testRequiredNint() { + /** @var ScalarValue $destv */ + Schema::nv($destv, $dest, null, $schema, [ + "?int", null, + "required" => true, + ]); + $destvSetter = function($value) use($destv) { + return function() use($destv, $value) { + $destv->set($value); + }; + }; + + $destv->set(null); + self::assertNull($destv->get()); + self::assertNull($dest); + self::assertSame("", $destv->format()); + + $destv->set(""); + self::assertNull($destv->get()); + self::assertNull($dest); + self::assertSame("", $destv->format()); + + $destv->set(" "); + self::assertNull($destv->get()); + self::assertNull($dest); + self::assertSame("", $destv->format()); + + // valeur requise donc lance une exception + self::assertException(Exception::class, $destvSetter(false)); + + $this->commonTests($destv, $dest, $destvSetter); + } +} diff --git a/tests/schema/types/strTest.php b/tests/schema/types/strTest.php new file mode 100644 index 0000000..c871afa --- /dev/null +++ b/tests/schema/types/strTest.php @@ -0,0 +1,123 @@ +set(""); + self::assertSame("", $destv->get()); + self::assertSame("", $dest); + + $destv->set(" "); + self::assertSame(" ", $destv->get()); + self::assertSame(" ", $dest); + + $destv->set("a"); + self::assertSame("a", $destv->get()); + self::assertSame("a", $dest); + + $destv->set("12"); + self::assertSame("12", $destv->get()); + + $destv->set(" 12 "); + self::assertSame(" 12 ", $destv->get()); + + $destv->set(12); + self::assertSame("12", $destv->get()); + + $destv->set(12.34); + self::assertSame("12.34", $destv->get()); + + $destv->set(true); + self::assertSame("1", $destv->get()); + + self::assertException(Exception::class, $destvSetter([])); + self::assertException(Exception::class, $destvSetter(["a"])); + } + + function testStr() { + /** @var ScalarValue $destv */ + Schema::nv($destv, $dest, null, $schema, "string"); + $destvSetter = function($value) use($destv) { + return function() use($destv, $value) { + $destv->set($value); + }; + }; + + self::assertException(Exception::class, $destvSetter(null)); + + // valeur non requise donc retourne null + $destv->set(false); + self::assertNull($destv->get()); + + $this->commonTests($destv, $dest, $destvSetter); + } + + function testRequiredStr() { + /** @var ScalarValue $destv */ + Schema::nv($destv, $dest, null, $schema, [ + "string", null, + "required" => true, + ]); + $destvSetter = function($value) use($destv) { + return function() use($destv, $value) { + $destv->set($value); + }; + }; + + self::assertException(Exception::class, $destvSetter(null)); + + // valeur requise donc lance une exception + self::assertException(Exception::class, $destvSetter(false)); + + $this->commonTests($destv, $dest, $destvSetter); + } + + function testNstr() { + /** @var ScalarValue $destv */ + Schema::nv($destv, $dest, null, $schema, "?string"); + $destvSetter = function($value) use($destv) { + return function() use($destv, $value) { + $destv->set($value); + }; + }; + + $destv->set(null); + self::assertNull($destv->get()); + self::assertNull($dest); + self::assertSame("", $destv->format()); + + // valeur non requise donc retourne null + $destv->set(false); + self::assertNull($destv->get()); + + $this->commonTests($destv, $dest, $destvSetter); + } + + function testRequiredNstr() { + /** @var ScalarValue $destv */ + Schema::nv($destv, $dest, null, $schema, [ + "?string", null, + "required" => true, + ]); + $destvSetter = function($value) use($destv) { + return function() use($destv, $value) { + $destv->set($value); + }; + }; + + $destv->set(null); + self::assertNull($destv->get()); + self::assertNull($dest); + self::assertSame("", $destv->format()); + + // valeur requise donc lance une exception + self::assertException(Exception::class, $destvSetter(false)); + + $this->commonTests($destv, $dest, $destvSetter); + } +} diff --git a/tests/schema/types/unionTest.php b/tests/schema/types/unionTest.php new file mode 100644 index 0000000..048d088 --- /dev/null +++ b/tests/schema/types/unionTest.php @@ -0,0 +1,29 @@ +set("12"); + self::assertSame("12", $si); + $siv->set(12); + self::assertSame(12, $si); + + # int puis string + Schema::nv($isv, $is, null, $iss, "int|string"); + + $isv->set("12"); + self::assertSame("12", $is); + $isv->set(12); + self::assertSame(12, $is); + } +}