From 9d6e7f3955e0a52b4cde66dd986b48f4855b19fa Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Wed, 22 Oct 2025 08:17:17 +0400 Subject: [PATCH 1/4] modifs.mineures sans commentaires --- php/src/mail/mailer.php | 41 ++++++++++++----------------------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/php/src/mail/mailer.php b/php/src/mail/mailer.php index d11eb34..ac2e9ad 100644 --- a/php/src/mail/mailer.php +++ b/php/src/mail/mailer.php @@ -6,38 +6,26 @@ use nulib\cl; use nulib\cv; use nulib\exceptions; use nulib\output\msg; +use nulib\php\types\vbool; use nulib\str; use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\SMTP; class mailer { private static function is_bool(&$value): bool { - if ($value === null) { - return false; - } elseif (is_bool($value)) { + if ($value === null) return false; + elseif (is_bool($value)) return true; + elseif (is_numeric($value)) { + $value = $value != 0; return true; - } elseif (is_int($value)) { - $value = boolval($value); + } elseif (vbool::is_yes($value)) { + $value = true; + return true; + } elseif ($value === "" || vbool::is_no($value)) { + $value = false; return true; - } else { - switch (strval($value)) { - case "": - case "0": - case "no": - case "off": - case "false": - $value = false; - return true; - case "1": - case "yes": - case "on": - case "true": - $value = true; - return true; - default: - return false; - } } + return false; } private static function get_bool($value): bool { @@ -120,19 +108,14 @@ class mailer { $mailer->SMTPDebug = $debug; # auth, username, password $username = $params["username"] ?? null; - $username ??= cv::vn(getenv("NULIB_MAIL_USERNAME")); $password = $params["password"] ?? null; - $password ??= cv::vn(getenv("NULIB_MAIL_PASSWORD")); $auth = $params["auth"] ?? null; - $auth ??= cv::vn(getenv("NULIB_MAIL_AUTH")); $auth ??= $username !== null && $password !== null; $mailer->SMTPAuth = self::get_bool($auth); $mailer->Username = $username; $mailer->Password = $password; # secure - $secure = $params["secure"] ?? null; - $secure ??= cv::vn(getenv("NULIB_MAIL_SECURE")); - $secure ??= false; + $secure = $params["secure"] ?? false; if (self::is_bool($secure)) { if (!$secure) { $mailer->SMTPSecure = ""; From 4f0d6d40dcbe90eb717cb9fc6c0c366f2825ce54 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Wed, 22 Oct 2025 13:55:13 +0400 Subject: [PATCH 2/4] function isa() pour les vclasses --- php/src/php/types/varray.php | 5 +++++ php/src/php/types/vbool.php | 6 ++++++ php/src/php/types/vcontent.php | 5 +++++ php/src/php/types/vfloat.php | 5 +++++ php/src/php/types/vfunc.php | 5 +++++ php/src/php/types/vint.php | 5 +++++ php/src/php/types/vkey.php | 5 +++++ php/src/php/types/vpkey.php | 5 +++++ php/src/php/types/vrawstring.php | 5 +++++ 9 files changed, 46 insertions(+) diff --git a/php/src/php/types/varray.php b/php/src/php/types/varray.php index 3a6b416..210590f 100644 --- a/php/src/php/types/varray.php +++ b/php/src/php/types/varray.php @@ -4,6 +4,11 @@ namespace nulib\php\types; use nulib\cl; class varray { + static function isa($value, bool $strict=false) : bool { + if ($strict) return is_array($value); + else return is_scalar($value); + } + static function ensure(&$array): void { if (!is_array($array)) $array = cl::with($array); } diff --git a/php/src/php/types/vbool.php b/php/src/php/types/vbool.php index ab9a1da..3787fef 100644 --- a/php/src/php/types/vbool.php +++ b/php/src/php/types/vbool.php @@ -30,6 +30,12 @@ class vbool { return in_array($value, self::NO_VALUES, true); } + static function isa($value, bool $strict=false) : bool { + if ($strict) return is_bool($value); + elseif (is_string($value)) return self::is_yes($value) || self::is_no($value); + else return is_scalar($value); + } + static function ensure(&$bool): void { if (is_string($bool)) { if (self::is_yes($bool)) $bool = true; diff --git a/php/src/php/types/vcontent.php b/php/src/php/types/vcontent.php index cfb5b77..8596979 100644 --- a/php/src/php/types/vcontent.php +++ b/php/src/php/types/vcontent.php @@ -2,6 +2,11 @@ namespace nulib\php\types; class vcontent { + static function isa($value, bool $strict=false) : bool { + if ($strict) return is_array($value) || is_string($value); + else return is_array($value) || is_scalar($value); + } + static function ensure(&$content): void { if ($content === null || $content === false) $content = []; elseif (!is_string($content) && !is_array($content)) $content = strval($content); diff --git a/php/src/php/types/vfloat.php b/php/src/php/types/vfloat.php index 3233b73..13d5c7c 100644 --- a/php/src/php/types/vfloat.php +++ b/php/src/php/types/vfloat.php @@ -2,6 +2,11 @@ namespace nulib\php\types; class vfloat { + static function isa($value, bool $strict=false) : bool { + if ($strict) return is_float($value); + else return is_numeric($value); + } + static function ensure(&$float): void { if (!is_float($float)) $float = floatval($float); } diff --git a/php/src/php/types/vfunc.php b/php/src/php/types/vfunc.php index ec690bf..bcde965 100644 --- a/php/src/php/types/vfunc.php +++ b/php/src/php/types/vfunc.php @@ -4,6 +4,11 @@ namespace nulib\php\types; use nulib\php\func; class vfunc { + static function isa($value, bool $strict=false) : bool { + if ($strict) return $value instanceof func; + else return func::is_callable($value); + } + static function ensure(&$func): void { $func = func::ensure($func); } diff --git a/php/src/php/types/vint.php b/php/src/php/types/vint.php index 6d5ed4c..74e8b6a 100644 --- a/php/src/php/types/vint.php +++ b/php/src/php/types/vint.php @@ -2,6 +2,11 @@ namespace nulib\php\types; class vint { + static function isa($value, bool $strict=false) : bool { + if ($strict) return is_int($value); + else return is_numeric($value); + } + static function ensure(&$int): void { if (!is_int($int)) $int = intval($int); } diff --git a/php/src/php/types/vkey.php b/php/src/php/types/vkey.php index 87a8402..0769bfb 100644 --- a/php/src/php/types/vkey.php +++ b/php/src/php/types/vkey.php @@ -2,6 +2,11 @@ namespace nulib\php\types; class vkey { + static function isa($value, bool $strict=false) : bool { + if ($strict) return is_int($value) || is_string($value); + else return is_scalar($value); + } + static function ensure(&$key): void { if ($key === null) $key = ""; elseif ($key === false) $key = 0; diff --git a/php/src/php/types/vpkey.php b/php/src/php/types/vpkey.php index 318c7bb..27c8ef6 100644 --- a/php/src/php/types/vpkey.php +++ b/php/src/php/types/vpkey.php @@ -2,6 +2,11 @@ namespace nulib\php\types; class vpkey { + static function isa($value, bool $strict=false) : bool { + if ($strict) return is_array($value) || is_int($value) || is_string($value); + else return is_array($value) || is_scalar($value); + } + static function ensure(&$pkey): void { if ($pkey === null) $pkey = ""; elseif ($pkey === false) $pkey = 0; diff --git a/php/src/php/types/vrawstring.php b/php/src/php/types/vrawstring.php index 463aba3..28f1ff8 100644 --- a/php/src/php/types/vrawstring.php +++ b/php/src/php/types/vrawstring.php @@ -9,6 +9,11 @@ class vrawstring { /** @var bool faut-il normaliser les caractères fin de ligne */ const NORM_NL = false; + static function isa($value, bool $strict=false) : bool { + if ($strict) return is_string($value); + else return is_scalar($value); + } + static function ensure(&$string): void { if (!is_string($string)) $string = strval($string); if (static::TRIM) $string = trim($string); From efb4f037ecfb049aca3a5a96935689beaa5f7420 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Wed, 22 Oct 2025 15:42:52 +0400 Subject: [PATCH 3/4] importation Hour et Time et d'autres vclasses --- php/src/php/time/Hour.php | 16 ++ php/src/php/time/Time.php | 288 ++++++++++++++++++++++++++++++++ php/src/php/types/vdate.php | 29 ++++ php/src/php/types/vdatetime.php | 29 ++++ php/src/php/types/vmixed.php | 22 +++ php/src/php/types/vraw.php | 22 +++ php/src/php/types/vtime.php | 30 ++++ php/tests/php/time/HourTest.php | 60 +++++++ php/tests/php/time/TimeTest.php | 74 ++++++++ 9 files changed, 570 insertions(+) create mode 100644 php/src/php/time/Hour.php create mode 100644 php/src/php/time/Time.php create mode 100644 php/src/php/types/vdate.php create mode 100644 php/src/php/types/vdatetime.php create mode 100644 php/src/php/types/vmixed.php create mode 100644 php/src/php/types/vraw.php create mode 100644 php/src/php/types/vtime.php create mode 100644 php/tests/php/time/HourTest.php create mode 100644 php/tests/php/time/TimeTest.php diff --git a/php/src/php/time/Hour.php b/php/src/php/time/Hour.php new file mode 100644 index 0000000..72be43e --- /dev/null +++ b/php/src/php/time/Hour.php @@ -0,0 +1,16 @@ +getSeconds(); + } elseif (is_int($time)) { + return $time * $unit; + } elseif (is_string($time)) { + $matched = false; + foreach (self::PATTERNS as $pattern) { + if (preg_match($pattern, $time, $ms)) { + $matched = true; + break; + } + } + if ($matched) { + $h = $ms[1]; + $m = $ms[2] ?? 0; + $s = $ms[3] ?? 0; + return intval($h) * 3600 + intval($m) * 60 + intval($s); + } + } elseif ($time instanceof DateTimeInterface) { + $hms = $time->format('His'); + return intval(substr($hms, 0, 2)) * 3600 + + intval(substr($hms, 2, 2)) * 60 + + intval(substr($hms, 4, 2)); + } elseif (is_array($time) && count($time) == 3) { + [$h, $m, $s] = $time; + return $h * 3600 + $m * 60 + $s; + } + throw exceptions::invalid_value($time, "time"); + } + + protected static function s_adjust(int &$seconds, int $unit=self::UNIT_SECONDS, ?int $step=null): int { + if ($step !== null) $unit *= $step; + $adjust = $seconds % $unit; + if ($seconds < 0) $adjust = -$adjust; + $seconds -= $adjust; + return $seconds; + } + + protected static function s_wrap_start(int &$seconds): int { + while ($seconds < 0) $seconds += 86400; + if ($seconds >= 86400) $seconds %= 86400; + return $seconds; + } + + protected static function s_wrap_end(int &$seconds): int { + while ($seconds < 0) $seconds += 86400; + if ($seconds > 86400) $seconds %= 86400; + return $seconds; + } + + /** + * @var int la valeur de l'unité en secondes, pour le constructeur et les + * méthodes {@link setu()}, {@link addu()} et {@link subu()} + */ + const UNIT = self::UNIT_SECONDS; + + /** + * @var int|null un nombre d'unité dont l'heure doit être multiple. par + * exemple, si l'unité est la minute, une valeur 5 permet d'avoir des heures + * qui vont de 5 en 5 minutes (0h00, 0h05, 0h10, etc.) + */ + const STEP = null; + + /** @var bool s'il faut garder les heures dans la plage [0, 24h] */ + const WRAP = true; + + function __construct($time=null, ?array $params=null) { + $this->unit = vint::with($params["unit"] ?? static::UNIT); + $this->step = vint::withn($params["step"] ?? self::STEP); + $this->wrap = vbool::with($params["wrap"] ?? self::WRAP); + if ($time === null) $seconds = self::s_now(); + else $seconds = self::s_get($time, $this->unit); + $this->setSeconds($seconds); + } + + protected int $unit; + + protected ?int $step; + + protected bool $wrap; + + protected int $seconds; + + function getSeconds(): int { + return $this->seconds; + } + + /** + * mettre à jour cet objet avec le nombre de secondes spécifié + * + * le nombre effectif de secondes est calculé en tenant compte de l'unité + * actuelle + * + * @return int le nombre de seconde effectif, après correction + */ + protected function setSeconds(?int $seconds): int { + $this->seconds = $seconds ?? self::s_now(); + return $this->afterUpdate(); + } + + protected function afterUpdate(): int { + self::s_adjust($this->seconds, $this->unit, $this->step); + if ($this->wrap) $this->wrapEnd(); + return $this->seconds; + } + + /** + * wrapper l'heure pour la garder dans la plage [0h, 24h[ ce qui la rend + * propice à l'utilisation comme borne inférieure d'une période + */ + function wrapStart(): self { + self::s_wrap_start($this->seconds); + return $this; + } + + /** + * wrapper l'heure pour la garder dans la plage [0h, 24h] ce qui la rend + * propice à l'utilisation comme borne supérieure d'une période + */ + function wrapEnd(): self { + self::s_wrap_end($this->seconds); + return $this; + } + + /** formatter cette heure pour affichage */ + function format(?string $format=null): string { + if ($format === null) $format = static::FORMAT; + $v = $this->seconds; + $h = intdiv($v, 3600); $v = $v % 3600; + $m = intdiv($v, 60); + $s = $v % 60; + $searches = [ + "%H", "%h", + "%M", "%m", + "%S", "%s", + "%%", + ]; + $replaces = [ + sprintf("%02u", $h), strval($h), + sprintf("%02u", $m), strval($m), + sprintf("%02u", $s), strval($s), + "%", + ]; + return str_replace($searches, $replaces, $format); + } + + function __toString(): string { + return $this->format(); + } + + /** @return int le nombre d'unités */ + function getu(): int { + return intdiv($this->seconds, $this->unit); + } + + /** créer une nouvelle heure avec le nombre d'unités spécifiées */ + function setu(int $count): self { + $this->setSeconds($count * $this->unit); + return $this; + } + + /** créer une nouvelle heure en ajoutant à cette heure le nombre d'unités spécifiées */ + function addu(int $count=1): self { + $count *= $this->unit; + if ($this->step !== null) $count *= $this->step; + $this->setSeconds($this->seconds + $count); + return $this; + } + + /** créer une nouvelle heure en soustrayant à cette heure le nombre d'unités spécifiées */ + function subu(int $count=1): self { + $count *= $this->unit; + if ($this->step !== null) $count *= $this->step; + $this->setSeconds($this->seconds - $count); + return $this; + } + + /** forcer cette heure à l'heure spécifiée */ + function set($time): self { + if ($time === null) $seconds = self::s_now(); + else $seconds = self::with($time)->getSeconds(); + $this->setSeconds($seconds); + return $this; + } + + /** ajouter à cette heure l'heure spécifiée */ + function add($time): self { + if ($time !== null) { + $this->setSeconds($this->seconds + self::with($time)->getSeconds()); + } + return $this; + } + + /** soustraire à cette heure l'heure spécifiée */ + function sub($time): self { + if ($time !== null) { + $this->setSeconds($this->seconds - self::with($time)->getSeconds()); + } + return $this; + } + + /** + * comparer avec l'heure spécifiée. retourner une valeur négative, égale à + * zéro ou positive suivant le résultat de la comparaison + */ + function compare($time): int { + if ($time === null) return 1; + else return $this->seconds - self::with($time)->getSeconds(); + } + + /** + * tester si cette heure est avant ou égale à l'heure spécifiée + */ + function before($other): bool { + if ($other === null) return false; + else return $this->seconds <= self::with($other)->getSeconds(); + } + + /** + * tester si cette heure est après ou égale à l'heure spécifiée + */ + function after($other): bool { + if ($other === null) return true; + else return $this->seconds >= self::with($other)->getSeconds(); + } +} diff --git a/php/src/php/types/vdate.php b/php/src/php/types/vdate.php new file mode 100644 index 0000000..3f102f7 --- /dev/null +++ b/php/src/php/types/vdate.php @@ -0,0 +1,29 @@ + false, + ]))); + self::assertSame("7h11", strval(new Hour("30:70:80"))); + + self::assertException(ValueException::class, function() { + return strval(new Hour("bad format")); + }); + } + + function testFormat() { + self::assertSame("0h", (new Hour(0))->format()); + self::assertSame("0h56", (new Hour(56))->format()); + self::assertSame("2h", (new Hour(120))->format()); + self::assertSame("23h59", (new Hour(1439))->format()); + self::assertSame("24h", (new Hour(1440))->format()); + self::assertSame("0h01", (new Hour(1441))->format()); + } + + function testStep() { + $h = new Hour(null, [ + "step" => 5, + ]); + $h->setu(10); self::assertSame("0h10", strval($h)); + $h->setu(12); self::assertSame("0h10", strval($h)); + $h->setu(15); self::assertSame("0h15", strval($h)); + $h->setu(17); self::assertSame("0h15", strval($h)); + + $h->set("8h"); + $h->addu(); self::assertSame("8h05", strval($h)); + $h->addu(); self::assertSame("8h10", strval($h)); + $h->addu(); self::assertSame("8h15", strval($h)); + $h->subu(); self::assertSame("8h10", strval($h)); + $h->subu(); self::assertSame("8h05", strval($h)); + $h->subu(); self::assertSame("8h", strval($h)); + } +} diff --git a/php/tests/php/time/TimeTest.php b/php/tests/php/time/TimeTest.php new file mode 100644 index 0000000..998b0cb --- /dev/null +++ b/php/tests/php/time/TimeTest.php @@ -0,0 +1,74 @@ + false, + ]))); + self::assertSame("07:11:20", strval(new Time("30:70:80"))); + + self::assertException(ValueException::class, function() { + return strval(new Time("bad format")); + }); + } + + function testGetu() { + self::assertSame(0, (new Time(0))->getu()); + self::assertSame(86399, (new Time(-1))->getu()); + self::assertSame(1, (new Time(1))->getu()); + self::assertSame(120, (new Time(120))->getu()); + self::assertSame(86400, (new Time(86400))->getu()); + self::assertSame(0, (new Time(-86400))->getu()); + } + + function testAddu() { + $t = new Time(0); + $t->addu(0); self::assertSame(0, $t->getu()); + $t->addu(10); self::assertSame(10, $t->getu()); + $t->addu(10); self::assertSame(20, $t->getu()); + $t->addu(100); self::assertSame(120, $t->getu()); + $t->addu(86280); self::assertSame(86400, $t->getu()); + $t->addu(86400); self::assertSame(0, $t->getu()); + $t->addu(-86400); self::assertSame(0, $t->getu()); + } + + function testSubu() { + $t = new Time(0); + $t->subu(-86400); self::assertSame(86400, $t->getu()); + $t->subu(86400); self::assertSame(0, $t->getu()); + + $t = new Time(120); + $t->subu(100); self::assertSame(20, $t->getu()); + $t->subu(10); self::assertSame(10, $t->getu()); + $t->subu(10); self::assertSame(0, $t->getu()); + $t->subu(0); self::assertSame(0, $t->getu()); + } + + function testFormat() { + self::assertSame("00:00:00", (new Time(0))->format()); + self::assertSame("00:00:56", (new Time(56))->format()); + self::assertSame("00:02:00", (new Time(120))->format()); + self::assertSame("23:59:59", (new Time(86399))->format()); + self::assertSame("24:00:00", (new Time(86400))->format()); + self::assertSame("00:00:01", (new Time(86401))->format()); + } +} From 5e41e7d5e0d9eff294e57c5275f27a8893deae86 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Wed, 22 Oct 2025 17:42:08 +0400 Subject: [PATCH 4/4] =?UTF-8?q?gestion=20simplifi=C3=A9e=20des=20sch=C3=A9?= =?UTF-8?q?ma?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- php/src/php/types/_schema.php | 58 ++++++++++++++++++++ php/src/php/types/assoc.php | 75 +++++++++++++++++++++++++ php/src/php/types/scalar.php | 34 ++++++++++++ php/src/php/types/varray.php | 6 +- php/src/php/types/vbool.php | 13 ++++- php/src/php/types/vcontent.php | 19 ++++++- php/src/php/types/vfloat.php | 7 ++- php/src/php/types/vint.php | 7 ++- php/src/php/types/vkey.php | 6 +- php/src/php/types/vpkey.php | 12 +++- php/src/php/types/vrawstring.php | 9 ++- php/tests/php/types/assocTest.php | 88 ++++++++++++++++++++++++++++++ php/tests/php/types/scalarTest.php | 60 ++++++++++++++++++++ 13 files changed, 381 insertions(+), 13 deletions(-) create mode 100644 php/src/php/types/_schema.php create mode 100644 php/src/php/types/assoc.php create mode 100644 php/src/php/types/scalar.php create mode 100644 php/tests/php/types/assocTest.php create mode 100644 php/tests/php/types/scalarTest.php diff --git a/php/src/php/types/_schema.php b/php/src/php/types/_schema.php new file mode 100644 index 0000000..e0cc6e9 --- /dev/null +++ b/php/src/php/types/_schema.php @@ -0,0 +1,58 @@ + vrawstring::class, + "string" => vstring::class, + "text" => vtext::class, + "bool" => vbool::class, + "int" => vint::class, + "float" => vfloat::class, + "array" => varray::class, + "func" => vfunc::class, + "raw" => vraw::class, + "mixed" => vmixed::class, + "key" => vkey::class, + "pkey" => vpkey::class, + "content" => vcontent::class, + "datetime" => vdatetime::class, + "date" => vdate::class, + "time" => vtime::class, + ]; + + static function get_types($schema, &$default = null, ?bool &$required = null): array { + if (is_array($schema)) { + $types = $schema["type"] ?? $schema[0] ?? null; + $default = $schema["default"] ?? $schema[1] ?? null; + $required = vbool::with($schema["required"] ?? false); + } elseif (is_string($schema)) { + $types = $schema; + $default = null; + $required = false; + } else { + throw exceptions::invalid_value($schema, "schema"); + } + if (is_string($types)) { + $types = explode(",", $types); + } elseif (!is_array($types)) { + throw exceptions::invalid_value($types, "types"); + } + return $types; + } + + static function get_vclass(array $types, ?bool &$nullable): ?string { + foreach ($types as $type) { + $vclass = self::VCLASSES[$type] ?? null; + if ($vclass !== null) { + $nullable = str::del_prefix($type, "?"); + return $vclass; + } + } + return null; + } +} diff --git a/php/src/php/types/assoc.php b/php/src/php/types/assoc.php new file mode 100644 index 0000000..5380296 --- /dev/null +++ b/php/src/php/types/assoc.php @@ -0,0 +1,75 @@ + $kschema) { + $types = _schema::get_types($kschema, $default, $required); + $exists = array_key_exists($key, $array); + if (!$exists) { + if ($required) return false; + else continue; + } + $vclass = _schema::get_vclass($types, $nullable); + # le test échoue si le type n'est pas supporté + if ($vclass === null) return false; + $value = $array[$key]; + if ($value === null) { + if (!$nullable) return false; + } else { + if (!$vclass::isa($value, $strict)) return false; + } + } + return true; + } + + /** + * s'assurer que $array est conforme au schéma + * - les clés ne sont pas créées si elles n'existent pas, sauf si la valeur + * est requise ou si une valeur par défaut non nulle est fournie + */ + public static function ensure_schema(&$array, array $schema): bool { + $ensured = true; + foreach ($schema as $key => $kschema) { + $types = _schema::get_types($kschema, $default, $required); + + $exists = array_key_exists($key, $array); + if (!$exists) { + if ($required) { + if ($default !== null) { + $array[$key] = $default; + } else { + throw exceptions::missing_value(null, "array", "$key est obligatoire"); + } + } elseif ($default !== null) { + $array[$key] = $default; + } + continue; + } + + $vclass = _schema::get_vclass($types, $nullable); + # le test échoue si le type n'est pas supporté + if ($vclass === null) { + $ensured = false; + continue; + } + + $value = $array[$key]; + if ($nullable) { + $array[$key] = $vclass::withn($value); + } else { + if ($value === null) $value = $default; + $array[$key] = $vclass::with($value); + } + } + return $ensured; + } +} diff --git a/php/src/php/types/scalar.php b/php/src/php/types/scalar.php new file mode 100644 index 0000000..0a34b5b --- /dev/null +++ b/php/src/php/types/scalar.php @@ -0,0 +1,34 @@ + "string", + "int" => "int", + ], [ + "string" => 5, + "int" => "42", + ], [ + "string" => "5", + "int" => 42, + ]); + } + + const SCHEMA_S = ["s" => "string"]; + const SCHEMA_SD = ["s" => ["string", null]]; + const SCHEMA_SND = ["s" => ["string", "not null"]]; + const SCHEMA_RS = ["s" => ["string", "required" => true]]; + const SCHEMA_RSD = ["s" => ["string", null, "required" => true]]; + const SCHEMA_RSND = ["s" => ["string", "not null", "required" => true]]; + const SCHEMA_NS = ["s" => "?string"]; + const SCHEMA_NSD = ["s" => ["?string", null]]; + const SCHEMA_NSND = ["s" => ["?string", "not null"]]; + const SCHEMA_NRS = ["s" => ["?string", "required" => true]]; + const SCHEMA_NRSD = ["s" => ["?string", null, "required" => true]]; + const SCHEMA_NRSND = ["s" => ["?string", "not null", "required" => true]]; + + function testEnsureSchema2() { + self::assertEnsureOk(self::SCHEMA_S, [], []); + self::assertEnsureFail(self::SCHEMA_S, ["s" => null], ["s" => null]); + self::assertEnsureOk(self::SCHEMA_S, ["s" => "not null"], ["s" => "not null"]); + self::assertEnsureOk(self::SCHEMA_NS, [], []); + self::assertEnsureOk(self::SCHEMA_NS, ["s" => null], ["s" => null]); + self::assertEnsureOk(self::SCHEMA_NS, ["s" => "not null"], ["s" => "not null"]); + + self::assertEnsureOk(self::SCHEMA_SD, [], []); + self::assertEnsureFail(self::SCHEMA_SD, ["s" => null], ["s" => null]); + self::assertEnsureOk(self::SCHEMA_SD, ["s" => "not null"], ["s" => "not null"]); + self::assertEnsureOk(self::SCHEMA_NSD, [], []); + self::assertEnsureOk(self::SCHEMA_NSD, ["s" => null], ["s" => null]); + self::assertEnsureOk(self::SCHEMA_NSD, ["s" => "not null"], ["s" => "not null"]); + + self::assertEnsureOk(self::SCHEMA_SND, [], ["s" => "not null"]); + self::assertEnsureOk(self::SCHEMA_SND, ["s" => null], ["s" => "not null"]); + self::assertEnsureOk(self::SCHEMA_SND, ["s" => "not null"], ["s" => "not null"]); + self::assertEnsureOk(self::SCHEMA_NSND, [], ["s" => "not null"]); + self::assertEnsureOk(self::SCHEMA_NSND, ["s" => null], ["s" => null]); + self::assertEnsureOk(self::SCHEMA_NSND, ["s" => "not null"], ["s" => "not null"]); + + self::assertEnsureFail(self::SCHEMA_RS, [], []); + self::assertEnsureFail(self::SCHEMA_RS, ["s" => null], []); + self::assertEnsureOk(self::SCHEMA_RS, ["s" => "not null"], ["s" => "not null"]); + self::assertEnsureFail(self::SCHEMA_NRS, [], []); + self::assertEnsureOk(self::SCHEMA_NRS, ["s" => null], ["s" => null]); + self::assertEnsureOk(self::SCHEMA_NRS, ["s" => "not null"], ["s" => "not null"]); + + self::assertEnsureFail(self::SCHEMA_RSD, [], []); + self::assertEnsureFail(self::SCHEMA_RSD, ["s" => null], []); + self::assertEnsureOk(self::SCHEMA_RSD, ["s" => "not null"], ["s" => "not null"]); + self::assertEnsureFail(self::SCHEMA_NRSD, [], []); + self::assertEnsureOk(self::SCHEMA_NRSD, ["s" => null], ["s" => null]); + self::assertEnsureOk(self::SCHEMA_NRSD, ["s" => "not null"], ["s" => "not null"]); + + self::assertEnsureOk(self::SCHEMA_RSND, [], ["s" => "not null"]); + self::assertEnsureOk(self::SCHEMA_RSND, ["s" => null], ["s" => "not null"]); + self::assertEnsureOk(self::SCHEMA_RSND, ["s" => "not null"], ["s" => "not null"]); + self::assertEnsureOk(self::SCHEMA_NRSND, [], ["s" => "not null"]); + self::assertEnsureOk(self::SCHEMA_NRSND, ["s" => null], ["s" => null]); + self::assertEnsureOk(self::SCHEMA_NRSND, ["s" => "not null"], ["s" => "not null"]); + } +} diff --git a/php/tests/php/types/scalarTest.php b/php/tests/php/types/scalarTest.php new file mode 100644 index 0000000..44bd667 --- /dev/null +++ b/php/tests/php/types/scalarTest.php @@ -0,0 +1,60 @@ +