From 394ea62bd4413ff052da49fcc4728918b4f7d085 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Sat, 1 Mar 2025 13:46:46 +0400 Subject: [PATCH 01/27] deps de dev --- composer.json | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index ba50be9..dcc65a0 100644 --- a/composer.json +++ b/composer.json @@ -3,6 +3,18 @@ "type": "library", "description": "espace de maturation pour les librairies", "repositories": [ + { + "type": "path", + "url": "../nulib" + }, + { + "type": "path", + "url": "../nulib-spout" + }, + { + "type": "path", + "url": "../nulib-phpss" + }, { "type": "composer", "url": "https://repos.univ-reunion.fr/composer" @@ -18,9 +30,9 @@ "php": "^7.4" }, "require-dev": { - "nulib/php": "^0.3.0p74", - "nulib/spout": "^0.3.0p74", - "nulib/phpss": "^0.3.0p74", + "nulib/php": "^7.4-dev", + "nulib/spout": "^7.4-dev", + "nulib/phpss": "^7.4-dev", "nulib/tests": "^7.4", "ext-posix": "*", "ext-pcntl": "*", From 9438aaf396c2b9e0cc2d815df90c9ac458ffedcd Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Sun, 2 Mar 2025 15:40:10 +0400 Subject: [PATCH 02/27] ajout config .pman.yml --- .pman.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .pman.yml diff --git a/.pman.yml b/.pman.yml new file mode 100644 index 0000000..aebde45 --- /dev/null +++ b/.pman.yml @@ -0,0 +1,16 @@ +# -*- coding: utf-8 mode: yaml -*- vim:sw=2:sts=2:et:ai:si:sta:fenc=utf-8 + +composer: + profiles: [ dev, dist ] + dev: + link: true + require-dev: + nulib/php: ^7.4-dev + nulib/spout: ^7.4-dev + nulib/phpss: ^7.4-dev + dist: + link: false + require: + nulib/php: ^0.3.0p74 + nulib/spout: ^0.3.0p74 + nulib/phpss: ^0.3.0p74 From 2812046b4b1605735707fd0cfc3df3fbbd7c3690 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Sun, 2 Mar 2025 19:20:45 +0400 Subject: [PATCH 03/27] maj projet --- .pman.conf | 13 ++++++++++++- .pman.yml | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.pman.conf b/.pman.conf index 272df17..483215c 100644 --- a/.pman.conf +++ b/.pman.conf @@ -9,4 +9,15 @@ TAG_PREFIX= TAG_SUFFIX=p74 HOTFIX=hotf74- DIST= -NOAUTO=1 +NOAUTO= + +AFTER_CREATE_RELEASE=' +pman --composer-select-profile dist +composer u +git commit -am "deps de dist" +' +AFTER_MERGE_RELEASE=' +pman --composer-select-profile dev +composer u +git commit -am "deps de dev" +' diff --git a/.pman.yml b/.pman.yml index aebde45..0d391af 100644 --- a/.pman.yml +++ b/.pman.yml @@ -10,7 +10,7 @@ composer: nulib/phpss: ^7.4-dev dist: link: false - require: + require-dev: nulib/php: ^0.3.0p74 nulib/spout: ^0.3.0p74 nulib/phpss: ^0.3.0p74 From 1a5ca79ef78e03348d66fe966e5abb4110127454 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Tue, 4 Mar 2025 06:53:19 +0400 Subject: [PATCH 04/27] support des colonnes --- src/php/coll/Cursor.php | 47 ++++++++++++++++++++++--------- tests/wip/php/coll/CursorTest.php | 46 ++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 14 deletions(-) diff --git a/src/php/coll/Cursor.php b/src/php/coll/Cursor.php index f1ec9d9..b10d011 100644 --- a/src/php/coll/Cursor.php +++ b/src/php/coll/Cursor.php @@ -2,6 +2,7 @@ namespace nur\sery\wip\php\coll; use Iterator; +use IteratorAggregate; use nulib\cl; use nulib\php\func; use nur\sery\wip\php\iter; @@ -33,7 +34,7 @@ class Cursor implements Iterator { * alors retourner le tableau * ["a" => $row["a"], "b" => $row["x"], "c" => "y", "d" => null] */ - private static function map_row(array $row, ?array $map): array { + protected static function map_row(array $row, ?array $map): array { if ($map === null) return $row; $index = 0; $mapped = []; @@ -48,7 +49,7 @@ class Cursor implements Iterator { $mapped[$key] = $func->invoke([$value, $key, $row]); } else { if ($value === null) $mapped[$key] = null; - else $mapped[$key] = cl::get($row, $key); + else $mapped[$key] = cl::get($row, $value); } } return $mapped; @@ -67,7 +68,7 @@ class Cursor implements Iterator { * - une valeur associative $key => $value indique que la clé correspondante * doit exiter avec la valeur spécifiée */ - private static function filter_row(array $row, $filter): bool { + protected static function filter_row(array $row, $filter): bool { if ($filter === null) return false; if (!is_array($filter)) $filter = [$filter]; if (!$filter) return false; @@ -79,12 +80,12 @@ class Cursor implements Iterator { if (!array_key_exists($value, $row)) return false; } elseif (is_bool($value)) { if ($value) { - if (!array_key_exists($value, $row)) return false; + if (!array_key_exists($key, $row)) return false; } else { - if (array_key_exists($value, $row)) return false; + if (array_key_exists($key, $row)) return false; } } else { - if (!array_key_exists($value, $row)) return false; + if (!array_key_exists($key, $row)) return false; if ($row[$key] !== $value) return false; } } @@ -114,6 +115,11 @@ class Cursor implements Iterator { $this->rowsGenerator = $rowsGenerator; $this->rowsFunc = $rowsFunc; + $this->cols = $params["cols"] ?? null; + $colsFunc = $params["cols_func"] ?? null; + if ($colsFunc !== null) $colsFunc = func::with($colsFunc); + $this->colsFunc = $colsFunc; + $map = $params["map"] ?? null; $mapFunc = $params["map_func"] ?? null; if ($mapFunc !== null) { @@ -140,16 +146,16 @@ class Cursor implements Iterator { /** un générateur de lignes */ private ?Traversable $rowsGenerator; - /** une fonction de signature function(Cursor):?iterable */ + /** une fonction de signature function(Cursor): ?iterable */ private ?func $rowsFunc; - /** une fonction de signature function(Cursor):?array */ + /** une fonction de signature function(Cursor): ?array */ private ?func $colsFunc; - /** une fonction de signature function(Cursor):?array */ + /** une fonction de signature function(Cursor): ?array */ private ?func $mapFunc; - /** une fonction de signature function(Cursor):bool */ + /** une fonction de signature function(Cursor): bool */ private ?func $filterFunc; protected ?iterable $rows; @@ -173,6 +179,10 @@ class Cursor implements Iterator { return null; } + protected function cols(): ?array { + return $this->row !== null? array_keys($this->row): null; + } + protected function filter(): bool { return false; } @@ -185,20 +195,24 @@ class Cursor implements Iterator { # Iterator function rewind() { + $this->cols = null; $this->index = 0; $this->origIndex = 0; $this->key = null; $this->raw = null; $this->row = null; if ($this->rowsGenerator !== null) { - $this->rows = $this->rowsGenerator; - $this->rows->rewind(); + $rows = $this->rowsGenerator; + if ($rows instanceof IteratorAggregate) $rows = $rows->getIterator(); + $rows->rewind(); + $this->rows = $rows; } else { $this->rows = $this->rowsFunc->invoke(); } } - function valid() { + function valid(): bool { + $cols = $this->colsFunc; $filter = $this->filterFunc; $map = $this->mapFunc; while ($valid = iter::valid($this->rows)) { @@ -210,6 +224,10 @@ class Cursor implements Iterator { if (!$filtered) { if ($map === null) $this->row = $this->map(); else $this->row = $map->invoke([$this]); + if ($this->cols === null) { + if ($cols === null) $this->cols = $this->cols(); + else $this->cols = $cols->invoke([$this]); + } break; } else { iter::next($this->rows); @@ -219,6 +237,7 @@ class Cursor implements Iterator { if (!$valid) { iter::close($this->rows); $this->rows = null; + $this->cols = null; $this->index = -1; $this->origIndex = -1; $this->key = null; @@ -228,7 +247,7 @@ class Cursor implements Iterator { return $valid; } - function current() { + function current(): ?array { return $this->row; } diff --git a/tests/wip/php/coll/CursorTest.php b/tests/wip/php/coll/CursorTest.php index ec820d8..f28bc95 100644 --- a/tests/wip/php/coll/CursorTest.php +++ b/tests/wip/php/coll/CursorTest.php @@ -13,6 +13,43 @@ class CursorTest extends TestCase { msg::set_messenger(new StdMessenger()); } + function test_map_row() { + $cursor = new class extends Cursor { + function mapRow(array $row, ?array $map): array { + return self::map_row($row, $map); + } + }; + $row = ["a" => 1, "b" => 2, "c" => 3, "x" => 99]; + $map = ["a", "b" => "x", "c" => function() { return "y"; }, "d" => null]; + self::assertSame([ + "a" => $row["a"], + "b" => $row["x"], + "c" => "y", + "d" => null + ], $cursor->mapRow($row, $map)); + } + + function test_filter_row() { + $cursor = new class extends Cursor { + function filterRow(array $row, $filter): bool { + return self::filter_row($row, $filter); + } + }; + $row = ["a" => 1, "b" => 2, "c" => 3, "x" => 99]; + self::assertTrue($cursor->filterRow($row, "a")); + self::assertTrue($cursor->filterRow($row, ["a"])); + self::assertTrue($cursor->filterRow($row, ["a" => true])); + self::assertFalse($cursor->filterRow($row, ["a" => false])); + self::assertTrue($cursor->filterRow($row, ["a" => 1])); + self::assertFalse($cursor->filterRow($row, ["a" => 2])); + + self::assertFalse($cursor->filterRow($row, "z")); + self::assertFalse($cursor->filterRow($row, ["z"])); + self::assertFalse($cursor->filterRow($row, ["z" => true])); + self::assertTrue($cursor->filterRow($row, ["z" => false])); + self::assertFalse($cursor->filterRow($row, ["z" => 1])); + } + const SCALARS = [0, 1, 2, 3, 4]; function generator() { @@ -41,6 +78,15 @@ class CursorTest extends TestCase { return cl::all($c); }); + $c = new Cursor(null, [ + "rows" => $this->generator(), + ]); + self::assertSame([[0], [1], [2], [3], [4]], cl::all($c)); + self::assertException(Exception::class, function() use ($c) { + // pas possible de rewind un générateur + return cl::all($c); + }); + $c = new Cursor(null, [ "rows_func" => function() { return self::SCALARS; From 998d353758c6673153514e13ff1d8d6c6ac8f4f2 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Tue, 4 Mar 2025 06:53:55 +0400 Subject: [PATCH 05/27] modifs.mineures sans commentaires --- src/php/access/AbstractAccess.php | 2 +- src/php/access/FormAccess.php | 2 +- src/php/access/GetAccess.php | 2 +- src/php/access/IAccess.php | 4 ++-- src/php/access/KeyAccess.php | 2 +- src/php/access/PostAccess.php | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/php/access/AbstractAccess.php b/src/php/access/AbstractAccess.php index d9df3db..21dda22 100644 --- a/src/php/access/AbstractAccess.php +++ b/src/php/access/AbstractAccess.php @@ -1,7 +1,7 @@ Date: Tue, 4 Mar 2025 08:08:03 +0400 Subject: [PATCH 06/27] maj projet --- src/schema/README.md | 21 +- src/schema/Schema.php | 8 +- src/schema/TODO.md | 4 +- src/schema/_scalar/ScalarResult.php | 8 +- src/schema/_scalar/ScalarSchema.php | 13 +- src/schema/_scalar/ScalarValue.php | 10 +- src/schema/types/Registry.php | 2 +- src/schema/types/tarray.php | 2 +- src/schema/types/tbool.php | 4 +- src/schema/types/tcallable.php | 8 +- src/schema/types/tcontent.php | 3 +- src/web/content/Tag.php | 7 +- tests/app/argsTest.php | 26 - tests/appTest.php | 132 -- tests/db/sqlite/.gitignore | 1 - tests/db/sqlite/SqliteStorageTest.php | 344 ----- tests/db/sqlite/SqliteTest.php | 146 --- tests/db/sqlite/_queryTest.php | 125 -- tests/file/base/FileReaderTest.php | 63 - tests/file/base/impl/avec_bom.csv | 2 - tests/file/base/impl/avec_bom.txt | 1 - tests/file/base/impl/msexcel.csv | 2 - tests/file/base/impl/ooffice.csv | 2 - tests/file/base/impl/sans_bom.txt | 1 - tests/file/base/impl/weird.tsv | 2 - tests/php/funcTest.php | 1167 ----------------- tests/php/nur_funcTest.php | 292 ----- tests/php/time/DateTest.php | 85 -- tests/php/time/DateTimeTest.php | 109 -- tests/php/time/DelayTest.php | 83 -- tests/strTest.php | 28 - tests/web/uploadsTest.php | 200 --- tests/{ => wip}/php/access/KeyAccessTest.php | 3 +- .../{ => wip}/php/access/ValueAccessTest.php | 3 +- tests/{ => wip}/php/content/cTest.php | 5 +- tests/{ => wip}/php/content/impl/AContent.php | 4 +- .../{ => wip}/php/content/impl/APrintable.php | 4 +- tests/{ => wip}/php/content/impl/ATag.php | 6 +- tests/{ => wip}/php/content/impl/html.php | 2 +- .../schema/_scalar/ScalarSchemaTest.php | 4 +- tests/{ => wip}/schema/types/boolTest.php | 6 +- tests/{ => wip}/schema/types/floatTest.php | 6 +- tests/{ => wip}/schema/types/intTest.php | 6 +- tests/{ => wip}/schema/types/strTest.php | 2 +- tests/{ => wip}/schema/types/unionTest.php | 6 +- 45 files changed, 78 insertions(+), 2880 deletions(-) delete mode 100644 tests/app/argsTest.php delete mode 100644 tests/appTest.php delete mode 100644 tests/db/sqlite/.gitignore delete mode 100644 tests/db/sqlite/SqliteStorageTest.php delete mode 100644 tests/db/sqlite/SqliteTest.php delete mode 100644 tests/db/sqlite/_queryTest.php delete mode 100644 tests/file/base/FileReaderTest.php delete mode 100644 tests/file/base/impl/avec_bom.csv delete mode 100644 tests/file/base/impl/avec_bom.txt delete mode 100644 tests/file/base/impl/msexcel.csv delete mode 100644 tests/file/base/impl/ooffice.csv delete mode 100644 tests/file/base/impl/sans_bom.txt delete mode 100644 tests/file/base/impl/weird.tsv delete mode 100644 tests/php/funcTest.php delete mode 100644 tests/php/nur_funcTest.php delete mode 100644 tests/php/time/DateTest.php delete mode 100644 tests/php/time/DateTimeTest.php delete mode 100644 tests/php/time/DelayTest.php delete mode 100644 tests/strTest.php delete mode 100644 tests/web/uploadsTest.php rename tests/{ => wip}/php/access/KeyAccessTest.php (96%) rename tests/{ => wip}/php/access/ValueAccessTest.php (96%) rename tests/{ => wip}/php/content/cTest.php (93%) rename tests/{ => wip}/php/content/impl/AContent.php (62%) rename tests/{ => wip}/php/content/impl/APrintable.php (59%) rename tests/{ => wip}/php/content/impl/ATag.php (76%) rename tests/{ => wip}/php/content/impl/html.php (91%) rename tests/{ => wip}/schema/_scalar/ScalarSchemaTest.php (96%) rename tests/{ => wip}/schema/types/boolTest.php (96%) rename tests/{ => wip}/schema/types/floatTest.php (97%) rename tests/{ => wip}/schema/types/intTest.php (97%) rename tests/{ => wip}/schema/types/strTest.php (98%) rename tests/{ => wip}/schema/types/unionTest.php (82%) diff --git a/src/schema/README.md b/src/schema/README.md index 48eed33..499ce69 100644 --- a/src/schema/README.md +++ b/src/schema/README.md @@ -1,8 +1,8 @@ -# nur\sery\schema +# nulib\schema -objet: s'assurer que des données soit dans un type particulier, en les -convertissant si nécessaire. la source de ces données peut-être diverse: -formulaire web, résultat d'une requête SQL, flux CSV, etc. +les classes de ce package permettent de s'assurer que des données soit dans un +type particulier, en les convertissant si nécessaire. la source de ces données +peut-être diverse: formulaire web, résultat d'une requête SQL, flux CSV, etc. les données dont on peut modéliser le schéma sont de 3 types: * scalaire @@ -84,8 +84,12 @@ const SCALAR_SCHEMA = [ "title" => "libellé de la valeur, utilisable par exemple dans un formulaire", "required" => "la valeur est-elle requise? si oui, elle doit exister", "nullable" => "si la valeur existe, peut-elle être nulle?", + "allow_null" => "si la valeur existe, peut-elle être nulle?", #XXX + "allow_empty" => "si la valeur existe, peut-elle être vide?", #XXX "desc" => "description de la valeur", - "checker_func" => "une fonction qui vérifie une valeur et la classifie", + "analyzer_func" => "XXX", + "extractor_func" => "XXX", + "checker_func" => "XXX une fonction qui vérifie une valeur et la classifie", "parser_func" => "une fonction qui analyse une chaine pour produire la valeur", "messages" => "messages à afficher en cas d'erreur d'analyse", "formatter_func" => "une fonction qui formatte la valeur pour affichage", @@ -118,9 +122,9 @@ nature scalaire si: * c'est un tableau avec un élément à l'index 0, ainsi que d'autres éléments, e.g `["string", null, "required" => true]` -message indique les messages à afficher en cas d'erreur d'analyse. les clés sont -normalisées et correspondent à différents états de la valeur tels qu'analysés -par `checker_func` +`messages` indique les messages à afficher en cas d'erreur d'analyse. les clés +sont normalisées et correspondent à différents états de la valeur tels +qu'analysés par `checker_func` ~~~php const MESSAGE_SCHEMA = [ "missing" => "message si la valeur n'existe pas dans la source et qu'elle est requise", @@ -156,6 +160,7 @@ récursivement, avec cependant l'ajout de quelques clés supplémentaires: ~~~php VALUE_SCHEMA = [ ... + "key" => "nom du champ auquel assigner la valeur de la clé", #XXX "name" => "identifiant de la valeur", "pkey" => "chemin de clé de la valeur dans le tableau associatif", ]; diff --git a/src/schema/Schema.php b/src/schema/Schema.php index d8bcc8a..bd5d11b 100644 --- a/src/schema/Schema.php +++ b/src/schema/Schema.php @@ -2,15 +2,15 @@ namespace nur\sery\wip\schema; use ArrayAccess; -use nur\sery\AccessException; -use nur\sery\cl; +use nulib\AccessException; +use nulib\cl; use nur\sery\wip\schema\_assoc\AssocSchema; use nur\sery\wip\schema\_list\ListSchema; use nur\sery\wip\schema\_scalar\ScalarSchema; abstract class Schema implements ArrayAccess { /** - * créer si besoin une nouvelle instance de {@link Schema} à partir d'une + * créer le cas échéant une nouvelle instance de {@link Schema} à partir d'une * définition de schéma * * - si $schema est une instance de schéma, la retourner @@ -38,7 +38,7 @@ abstract class Schema implements ArrayAccess { } /** - * Créer si besoin une nouvelle instance de {@link Value} qui référence la + * Créer une nouvelle instance de {@link Value} qui référence la * variable $dest (si $destKey===null) ou $dest[$destKey] si $destKey n'est * pas null */ diff --git a/src/schema/TODO.md b/src/schema/TODO.md index 5184f37..a828364 100644 --- a/src/schema/TODO.md +++ b/src/schema/TODO.md @@ -1,4 +1,4 @@ -# nur\sery\schema +# nulib\schema * implémenter support `analyzer_func`, `extractor_func`, `parser_func`, `normalizer_func`, `formatter_func` @@ -42,6 +42,8 @@ $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 diff --git a/src/schema/_scalar/ScalarResult.php b/src/schema/_scalar/ScalarResult.php index 82f7f24..3cd0e60 100644 --- a/src/schema/_scalar/ScalarResult.php +++ b/src/schema/_scalar/ScalarResult.php @@ -1,10 +1,10 @@ schema = $schema; $this->defaultVerifix = $defaultVerifix; - $this->defaultThrow = $defaultThrow !== null? $defaultThrow: false; + $this->defaultThrow = $defaultThrow ?? false; $this->result = new ScalarResult(); $this->reset($dest, $destKey); - $this->defaultThrow = $defaultThrow !== null? $defaultThrow: true; + $this->defaultThrow = $defaultThrow ?? true; } function isScalar(?ScalarValue &$scalar=null): bool { $scalar = $this; return true; } diff --git a/src/schema/types/Registry.php b/src/schema/types/Registry.php index 58ed7a9..61a65e7 100644 --- a/src/schema/types/Registry.php +++ b/src/schema/types/Registry.php @@ -1,7 +1,7 @@ false])); - self::assertSame(["--opt"], args::from_array(["opt" => true])); - self::assertSame(["--opt", "value"], args::from_array(["opt" => "value"])); - self::assertSame(["--opt", "42"], args::from_array(["opt" => 42])); - self::assertSame(["--opt", "1", "2", "3", "--"], args::from_array(["opt" => [1, 2, 3]])); - - self::assertSame(["x", "1", "2", "3", "y"], args::from_array(["x", [1, 2, 3], "y"])); - } -} diff --git a/tests/appTest.php b/tests/appTest.php deleted file mode 100644 index 8fbac6a..0000000 --- a/tests/appTest.php +++ /dev/null @@ -1,132 +0,0 @@ - $projdir, - "vendor" => [ - "bindir" => "$projdir/vendor/bin", - "autoload" => "$projdir/vendor/autoload.php", - ], - "appcode" => "nur-sery", - "cwd" => $cwd, - "datadir" => "$projdir/devel", - "etcdir" => "$projdir/devel/etc", - "vardir" => "$projdir/devel/var", - "logdir" => "$projdir/devel/log", - "profile" => "devel", - "appgroup" => null, - "name" => "my-application1", - "title" => null, - ], $app1->getParams()); - - $app2 = myapp::with(MyApplication2::class, $app1); - self::assertSame([ - "projdir" => $projdir, - "vendor" => [ - "bindir" => "$projdir/vendor/bin", - "autoload" => "$projdir/vendor/autoload.php", - ], - "appcode" => "nur-sery", - "cwd" => $cwd, - "datadir" => "$projdir/devel", - "etcdir" => "$projdir/devel/etc", - "vardir" => "$projdir/devel/var", - "logdir" => "$projdir/devel/log", - "profile" => "devel", - "appgroup" => null, - "name" => "my-application2", - "title" => null, - ], $app2->getParams()); - } - - function testInit() { - $projdir = config::get_projdir(); - $cwd = getcwd(); - - myapp::reset(); - myapp::init(MyApplication1::class); - self::assertSame([ - "projdir" => $projdir, - "vendor" => [ - "bindir" => "$projdir/vendor/bin", - "autoload" => "$projdir/vendor/autoload.php", - ], - "appcode" => "nur-sery", - "cwd" => $cwd, - "datadir" => "$projdir/devel", - "etcdir" => "$projdir/devel/etc", - "vardir" => "$projdir/devel/var", - "logdir" => "$projdir/devel/log", - "profile" => "devel", - "appgroup" => null, - "name" => "my-application1", - "title" => null, - ], myapp::get()->getParams()); - - myapp::init(MyApplication2::class); - self::assertSame([ - "projdir" => $projdir, - "vendor" => [ - "bindir" => "$projdir/vendor/bin", - "autoload" => "$projdir/vendor/autoload.php", - ], - "appcode" => "nur-sery", - "cwd" => $cwd, - "datadir" => "$projdir/devel", - "etcdir" => "$projdir/devel/etc", - "vardir" => "$projdir/devel/var", - "logdir" => "$projdir/devel/log", - "profile" => "devel", - "appgroup" => null, - "name" => "my-application2", - "title" => null, - ], myapp::get()->getParams()); - } - } -} - -namespace nur\sery\impl { - - use nur\sery\app\cli\Application; - use nur\sery\os\path; - use nur\sery\app; - - class config { - const PROJDIR = __DIR__.'/..'; - - static function get_projdir(): string { - return path::abspath(self::PROJDIR); - } - } - - class myapp extends app { - static function reset(): void { - self::$app = null; - } - } - - class MyApplication1 extends Application { - const PROJDIR = config::PROJDIR; - - function main() { - } - } - class MyApplication2 extends Application { - const PROJDIR = null; - - function main() { - } - } -} diff --git a/tests/db/sqlite/.gitignore b/tests/db/sqlite/.gitignore deleted file mode 100644 index 6ab0f32..0000000 --- a/tests/db/sqlite/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/capacitor.db* diff --git a/tests/db/sqlite/SqliteStorageTest.php b/tests/db/sqlite/SqliteStorageTest.php deleted file mode 100644 index 8461de0..0000000 --- a/tests/db/sqlite/SqliteStorageTest.php +++ /dev/null @@ -1,344 +0,0 @@ -reset($channel); - $storage->charge($channel, "first"); - $storage->charge($channel, "second"); - $storage->charge($channel, "third"); - $items = cl::all($storage->discharge($channel, false)); - self::assertSame(["first", "second", "third"], $items); - } - - function _testChargeArrays(SqliteStorage $storage, ?string $channel) { - $storage->reset($channel); - $storage->charge($channel, ["id" => 10, "name" => "first"]); - $storage->charge($channel, ["name" => "second", "id" => 20]); - $storage->charge($channel, ["name" => "third", "id" => "30"]); - } - - function testChargeStrings() { - $storage = new SqliteStorage(__DIR__.'/capacitor.db'); - $this->_testChargeStrings($storage, null); - $storage->close(); - } - - function testChargeArrays() { - $storage = new SqliteStorage(__DIR__.'/capacitor.db'); - $storage->addChannel(new class extends CapacitorChannel { - const NAME = "arrays"; - const COLUMN_DEFINITIONS = ["id" => "integer"]; - - function getItemValues($item): ?array { - return ["id" => $item["id"] ?? null]; - } - }); - - $this->_testChargeStrings($storage, "strings"); - $this->_testChargeArrays($storage, "arrays"); - $storage->close(); - } - - function testEach() { - $storage = new SqliteStorage(__DIR__.'/capacitor.db'); - $capacitor = new Capacitor($storage, new class extends CapacitorChannel { - const NAME = "each"; - const COLUMN_DEFINITIONS = [ - "age" => "integer", - "done" => "integer default 0", - ]; - - function getItemValues($item): ?array { - return [ - "age" => $item["age"], - ]; - } - }); - - $capacitor->reset(); - $capacitor->charge(["name" => "first", "age" => 5]); - $capacitor->charge(["name" => "second", "age" => 10]); - $capacitor->charge(["name" => "third", "age" => 15]); - $capacitor->charge(["name" => "fourth", "age" => 20]); - - $setDone = function ($item, $row, $suffix=null) { - $updates = ["done" => 1]; - if ($suffix !== null) { - $item["name"] .= $suffix; - $updates["item"] = $item; - } - return $updates; - }; - $capacitor->each(["age" => [">", 10]], $setDone, ["++"]); - $capacitor->each(["done" => 0], $setDone, null); - - Txx(cl::all($capacitor->discharge(false))); - $capacitor->close(); - self::assertTrue(true); - } - - function testPrimayKey() { - $storage = new SqliteStorage(__DIR__.'/capacitor.db'); - $capacitor = new Capacitor($storage, new class extends CapacitorChannel { - const NAME = "pk"; - const COLUMN_DEFINITIONS = [ - "id_" => "varchar primary key", - "done" => "integer default 0", - ]; - - function getItemValues($item): ?array { - return [ - "id_" => $item["numero"], - ]; - } - }); - - $capacitor->charge(["numero" => "a", "name" => "first", "age" => 5]); - $capacitor->charge(["numero" => "b", "name" => "second", "age" => 10]); - $capacitor->charge(["numero" => "c", "name" => "third", "age" => 15]); - $capacitor->charge(["numero" => "d", "name" => "fourth", "age" => 20]); - sleep(2); - $capacitor->charge(["numero" => "b", "name" => "second", "age" => 100]); - $capacitor->charge(["numero" => "d", "name" => "fourth", "age" => 200]); - - $capacitor->close(); - self::assertTrue(true); - } - - function testSum() { - $storage = new SqliteStorage(__DIR__.'/capacitor.db'); - $capacitor = new Capacitor($storage, new class extends CapacitorChannel { - const NAME = "sum"; - const COLUMN_DEFINITIONS = [ - "a__" => "varchar", - "b__" => "varchar", - "b__sum_" => self::SUM_DEFINITION, - ]; - - function getItemValues($item): ?array { - return [ - "a" => $item["a"], - "b" => $item["b"], - ]; - } - }); - - $capacitor->reset(); - $capacitor->charge(["a" => null, "b" => null]); - $capacitor->charge(["a" => "first", "b" => "second"]); - - Txx("=== all"); - /** @var Sqlite $sqlite */ - $sqlite = $capacitor->getStorage()->db(); - Txx(cl::all($sqlite->all([ - "select", - "from" => $capacitor->getChannel()->getTableName(), - ]))); - Txx("=== each"); - $capacitor->each(null, function ($item, $values) { - Txx($values); - }); - - $capacitor->close(); - self::assertTrue(true); - } - - function testEachValues() { - # tester que values contient bien toutes les valeurs de la ligne - $storage = new SqliteStorage(__DIR__.'/capacitor.db'); - $capacitor = new Capacitor($storage, new class extends CapacitorChannel { - const NAME = "each_values"; - const COLUMN_DEFINITIONS = [ - "name" => "varchar primary key", - "age" => "integer", - "done" => "integer default 0", - "notes" => "text", - ]; - - function getItemValues($item): ?array { - return [ - "name" => $item["name"], - "age" => $item["age"], - ]; - } - }); - - $capacitor->reset(); - $capacitor->charge(["name" => "first", "age" => 5], function($item, ?array $values, ?array $pvalues) { - self::assertSame("first", $item["name"]); - self::assertSame(5, $item["age"]); - self::assertnotnull($values); - self::assertSame(["name", "age", "item", "item__sum_", "created_", "modified_"], array_keys($values)); - self::assertSame([ - "name" => "first", - "age" => 5, - "item" => $item, - ], cl::select($values, ["name", "age", "item"])); - self::assertNull($pvalues); - }); - $capacitor->charge(["name" => "first", "age" => 10], function($item, ?array $values, ?array $pvalues) { - self::assertSame("first", $item["name"]); - self::assertSame(10, $item["age"]); - self::assertnotnull($values); - self::assertSame(["name", "age", "done", "notes", "item", "item__sum_", "created_", "modified_"], array_keys($values)); - self::assertSame([ - "name" => "first", - "age" => 10, - "done" => 0, - "notes" => null, - "item" => $item, - ], cl::select($values, ["name", "age", "done", "notes", "item"])); - self::assertNotNull($pvalues); - self::assertSame([ - "name" => "first", - "age" => 5, - "done" => 0, - "notes" => null, - "item" => ["name" => "first", "age" => 5], - ], cl::select($pvalues, ["name", "age", "done", "notes", "item"])); - }); - - $capacitor->each(null, function($item, ?array $values) { - self::assertSame("first", $item["name"]); - self::assertSame(10, $item["age"]); - self::assertnotnull($values); - self::assertSame(["name", "age", "done", "notes", "item", "item__sum_", "created_", "modified_"], array_keys($values)); - self::assertSame([ - "name" => "first", - "age" => 10, - "done" => 0, - "notes" => null, - "item" => $item, - ], cl::select($values, ["name", "age", "done", "notes", "item"])); - return [ - "done" => 1, - "notes" => "modified", - ]; - }); - $capacitor->charge(["name" => "first", "age" => 10], function($item, ?array $values, ?array $pvalues) { - self::assertSame("first", $item["name"]); - self::assertSame(10, $item["age"]); - self::assertnotnull($values); - self::assertSame(["name", "age", "done", "notes", "item", "item__sum_", "created_", "modified_"], array_keys($values)); - self::assertSame([ - "name" => "first", - "age" => 10, - "done" => 1, - "notes" => "modified", - "item" => $item, - ], cl::select($values, ["name", "age", "done", "notes", "item"])); - self::assertNotNull($pvalues); - self::assertSame([ - "name" => "first", - "age" => 10, - "done" => 1, - "notes" => "modified", - "item" => $item, - ], cl::select($pvalues, ["name", "age", "done", "notes", "item"])); - }); - - $capacitor->charge(["name" => "first", "age" => 20], function($item, ?array $values, ?array $pvalues) { - self::assertSame("first", $item["name"]); - self::assertSame(20, $item["age"]); - self::assertnotnull($values); - self::assertSame(["name", "age", "done", "notes", "item", "item__sum_", "created_", "modified_"], array_keys($values)); - self::assertSame([ - "name" => "first", - "age" => 20, - "done" => 1, - "notes" => "modified", - "item" => $item, - ], cl::select($values, ["name", "age", "done", "notes", "item"])); - self::assertNotNull($pvalues); - self::assertSame([ - "name" => "first", - "age" => 10, - "done" => 1, - "notes" => "modified", - "item" => ["name" => "first", "age" => 10], - ], cl::select($pvalues, ["name", "age", "done", "notes", "item"])); - }); - } - - function testSetItemNull() { - # tester le forçage de $îtem à null pour économiser la place - $storage = new SqliteStorage(__DIR__.'/capacitor.db'); - $capacitor = new Capacitor($storage, new class extends CapacitorChannel { - const NAME = "set_item_null"; - const COLUMN_DEFINITIONS = [ - "name" => "varchar primary key", - "age" => "integer", - "done" => "integer default 0", - "notes" => "text", - ]; - - function getItemValues($item): ?array { - return [ - "name" => $item["name"], - "age" => $item["age"], - ]; - } - }); - - $capacitor->reset(); - $nbModified = $capacitor->charge(["name" => "first", "age" => 5], function ($item, ?array $values, ?array $pvalues) { - self::assertSame([ - "name" => "first", "age" => 5, - "item" => $item, - ], cl::select($values, ["name", "age", "item"])); - return ["item" => null]; - }); - self::assertSame(1, $nbModified); - sleep(1); - # nb: on met des sleep() pour que la date de modification soit systématiquement différente - - $nbModified = $capacitor->charge(["name" => "first", "age" => 10], function ($item, ?array $values, ?array $pvalues) { - self::assertSame([ - "name" => "first", "age" => 10, - "item" => $item, "item__sum_" => "9181336dfca20c86313d6065d89aa2ad5070b0fc", - ], cl::select($values, ["name", "age", "item", "item__sum_"])); - self::assertSame([ - "name" => "first", "age" => 5, - "item" => null, "item__sum_" => null, - ], cl::select($pvalues, ["name", "age", "item", "item__sum_"])); - return ["item" => null]; - }); - self::assertSame(1, $nbModified); - sleep(1); - - # pas de modification ici - $nbModified = $capacitor->charge(["name" => "first", "age" => 10], function ($item, ?array $values, ?array $pvalues) { - self::assertSame([ - "name" => "first", "age" => 10, - "item" => $item, "item__sum_" => "9181336dfca20c86313d6065d89aa2ad5070b0fc", - ], cl::select($values, ["name", "age", "item", "item__sum_"])); - self::assertSame([ - "name" => "first", "age" => 10, - "item" => null, "item__sum_" => null, - ], cl::select($pvalues, ["name", "age", "item", "item__sum_"])); - return ["item" => null]; - }); - self::assertSame(0, $nbModified); - sleep(1); - - $nbModified = $capacitor->charge(["name" => "first", "age" => 20], function ($item, ?array $values, ?array $pvalues) { - self::assertSame([ - "name" => "first", "age" => 20, - "item" => $item, "item__sum_" => "001b91982b4e0883b75428c0eb28573a5dc5f7a5", - ], cl::select($values, ["name", "age", "item", "item__sum_"])); - self::assertSame([ - "name" => "first", "age" => 10, - "item" => null, "item__sum_" => null, - ], cl::select($pvalues, ["name", "age", "item", "item__sum_"])); - return ["item" => null]; - }); - self::assertSame(1, $nbModified); - sleep(1); - } -} diff --git a/tests/db/sqlite/SqliteTest.php b/tests/db/sqlite/SqliteTest.php deleted file mode 100644 index b06a345..0000000 --- a/tests/db/sqlite/SqliteTest.php +++ /dev/null @@ -1,146 +0,0 @@ - [ - self::CREATE_PERSON, - self::INSERT_JEPHTE, - ], - ]); - self::assertSame("clain", $sqlite->get("select nom, age from person")); - self::assertSame([ - "nom" => "clain", - "age" => 50, - ], $sqlite->get("select nom, age from person", null, true)); - - $sqlite->exec(self::INSERT_JEAN); - self::assertSame("payet", $sqlite->get("select nom, age from person where nom = 'payet'")); - self::assertSame([ - "nom" => "payet", - "age" => 32, - ], $sqlite->get("select nom, age from person where nom = 'payet'", null, true)); - - self::assertSame([ - ["key" => "0", "value" => self::CREATE_PERSON, "done" => 1], - ["key" => "1", "value" => self::INSERT_JEPHTE, "done" => 1], - ], iterator_to_array($sqlite->all("select key, value, done from _migration"))); - } - - function testException() { - $sqlite = new Sqlite(":memory:"); - self::assertException(Exception::class, [$sqlite, "exec"], "prout"); - self::assertException(SqliteException::class, [$sqlite, "exec"], ["prout"]); - } - - protected function assertInserted(Sqlite $sqlite, array $row, array $query): void { - $sqlite->exec($query); - self::assertSame($row, $sqlite->one("select * from mapping where i = :i", [ - "i" => $query["values"]["i"], - ])); - } - function testInsert() { - $sqlite = new Sqlite(":memory:", [ - "migrate" => "create table mapping (i integer, s varchar)", - ]); - $sqlite->exec(["insert into mapping", "values" => ["i" => 1, "s" => "un"]]); - $sqlite->exec(["insert mapping", "values" => ["i" => 2, "s" => "deux"]]); - $sqlite->exec(["insert into", "into" => "mapping", "values" => ["i" => 3, "s" => "trois"]]); - $sqlite->exec(["insert", "into" => "mapping", "values" => ["i" => 4, "s" => "quatre"]]); - $sqlite->exec(["insert into mapping(i)", "values" => ["i" => 5, "s" => "cinq"]]); - $sqlite->exec(["insert into (i)", "into" => "mapping", "values" => ["i" => 6, "s" => "six"]]); - $sqlite->exec(["insert into mapping(i) values ()", "values" => ["i" => 7, "s" => "sept"]]); - $sqlite->exec(["insert into mapping(i) values (8)", "values" => ["i" => 42, "s" => "whatever"]]); - $sqlite->exec(["insert into mapping(i, s) values (9, 'neuf')", "values" => ["i" => 43, "s" => "garbage"]]); - $sqlite->exec(["insert into mapping", "cols" => ["i"], "values" => ["i" => 10, "s" => "dix"]]); - - self::assertSame([ - ["i" => 1, "s" => "un"], - ["i" => 2, "s" => "deux"], - ["i" => 3, "s" => "trois"], - ["i" => 4, "s" => "quatre"], - ["i" => 5, "s" => null/*"cinq"*/], - ["i" => 6, "s" => null/*"six"*/], - ["i" => 7, "s" => null/*"sept"*/], - ["i" => 8, "s" => null/*"huit"*/], - ["i" => 9, "s" => "neuf"], - ["i" => 10, "s" => null/*"dix"*/], - ], iterator_to_array($sqlite->all("select * from mapping"))); - } - - function testSelect() { - $sqlite = new Sqlite(":memory:", [ - "migrate" => "create table user (name varchar, amount integer)", - ]); - $sqlite->exec(["insert into user", "values" => ["name" => "jclain1", "amount" => 1]]); - $sqlite->exec(["insert into user", "values" => ["name" => "jclain2", "amount" => 2]]); - $sqlite->exec(["insert into user", "values" => ["name" => "jclain5", "amount" => 5]]); - $sqlite->exec(["insert into user", "values" => ["name" => "fclain7", "amount" => 7]]); - $sqlite->exec(["insert into user", "values" => ["name" => "fclain9", "amount" => 9]]); - $sqlite->exec(["insert into user", "values" => ["name" => "fclain10", "amount" => 10]]); - self::assertSame([ - "name" => "jclain1", - "amount" => 1, - ], $sqlite->one("select * from user where name = 'jclain1'")); - self::assertSame([ - "name" => "jclain1", - "amount" => 1, - ], $sqlite->one(["select * from user where name = 'jclain1'"])); - self::assertSame([ - "name" => "jclain1", - "amount" => 1, - ], $sqlite->one(["select from user where name = 'jclain1'"])); - self::assertSame([ - "name" => "jclain1", - "amount" => 1, - ], $sqlite->one(["select from user where", "where" => ["name = 'jclain1'"]])); - self::assertSame([ - "name" => "jclain1", - "amount" => 1, - ], $sqlite->one(["select from user", "where" => ["name = 'jclain1'"]])); - self::assertSame([ - "name" => "jclain1", - "amount" => 1, - ], $sqlite->one(["select", "from" => "user", "where" => ["name = 'jclain1'"]])); - self::assertSame([ - "name" => "jclain1", - "amount" => 1, - ], $sqlite->one(["select", "from" => "user", "where" => ["name" => "jclain1"]])); - self::assertSame([ - "name" => "jclain1", - ], $sqlite->one(["select name", "from" => "user", "where" => ["name" => "jclain1"]])); - self::assertSame([ - "name" => "jclain1", - ], $sqlite->one(["select", "cols" => "name", "from" => "user", "where" => ["name" => "jclain1"]])); - self::assertSame([ - "name" => "jclain1", - ], $sqlite->one(["select", "cols" => ["name"], "from" => "user", "where" => ["name" => "jclain1"]])); - self::assertSame([ - "plouf" => "jclain1", - ], $sqlite->one(["select", "cols" => ["plouf" => "name"], "from" => "user", "where" => ["name" => "jclain1"]])); - } - - function testSelectGroupBy() { - $sqlite = new Sqlite(":memory:", [ - "migrate" => "create table user (name varchar, amount integer)", - ]); - $sqlite->exec(["insert into user", "values" => ["name" => "jclain1", "amount" => 1]]); - $sqlite->exec(["insert into user", "values" => ["name" => "jclain2", "amount" => 1]]); - $sqlite->exec(["insert into user", "values" => ["name" => "jclain5", "amount" => 2]]); - $sqlite->exec(["insert into user", "values" => ["name" => "fclain7", "amount" => 2]]); - $sqlite->exec(["insert into user", "values" => ["name" => "fclain9", "amount" => 2]]); - $sqlite->exec(["insert into user", "values" => ["name" => "fclain10", "amount" => 3]]); - - self::assertSame([ - ["count" => 2], - ], iterator_to_array($sqlite->all(["select count(name) as count from user", "group by" => ["amount"], "having" => ["count(name) = 2"]]))); - } -} diff --git a/tests/db/sqlite/_queryTest.php b/tests/db/sqlite/_queryTest.php deleted file mode 100644 index 2fd73e5..0000000 --- a/tests/db/sqlite/_queryTest.php +++ /dev/null @@ -1,125 +0,0 @@ - null], $sql, $params); - self::assertSame(["col is null"], $sql); - self::assertNull($params); - - $sql = $params = null; - _query_base::parse_conds(["col = 'value'"], $sql, $params); - self::assertSame(["col = 'value'"], $sql); - self::assertNull($params); - - $sql = $params = null; - _query_base::parse_conds([["col = 'value'"]], $sql, $params); - self::assertSame(["col = 'value'"], $sql); - self::assertNull($params); - - $sql = $params = null; - _query_base::parse_conds(["int" => 42, "string" => "value"], $sql, $params); - self::assertSame(["(int = :int and string = :string)"], $sql); - self::assertSame(["int" => 42, "string" => "value"], $params); - - $sql = $params = null; - _query_base::parse_conds(["or", "int" => 42, "string" => "value"], $sql, $params); - self::assertSame(["(int = :int or string = :string)"], $sql); - self::assertSame(["int" => 42, "string" => "value"], $params); - - $sql = $params = null; - _query_base::parse_conds([["int" => 42, "string" => "value"], ["int" => 24, "string" => "eulav"]], $sql, $params); - self::assertSame(["((int = :int and string = :string) and (int = :int2 and string = :string2))"], $sql); - self::assertSame(["int" => 42, "string" => "value", "int2" => 24, "string2" => "eulav"], $params); - - $sql = $params = null; - _query_base::parse_conds(["int" => ["is null"], "string" => ["<>", "value"]], $sql, $params); - self::assertSame(["(int is null and string <> :string)"], $sql); - self::assertSame(["string" => "value"], $params); - - $sql = $params = null; - _query_base::parse_conds(["col" => ["between", "lower", "upper"]], $sql, $params); - self::assertSame(["col between :col and :col2"], $sql); - self::assertSame(["col" => "lower", "col2" => "upper"], $params); - - $sql = $params = null; - _query_base::parse_conds(["col" => ["in", "one"]], $sql, $params); - self::assertSame(["col in (:col)"], $sql); - self::assertSame(["col" => "one"], $params); - - $sql = $params = null; - _query_base::parse_conds(["col" => ["in", ["one", "two"]]], $sql, $params); - self::assertSame(["col in (:col, :col2)"], $sql); - self::assertSame(["col" => "one", "col2" => "two"], $params); - - $sql = $params = null; - _query_base::parse_conds(["col" => ["=", ["one", "two"]]], $sql, $params); - self::assertSame(["col = :col and col = :col2"], $sql); - self::assertSame(["col" => "one", "col2" => "two"], $params); - - $sql = $params = null; - _query_base::parse_conds(["or", "col" => ["=", ["one", "two"]]], $sql, $params); - self::assertSame(["col = :col or col = :col2"], $sql); - self::assertSame(["col" => "one", "col2" => "two"], $params); - - $sql = $params = null; - _query_base::parse_conds(["col" => ["<>", ["one", "two"]]], $sql, $params); - self::assertSame(["col <> :col and col <> :col2"], $sql); - self::assertSame(["col" => "one", "col2" => "two"], $params); - - $sql = $params = null; - _query_base::parse_conds(["or", "col" => ["<>", ["one", "two"]]], $sql, $params); - self::assertSame(["col <> :col or col <> :col2"], $sql); - self::assertSame(["col" => "one", "col2" => "two"], $params); - } - - function testParseValues(): void { - $sql = $params = null; - _query_base::parse_set_values(null, $sql, $params); - self::assertNull($sql); - self::assertNull($params); - - $sql = $params = null; - _query_base::parse_set_values([], $sql, $params); - self::assertNull($sql); - self::assertNull($params); - - $sql = $params = null; - _query_base::parse_set_values(["col = 'value'"], $sql, $params); - self::assertSame(["col = 'value'"], $sql); - self::assertNull($params); - - $sql = $params = null; - _query_base::parse_set_values([["col = 'value'"]], $sql, $params); - self::assertSame(["col = 'value'"], $sql); - self::assertNull($params); - - $sql = $params = null; - _query_base::parse_set_values(["int" => 42, "string" => "value"], $sql, $params); - self::assertSame(["int = :int", "string = :string"], $sql); - self::assertSame(["int" => 42, "string" => "value"], $params); - - $sql = $params = null; - _query_base::parse_set_values(["int" => 42, "string" => "value"], $sql, $params); - self::assertSame(["int = :int", "string = :string"], $sql); - self::assertSame(["int" => 42, "string" => "value"], $params); - - $sql = $params = null; - _query_base::parse_set_values([["int" => 42, "string" => "value"], ["int" => 24, "string" => "eulav"]], $sql, $params); - self::assertSame(["int = :int", "string = :string", "int = :int2", "string = :string2"], $sql); - self::assertSame(["int" => 42, "string" => "value", "int2" => 24, "string2" => "eulav"], $params); - } -} diff --git a/tests/file/base/FileReaderTest.php b/tests/file/base/FileReaderTest.php deleted file mode 100644 index 1066468..0000000 --- a/tests/file/base/FileReaderTest.php +++ /dev/null @@ -1,63 +0,0 @@ -fread(10)); - self::assertSame(10, $reader->ftell()); - $reader->seek(30); - self::assertSame("abcdefghij", $reader->fread(10)); - self::assertSame(40, $reader->ftell()); - $reader->seek(10); - self::assertSame("ABCDEFGHIJ", $reader->fread(10)); - self::assertSame(20, $reader->ftell()); - $reader->seek(40); - self::assertSame("0123456789\n", $reader->getContents()); - $reader->close(); - ## avec BOM - $reader = new FileReader(__DIR__ . '/impl/avec_bom.txt'); - self::assertSame("0123456789", $reader->fread(10)); - self::assertSame(10, $reader->ftell()); - $reader->seek(30); - self::assertSame("abcdefghij", $reader->fread(10)); - self::assertSame(40, $reader->ftell()); - $reader->seek(10); - self::assertSame("ABCDEFGHIJ", $reader->fread(10)); - self::assertSame(20, $reader->ftell()); - $reader->seek(40); - self::assertSame("0123456789\n", $reader->getContents()); - $reader->close(); - } - - function testCsvAutoParams() { - $reader = new FileReader(__DIR__ . '/impl/msexcel.csv'); - self::assertSame(["nom", "prenom", "age"], $reader->fgetcsv()); - self::assertSame(["clain", "jephte", "50"], $reader->fgetcsv()); - self::assertNull($reader->fgetcsv()); - $reader->close(); - - $reader = new FileReader(__DIR__ . '/impl/ooffice.csv'); - self::assertSame(["nom", "prenom", "age"], $reader->fgetcsv()); - self::assertSame(["clain", "jephte", "50"], $reader->fgetcsv()); - self::assertNull($reader->fgetcsv()); - $reader->close(); - - $reader = new FileReader(__DIR__ . '/impl/weird.tsv'); - self::assertSame(["nom", "prenom", "age"], $reader->fgetcsv()); - self::assertSame(["clain", "jephte", "50"], $reader->fgetcsv()); - self::assertNull($reader->fgetcsv()); - $reader->close(); - - $reader = new FileReader(__DIR__ . '/impl/avec_bom.csv'); - self::assertSame(["nom", "prenom", "age"], $reader->fgetcsv()); - self::assertSame(["clain", "jephte", "50"], $reader->fgetcsv()); - self::assertNull($reader->fgetcsv()); - $reader->close(); - } -} diff --git a/tests/file/base/impl/avec_bom.csv b/tests/file/base/impl/avec_bom.csv deleted file mode 100644 index d1512a2..0000000 --- a/tests/file/base/impl/avec_bom.csv +++ /dev/null @@ -1,2 +0,0 @@ -nom,prenom,age -clain,jephte,50 diff --git a/tests/file/base/impl/avec_bom.txt b/tests/file/base/impl/avec_bom.txt deleted file mode 100644 index 9e55899..0000000 --- a/tests/file/base/impl/avec_bom.txt +++ /dev/null @@ -1 +0,0 @@ -0123456789ABCDEFGHIJ0123456789abcdefghij0123456789 diff --git a/tests/file/base/impl/msexcel.csv b/tests/file/base/impl/msexcel.csv deleted file mode 100644 index b2d95c4..0000000 --- a/tests/file/base/impl/msexcel.csv +++ /dev/null @@ -1,2 +0,0 @@ -nom;prenom;age -clain;jephte;50 diff --git a/tests/file/base/impl/ooffice.csv b/tests/file/base/impl/ooffice.csv deleted file mode 100644 index f00d4ff..0000000 --- a/tests/file/base/impl/ooffice.csv +++ /dev/null @@ -1,2 +0,0 @@ -nom,prenom,age -clain,jephte,50 diff --git a/tests/file/base/impl/sans_bom.txt b/tests/file/base/impl/sans_bom.txt deleted file mode 100644 index f16e49f..0000000 --- a/tests/file/base/impl/sans_bom.txt +++ /dev/null @@ -1 +0,0 @@ -0123456789ABCDEFGHIJ0123456789abcdefghij0123456789 diff --git a/tests/file/base/impl/weird.tsv b/tests/file/base/impl/weird.tsv deleted file mode 100644 index cd8bf3a..0000000 --- a/tests/file/base/impl/weird.tsv +++ /dev/null @@ -1,2 +0,0 @@ -nom prenom age -clain jephte 50 diff --git a/tests/php/funcTest.php b/tests/php/funcTest.php deleted file mode 100644 index e15a20f..0000000 --- a/tests/php/funcTest.php +++ /dev/null @@ -1,1167 +0,0 @@ -", - false, null, - false, null, - ], - ["tsimple", - true, [false, "tsimple"], - true, [false, "tsimple"], - ], - ['nur\sery\php\impl\ntsimple', - true, [false, 'nur\sery\php\impl\ntsimple'], - true, [false, 'nur\sery\php\impl\ntsimple'], - ], - ['tmissing', - false, null, - true, [false, 'tmissing'], - ], - ["::tstatic", - false, null, - false, null, - ], - ["->tmethod", - false, null, - false, null, - ], - ["::tmissing", - false, null, - false, null, - ], - ["->tmissing", - false, null, - false, null, - ], - ["xxx::tmissing", - false, null, - false, null, - ], - ["xxx->tmissing", - false, null, - false, null, - ], - [SC::class."::tstatic", - false, null, - false, null, - ], - [SC::class."->tmethod", - false, null, - false, null, - ], - [SC::class."::tmissing", - false, null, - false, null, - ], - [SC::class."->tmissing", - false, null, - false, null, - ], - # tableaux avec un seul scalaire - [[], - false, null, - false, null, - ], - [[null], - false, null, - false, null, - ], - [[false], - false, null, - false, null, - ], - [[""], - false, null, - false, null, - ], - [["::"], - false, null, - false, null, - ], - [["->"], - false, null, - false, null, - ], - [["tsimple"], - false, null, - false, null, - ], - [['nur\sery\php\impl\ntsimple'], - false, null, - false, null, - ], - [["::tstatic"], - false, null, - false, null, - ], - [["->tmethod"], - false, null, - false, null, - ], - [["::tmissing"], - false, null, - false, null, - ], - [["->tmissing"], - false, null, - false, null, - ], - [["xxx::tmissing"], - false, null, - false, null, - ], - [["xxx->tmissing"], - false, null, - false, null, - ], - [[SC::class."::tstatic"], - false, null, - false, null, - ], - [[SC::class."->tmethod"], - false, null, - false, null, - ], - [[SC::class."::tmissing"], - false, null, - false, null, - ], - [[SC::class."->tmissing"], - false, null, - false, null, - ], - # tableaux avec deux scalaires - [[null, "tsimple"], - false, null, - false, null, - ], - [[null, 'nur\sery\php\impl\ntsimple'], - false, null, - false, null, - ], - [[null, "tmissing"], - false, null, - false, null, - ], - [[null, "::tstatic"], - false, null, - false, null, - ], - [[null, "->tmethod"], - false, null, - false, null, - ], - [[null, "::tmissing"], - false, null, - false, null, - ], - [[null, "->tmissing"], - false, null, - false, null, - ], - [[false, "tsimple"], - true, [false, "tsimple"], - true, [false, "tsimple"], - ], - [[false, 'nur\sery\php\impl\ntsimple'], - true, [false, 'nur\sery\php\impl\ntsimple'], - true, [false, 'nur\sery\php\impl\ntsimple'], - ], - [[false, "tmissing"], - false, null, - true, [false, "tmissing"], - ], - [[false, "::tstatic"], - false, null, - false, null, - ], - [[false, "->tmethod"], - false, null, - false, null, - ], - [[false, "::tmissing"], - false, null, - false, null, - ], - [[false, "->tmissing"], - false, null, - false, null, - ], - [["", "tsimple"], - false, null, - false, null, - ], - [["", 'nur\sery\php\impl\ntsimple'], - false, null, - false, null, - ], - [["", "tmissing"], - false, null, - false, null, - ], - [["", "::tstatic"], - false, null, - false, null, - ], - [["", "->tmethod"], - false, null, - false, null, - ], - [["", "::tmissing"], - false, null, - false, null, - ], - [["", "->tmissing"], - false, null, - false, null, - ], - [["xxx", "tmissing"], - false, null, - false, null, - ], - [["xxx", "::tmissing"], - false, null, - false, null, - ], - [["xxx", "->tmissing"], - false, null, - false, null, - ], - [[SC::class, "tstatic"], - false, null, - false, null, - ], - [[SC::class, "::tstatic"], - false, null, - false, null, - ], - [[SC::class, "tmethod"], - false, null, - false, null, - ], - [[SC::class, "->tmethod"], - false, null, - false, null, - ], - [[SC::class, "tmissing"], - false, null, - false, null, - ], - [[SC::class, "::tmissing"], - false, null, - false, null, - ], - [[SC::class, "->tmissing"], - false, null, - false, null, - ], - ]; - - function testFunction() { - foreach (self::FUNCTION_TESTS as $args) { - [$func, - $verifix1, $func1, - $verifix2, $func2, - ] = $args; - if ($func === ["", "tsimple"]) { - //echo "breakpoint"; - } - - $workf = $func; - $msg = var_export($func, true)." (strict)"; - self::assertSame($verifix1, func::verifix_function($workf, true), "$msg --> verifix"); - if ($verifix1) { - self::assertSame($func1, $workf, "$msg --> func"); - } - - $workf = $func; - $msg = var_export($func, true)." (lenient)"; - self::assertSame($verifix2, func::verifix_function($workf, false), "$msg --> verifix"); - if ($verifix2) { - self::assertSame($func2, $workf, "$msg --> func"); - } - } - } - - const STATIC_TESTS = [ - # scalaires - [null, - false, null, null, - false, null, null, - ], - [false, - false, null, null, - false, null, null, - ], - ["", - false, null, null, - false, null, null, - ], - ["::", - false, null, null, - false, null, null, - ], - ["->", - false, null, null, - false, null, null, - ], - ["tsimple", - false, null, null, - false, null, null, - ], - ['nur\sery\php\impl\ntsimple', - false, null, null, - false, null, null, - ], - ['tmissing', - false, null, null, - false, null, null, - ], - ["::tstatic", - true, false, [null, "tstatic"], - true, false, [null, "tstatic"], - ], - ["->tmethod", - false, null, null, - false, null, null, - ], - ["::tmissing", - true, false, [null, "tmissing"], - true, false, [null, "tmissing"], - ], - ["->tmissing", - false, null, null, - false, null, null, - ], - ["xxx::tmissing", - false, null, null, - true, true, ["xxx", "tmissing"], - ], - ["xxx->tmissing", - false, null, null, - false, null, null, - ], - [SC::class."::tstatic", - true, true, [SC::class, "tstatic"], - true, true, [SC::class, "tstatic"], - ], - [SC::class."->tmethod", - false, null, null, - false, null, null, - ], - [SC::class."::tmissing", - false, null, null, - true, true, [SC::class, "tmissing"], - ], - [SC::class."->tmissing", - false, null, null, - false, null, null, - ], - # tableaux avec un seul scalaire - [[], - false, null, null, - false, null, null, - ], - [[null], - false, null, null, - false, null, null, - ], - [[false], - false, null, null, - false, null, null, - ], - [[""], - false, null, null, - false, null, null, - ], - [["::"], - false, null, null, - false, null, null, - ], - [["->"], - false, null, null, - false, null, null, - ], - [["tsimple"], - false, null, null, - false, null, null, - ], - [['nur\sery\php\impl\ntsimple'], - false, null, null, - false, null, null, - ], - [["::tstatic"], - true, false, [null, "tstatic"], - true, false, [null, "tstatic"], - ], - [["->tmethod"], - false, null, null, - false, null, null, - ], - [["::tmissing"], - true, false, [null, "tmissing"], - true, false, [null, "tmissing"], - ], - [["->tmissing"], - false, null, null, - false, null, null, - ], - [["xxx::tmissing"], - false, null, null, - true, true, ["xxx", "tmissing"], - ], - [["xxx->tmissing"], - false, null, null, - false, null, null, - ], - [[SC::class."::tstatic"], - true, true, [SC::class, "tstatic"], - true, true, [SC::class, "tstatic"], - ], - [[SC::class."->tmethod"], - false, null, null, - false, null, null, - ], - [[SC::class."::tmissing"], - false, null, null, - true, true, [SC::class, "tmissing"], - ], - [[SC::class."->tmissing"], - false, null, null, - false, null, null, - ], - # tableaux avec deux scalaires - [[null, "tsimple"], - true, false, [null, "tsimple"], - true, false, [null, "tsimple"], - ], - [[null, 'nur\sery\php\impl\ntsimple'], - false, null, null, - false, null, null, - ], - [[null, "tmissing"], - true, false, [null, "tmissing"], - true, false, [null, "tmissing"], - ], - [[null, "::tstatic"], - true, false, [null, "tstatic"], - true, false, [null, "tstatic"], - ], - [[null, "->tmethod"], - false, null, null, - false, null, null, - ], - [[null, "::tmissing"], - true, false, [null, "tmissing"], - true, false, [null, "tmissing"], - ], - [[null, "->tmissing"], - false, null, null, - false, null, null, - ], - [[false, "tsimple"], - false, null, null, - false, null, null, - ], - [[false, 'nur\sery\php\impl\ntsimple'], - false, null, null, - false, null, null, - ], - [[false, "tmissing"], - false, null, null, - false, null, null, - ], - [[false, "::tstatic"], - false, null, null, - false, null, null, - ], - [[false, "->tmethod"], - false, null, null, - false, null, null, - ], - [[false, "::tmissing"], - false, null, null, - false, null, null, - ], - [[false, "->tmissing"], - false, null, null, - false, null, null, - ], - [["", "tsimple"], - false, null, null, - false, null, null, - ], - [["", 'nur\sery\php\impl\ntsimple'], - false, null, null, - false, null, null, - ], - [["", "tmissing"], - false, null, null, - false, null, null, - ], - [["", "::tstatic"], - false, null, null, - false, null, null, - ], - [["", "->tmethod"], - false, null, null, - false, null, null, - ], - [["", "::tmissing"], - false, null, null, - false, null, null, - ], - [["", "->tmissing"], - false, null, null, - false, null, null, - ], - [["xxx", "tmissing"], - false, null, null, - true, true, ["xxx", "tmissing"], - ], - [["xxx", "::tmissing"], - false, null, null, - true, true, ["xxx", "tmissing"], - ], - [["xxx", "->tmissing"], - false, null, null, - false, null, null, - ], - [[SC::class, "tstatic"], - true, true, [SC::class, "tstatic"], - true, true, [SC::class, "tstatic"], - ], - [[SC::class, "::tstatic"], - true, true, [SC::class, "tstatic"], - true, true, [SC::class, "tstatic"], - ], - [[SC::class, "tmethod"], - true, true, [SC::class, "tmethod"], - true, true, [SC::class, "tmethod"], - ], - [[SC::class, "->tmethod"], - false, null, null, - false, null, null, - ], - [[SC::class, "tmissing"], - false, null, null, - true, true, [SC::class, "tmissing"], - ], - [[SC::class, "::tmissing"], - false, null, null, - true, true, [SC::class, "tmissing"], - ], - [[SC::class, "->tmissing"], - false, null, null, - false, null, null, - ], - ]; - - function testStatic() { - foreach (self::STATIC_TESTS as $args) { - [$func, - $verifix1, $bound1, $func1, - $verifix2, $bound2, $func2, - ] = $args; - if ($func === ["", "tsimple"]) { - //echo "breakpoint"; - } - - $workf = $func; - $msg = var_export($func, true)." (strict)"; - self::assertSame($verifix1, func::verifix_static($workf, true, $bound), "$msg --> verifix"); - if ($verifix1) { - self::assertSame($bound1, $bound, "$msg --> bound"); - self::assertSame($func1, $workf, "$msg --> func"); - } - - $workf = $func; - $msg = var_export($func, true)." (lenient)"; - self::assertSame($verifix2, func::verifix_static($workf, false, $bound), "$msg --> verifix"); - if ($verifix2) { - self::assertSame($bound2, $bound, "$msg --> bound"); - self::assertSame($func2, $workf, "$msg --> func"); - } - } - } - - const METHOD_TESTS = [ - # scalaires - [null, - false, null, null, - false, null, null, - ], - [false, - false, null, null, - false, null, null, - ], - ["", - false, null, null, - false, null, null, - ], - ["::", - false, null, null, - false, null, null, - ], - ["->", - false, null, null, - false, null, null, - ], - ["tsimple", - false, null, null, - false, null, null, - ], - ['nur\sery\php\impl\ntsimple', - false, null, null, - false, null, null, - ], - ['tmissing', - false, null, null, - false, null, null, - ], - ["::tstatic", - false, null, null, - false, null, null, - ], - ["->tmethod", - true, false, [null, "tmethod"], - true, false, [null, "tmethod"], - ], - ["::tmissing", - false, null, null, - false, null, null, - ], - ["->tmissing", - true, false, [null, "tmissing"], - true, false, [null, "tmissing"], - ], - ["xxx::tmissing", - false, null, null, - false, null, null, - ], - ["xxx->tmissing", - false, null, null, - true, true, ["xxx", "tmissing"], - ], - [SC::class."::tstatic", - false, null, null, - false, null, null, - ], - [SC::class."->tmethod", - true, true, [SC::class, "tmethod"], - true, true, [SC::class, "tmethod"], - ], - [SC::class."::tmissing", - false, null, null, - false, null, null, - ], - [SC::class."->tmissing", - false, null, null, - true, true, [SC::class, "tmissing"], - ], - # tableaux avec un seul scalaire - [[], - false, null, null, - false, null, null, - ], - [[null], - false, null, null, - false, null, null, - ], - [[false], - false, null, null, - false, null, null, - ], - [[""], - false, null, null, - false, null, null, - ], - [["::"], - false, null, null, - false, null, null, - ], - [["->"], - false, null, null, - false, null, null, - ], - [["tsimple"], - false, null, null, - false, null, null, - ], - [['nur\sery\php\impl\ntsimple'], - false, null, null, - false, null, null, - ], - [["::tstatic"], - false, null, null, - false, null, null, - ], - [["->tmethod"], - true, false, [null, "tmethod"], - true, false, [null, "tmethod"], - ], - [["::tmissing"], - false, null, null, - false, null, null, - ], - [["->tmissing"], - true, false, [null, "tmissing"], - true, false, [null, "tmissing"], - ], - [["xxx::tmissing"], - false, null, null, - false, null, null, - ], - [["xxx->tmissing"], - false, null, null, - true, true, ["xxx", "tmissing"], - ], - [[SC::class."::tstatic"], - false, null, null, - false, null, null, - ], - [[SC::class."->tmethod"], - true, true, [SC::class, "tmethod"], - true, true, [SC::class, "tmethod"], - ], - [[SC::class."::tmissing"], - false, null, null, - false, null, null, - ], - [[SC::class."->tmissing"], - false, null, null, - true, true, [SC::class, "tmissing"], - ], - # tableaux avec deux scalaires - [[null, "tsimple"], - true, false, [null, "tsimple"], - true, false, [null, "tsimple"], - ], - [[null, 'nur\sery\php\impl\ntsimple'], - false, null, null, - false, null, null, - ], - [[null, "tmissing"], - true, false, [null, "tmissing"], - true, false, [null, "tmissing"], - ], - [[null, "::tstatic"], - false, null, null, - false, null, null, - ], - [[null, "->tmethod"], - true, false, [null, "tmethod"], - true, false, [null, "tmethod"], - ], - [[null, "::tmissing"], - false, null, null, - false, null, null, - ], - [[null, "->tmissing"], - true, false, [null, "tmissing"], - true, false, [null, "tmissing"], - ], - [[false, "tsimple"], - false, null, null, - false, null, null, - ], - [[false, 'nur\sery\php\impl\ntsimple'], - false, null, null, - false, null, null, - ], - [[false, "tmissing"], - false, null, null, - false, null, null, - ], - [[false, "::tstatic"], - false, null, null, - false, null, null, - ], - [[false, "->tmethod"], - false, null, null, - false, null, null, - ], - [[false, "::tmissing"], - false, null, null, - false, null, null, - ], - [[false, "->tmissing"], - false, null, null, - false, null, null, - ], - [["", "tsimple"], - false, null, null, - false, null, null, - ], - [["", 'nur\sery\php\impl\ntsimple'], - false, null, null, - false, null, null, - ], - [["", "tmissing"], - false, null, null, - false, null, null, - ], - [["", "::tstatic"], - false, null, null, - false, null, null, - ], - [["", "->tmethod"], - false, null, null, - false, null, null, - ], - [["", "::tmissing"], - false, null, null, - false, null, null, - ], - [["", "->tmissing"], - false, null, null, - false, null, null, - ], - [["xxx", "tmissing"], - false, null, null, - true, true, ["xxx", "tmissing"], - ], - [["xxx", "::tmissing"], - false, null, null, - false, null, null, - ], - [["xxx", "->tmissing"], - false, null, null, - true, true, ["xxx", "tmissing"], - ], - [[SC::class, "tstatic"], - true, true, [SC::class, "tstatic"], - true, true, [SC::class, "tstatic"], - ], - [[SC::class, "::tstatic"], - false, null, null, - false, null, null, - ], - [[SC::class, "tmethod"], - true, true, [SC::class, "tmethod"], - true, true, [SC::class, "tmethod"], - ], - [[SC::class, "->tmethod"], - true, true, [SC::class, "tmethod"], - true, true, [SC::class, "tmethod"], - ], - [[SC::class, "tmissing"], - false, null, null, - true, true, [SC::class, "tmissing"], - ], - [[SC::class, "::tmissing"], - false, null, null, - false, null, null, - ], - [[SC::class, "->tmissing"], - false, null, null, - true, true, [SC::class, "tmissing"], - ], - ]; - - function testMethod() { - foreach (self::METHOD_TESTS as $args) { - [$func, - $verifix1, $bound1, $func1, - $verifix2, $bound2, $func2, - ] = $args; - - $workf = $func; - $msg = var_export($func, true)." (strict)"; - self::assertSame($verifix1, func::verifix_method($workf, true, $bound), "$msg --> verifix"); - if ($verifix1) { - self::assertSame($bound1, $bound, "$msg --> bound"); - self::assertSame($func1, $workf, "$msg --> func"); - } - - $workf = $func; - $msg = var_export($func, true)." (lenient)"; - self::assertSame($verifix2, func::verifix_method($workf, false, $bound), "$msg --> verifix"); - if ($verifix2) { - self::assertSame($bound2, $bound, "$msg --> bound"); - self::assertSame($func2, $workf, "$msg --> func"); - } - } - } - - function testInvokeFunction() { - # m1 - self::assertSame([null], func::call("tm1")); - self::assertSame([null], func::call("tm1", null)); - self::assertSame([null], func::call("tm1", null, null)); - self::assertSame([null], func::call("tm1", null, null, null)); - self::assertSame([null], func::call("tm1", null, null, null, null)); - self::assertSame([1], func::call("tm1", 1)); - self::assertSame([1], func::call("tm1", 1, 2)); - self::assertSame([1], func::call("tm1", 1, 2, 3)); - self::assertSame([1], func::call("tm1", 1, 2, 3, 4)); - - # o1 - self::assertSame([9], func::call("to1")); - self::assertSame([null], func::call("to1", null)); - self::assertSame([null], func::call("to1", null, null)); - self::assertSame([null], func::call("to1", null, null, null)); - self::assertSame([null], func::call("to1", null, null, null, null)); - self::assertSame([1], func::call("to1", 1)); - self::assertSame([1], func::call("to1", 1, 2)); - self::assertSame([1], func::call("to1", 1, 2, 3)); - self::assertSame([1], func::call("to1", 1, 2, 3, 4)); - - # v - self::assertSame([], func::call("tv")); - self::assertSame([null], func::call("tv", null)); - self::assertSame([null, null], func::call("tv", null, null)); - self::assertSame([null, null, null], func::call("tv", null, null, null)); - self::assertSame([null, null, null, null], func::call("tv", null, null, null, null)); - self::assertSame([1], func::call("tv", 1)); - self::assertSame([1, 2], func::call("tv", 1, 2)); - self::assertSame([1, 2, 3], func::call("tv", 1, 2, 3)); - self::assertSame([1, 2, 3, 4], func::call("tv", 1, 2, 3, 4)); - - # m1o1 - self::assertSame([null, 9], func::call("tm1o1")); - self::assertSame([null, 9], func::call("tm1o1", null)); - self::assertSame([null, null], func::call("tm1o1", null, null)); - self::assertSame([null, null], func::call("tm1o1", null, null, null)); - self::assertSame([null, null], func::call("tm1o1", null, null, null, null)); - self::assertSame([1, 9], func::call("tm1o1", 1)); - self::assertSame([1, 2], func::call("tm1o1", 1, 2)); - self::assertSame([1, 2], func::call("tm1o1", 1, 2, 3)); - self::assertSame([1, 2], func::call("tm1o1", 1, 2, 3, 4)); - - # m1v - self::assertSame([null], func::call("tm1v")); - self::assertSame([null], func::call("tm1v", null)); - self::assertSame([null, null], func::call("tm1v", null, null)); - self::assertSame([null, null, null], func::call("tm1v", null, null, null)); - self::assertSame([null, null, null, null], func::call("tm1v", null, null, null, null)); - self::assertSame([1], func::call("tm1v", 1)); - self::assertSame([1, 2], func::call("tm1v", 1, 2)); - self::assertSame([1, 2, 3], func::call("tm1v", 1, 2, 3)); - self::assertSame([1, 2, 3, 4], func::call("tm1v", 1, 2, 3, 4)); - - # m1o1v - self::assertSame([null, 9], func::call("tm1o1v")); - self::assertSame([null, 9], func::call("tm1o1v", null)); - self::assertSame([null, null], func::call("tm1o1v", null, null)); - self::assertSame([null, null, null], func::call("tm1o1v", null, null, null)); - self::assertSame([null, null, null, null], func::call("tm1o1v", null, null, null, null)); - self::assertSame([1, 9], func::call("tm1o1v", 1)); - self::assertSame([1, 2], func::call("tm1o1v", 1, 2)); - self::assertSame([1, 2, 3], func::call("tm1o1v", 1, 2, 3)); - self::assertSame([1, 2, 3, 4], func::call("tm1o1v", 1, 2, 3, 4)); - - # o1v - self::assertSame([9], func::call("to1v")); - self::assertSame([null], func::call("to1v", null)); - self::assertSame([null, null], func::call("to1v", null, null)); - self::assertSame([null, null, null], func::call("to1v", null, null, null)); - self::assertSame([null, null, null, null], func::call("to1v", null, null, null, null)); - self::assertSame([1], func::call("to1v", 1)); - self::assertSame([1, 2], func::call("to1v", 1, 2)); - self::assertSame([1, 2, 3], func::call("to1v", 1, 2, 3)); - self::assertSame([1, 2, 3, 4], func::call("to1v", 1, 2, 3, 4)); - } - - function testInvokeClass() { - $func = func::with(SC::class); - self::assertInstanceOf(SC::class, $func->invoke()); - self::assertInstanceOf(SC::class, $func->invoke([])); - self::assertInstanceOf(SC::class, $func->invoke([1])); - self::assertInstanceOf(SC::class, $func->invoke([1, 2])); - self::assertInstanceOf(SC::class, $func->invoke([1, 2, 3])); - - $func = func::with(C0::class); - self::assertInstanceOf(C0::class, $func->invoke()); - self::assertInstanceOf(C0::class, $func->invoke([])); - self::assertInstanceOf(C0::class, $func->invoke([1])); - self::assertInstanceOf(C0::class, $func->invoke([1, 2])); - self::assertInstanceOf(C0::class, $func->invoke([1, 2, 3])); - - $func = func::with(C1::class); - /** @var C1 $i1 */ - $i1 = $func->invoke(); - self::assertInstanceOf(C1::class, $i1); self::assertSame(0, $i1->base); - $i1 = $func->invoke([]); - self::assertInstanceOf(C1::class, $i1); self::assertSame(0, $i1->base); - $i1 = $func->invoke([1]); - self::assertInstanceOf(C1::class, $i1); self::assertSame(1, $i1->base); - $i1 = $func->invoke([1, 2]); - self::assertInstanceOf(C1::class, $i1); self::assertSame(1, $i1->base); - } - - private static function invoke_asserts(): array { - $inv_ok = function($func) { - return func::with($func)->invoke(); - }; - $inv_ko = function($func) use ($inv_ok) { - return function() use ($func, $inv_ok) { - return $inv_ok($func); - }; - }; - $bind_ok = function($func, $objet) { - return func::with($func)->bind($objet)->invoke(); - }; - $bind_ko = function($func, $object) use ($bind_ok) { - return function() use ($func, $object, $bind_ok) { - return $bind_ok($func, $object); - }; - }; - return [$inv_ok, $inv_ko, $bind_ok, $bind_ko]; - } - - function testInvokeStatic() { - [$inv_ok, $inv_ko, $bind_ok, $bind_ko] = self::invoke_asserts(); - $sc = new SC(); - - self::assertSame(10, $inv_ok([SC::class, "tstatic"])); - self::assertSame(10, $inv_ok([SC::class, "::tstatic"])); - self::assertSame(10, $inv_ok([SC::class, "->tstatic"])); - - self::assertSame(10, $inv_ok([$sc, "tstatic"])); - self::assertSame(10, $inv_ok([$sc, "::tstatic"])); - self::assertSame(10, $inv_ok([$sc, "->tstatic"])); - - self::assertException(ValueException::class, $inv_ko([null, "tstatic"])); - self::assertException(ValueException::class, $inv_ko([null, "::tstatic"])); - self::assertException(ValueException::class, $inv_ko([null, "->tstatic"])); - - self::assertSame(10, $bind_ok([null, "tstatic"], SC::class)); - self::assertSame(10, $bind_ok([null, "::tstatic"], SC::class)); - self::assertSame(10, $bind_ok([null, "->tstatic"], SC::class)); - - self::assertSame(10, $bind_ok([null, "tstatic"], $sc)); - self::assertSame(10, $bind_ok([null, "::tstatic"], $sc)); - self::assertSame(10, $bind_ok([null, "->tstatic"], $sc)); - } - - function testInvokeMethod() { - [$inv_ok, $inv_ko, $bind_ok, $bind_ko] = self::invoke_asserts(); - $sc = new SC(); - - self::assertException(ReflectionException::class, $inv_ko([SC::class, "tmethod"])); - self::assertException(ReflectionException::class, $inv_ko([SC::class, "::tmethod"])); - self::assertException(ReflectionException::class, $inv_ko([SC::class, "->tmethod"])); - - self::assertSame(11, $inv_ok([$sc, "tmethod"])); - self::assertException(ReflectionException::class, $inv_ko([$sc, "::tmethod"])); - self::assertSame(11, $inv_ok([$sc, "->tmethod"])); - - self::assertException(ValueException::class, $inv_ko([null, "tmethod"])); - self::assertException(ValueException::class, $inv_ko([null, "::tmethod"])); - self::assertException(ValueException::class, $inv_ko([null, "->tmethod"])); - - self::assertException(ReflectionException::class, $bind_ko([null, "tmethod"], SC::class)); - self::assertException(ReflectionException::class, $bind_ko([null, "::tmethod"], SC::class)); - self::assertException(ReflectionException::class, $bind_ko([null, "->tmethod"], SC::class)); - - self::assertSame(11, $bind_ok([null, "tmethod"], $sc)); - self::assertException(ReflectionException::class, $bind_ko([null, "::tmethod"], $sc)); - self::assertSame(11, $bind_ok([null, "->tmethod"], $sc)); - } - - function testArgs() { - $func = function(int $a, int $b, int $c): int { - return $a + $b + $c; - }; - - self::assertSame(6, func::call($func, 1, 2, 3)); - self::assertSame(6, func::call($func, 1, 2, 3, 4)); - - self::assertSame(6, func::with($func)->invoke([1, 2, 3])); - self::assertSame(6, func::with($func, [1])->invoke([2, 3])); - self::assertSame(6, func::with($func, [1, 2])->invoke([3])); - self::assertSame(6, func::with($func, [1, 2, 3])->invoke()); - self::assertSame(6, func::with($func, [1, 2, 3, 4])->invoke()); - } - - function testRebind() { - $func = func::with([C1::class, "tmethod"]); - self::assertSame(11, $func->bind(new C1(0))->invoke()); - self::assertSame(12, $func->bind(new C1(1))->invoke()); - self::assertException(ValueException::class, function() use ($func) { - $func->bind(new C0())->invoke(); - }); - } - } -} - -namespace { - function tsimple(): int { return 0; } - function tm1($a): array { return [$a]; } - function to1($b=9): array { return [$b]; } - function tv(...$c): array { return [...$c]; } - function tm1o1($a, $b=9): array { return [$a, $b]; } - function tm1v($a, ...$c): array { return [$a, ...$c]; } - function tm1o1v($a, $b=9, ...$c): array { return [$a, $b, ...$c]; } - function to1v($b=9, ...$c): array { return [$b, ...$c]; } -} - -namespace nur\sery\php\impl { - function ntsimple(): int { return 0; } - - class SC { - static function tstatic(): int { - return 10; - } - - function tmethod(): int { - return 11; - } - } - - class C0 { - function __construct() { - } - - static function tstatic(): int { - return 10; - } - - function tmethod(): int { - return 11; - } - } - - class C1 { - function __construct(int $base=0) { - $this->base = $base; - } - - public int $base; - - static function tstatic(): int { - return 10; - } - - function tmethod(): int { - return 11 + $this->base; - } - } -} diff --git a/tests/php/nur_funcTest.php b/tests/php/nur_funcTest.php deleted file mode 100644 index 8f6dc38..0000000 --- a/tests/php/nur_funcTest.php +++ /dev/null @@ -1,292 +0,0 @@ -")); - self::assertFalse(nur_func::is_method([])); - self::assertFalse(nur_func::is_method([""])); - self::assertFalse(nur_func::is_method([null, "->"])); - self::assertFalse(nur_func::is_method(["xxx", "->"])); - - self::assertTrue(nur_func::is_method("->xxx")); - self::assertTrue(nur_func::is_method(["->xxx"])); - self::assertTrue(nur_func::is_method([null, "->yyy"])); - self::assertTrue(nur_func::is_method(["xxx", "->yyy"])); - self::assertTrue(nur_func::is_method([null, "->yyy", "aaa"])); - self::assertTrue(nur_func::is_method(["xxx", "->yyy", "aaa"])); - } - - function testFix_method() { - $object = new \stdClass(); - $func= "->xxx"; - nur_func::fix_method($func, $object); - self::assertSame([$object, "xxx"], $func); - $func= ["->xxx"]; - nur_func::fix_method($func, $object); - self::assertSame([$object, "xxx"], $func); - $func= [null, "->yyy"]; - nur_func::fix_method($func, $object); - self::assertSame([$object, "yyy"], $func); - $func= ["xxx", "->yyy"]; - nur_func::fix_method($func, $object); - self::assertSame([$object, "yyy"], $func); - $func= [null, "->yyy", "aaa"]; - nur_func::fix_method($func, $object); - self::assertSame([$object, "yyy", "aaa"], $func); - $func= ["xxx", "->yyy", "aaa"]; - nur_func::fix_method($func, $object); - self::assertSame([$object, "yyy", "aaa"], $func); - } - - function testCall() { - self::assertSame(36, nur_func::call("func36")); - self::assertSame(12, nur_func::call(TC::class."::method")); - self::assertSame(12, nur_func::call([TC::class, "method"])); - $closure = function() { - return 21; - }; - self::assertSame(21, nur_func::call($closure)); - } - - function test_prepare_fill() { - # vérifier que les arguments sont bien remplis, en fonction du fait qu'ils - # soient obligatoires, facultatifs ou variadiques - - # m1 - self::assertSame([null], nur_func::call("func_m1")); - self::assertSame([null], nur_func::call("func_m1", null)); - self::assertSame([null], nur_func::call("func_m1", null, null)); - self::assertSame([null], nur_func::call("func_m1", null, null, null)); - self::assertSame([null], nur_func::call("func_m1", null, null, null, null)); - self::assertSame([1], nur_func::call("func_m1", 1)); - self::assertSame([1], nur_func::call("func_m1", 1, 2)); - self::assertSame([1], nur_func::call("func_m1", 1, 2, 3)); - self::assertSame([1], nur_func::call("func_m1", 1, 2, 3, 4)); - - # o1 - self::assertSame([9], nur_func::call("func_o1")); - self::assertSame([null], nur_func::call("func_o1", null)); - self::assertSame([null], nur_func::call("func_o1", null, null)); - self::assertSame([null], nur_func::call("func_o1", null, null, null)); - self::assertSame([null], nur_func::call("func_o1", null, null, null, null)); - self::assertSame([1], nur_func::call("func_o1", 1)); - self::assertSame([1], nur_func::call("func_o1", 1, 2)); - self::assertSame([1], nur_func::call("func_o1", 1, 2, 3)); - self::assertSame([1], nur_func::call("func_o1", 1, 2, 3, 4)); - - # v - self::assertSame([], nur_func::call("func_v")); - self::assertSame([null], nur_func::call("func_v", null)); - self::assertSame([null, null], nur_func::call("func_v", null, null)); - self::assertSame([null, null, null], nur_func::call("func_v", null, null, null)); - self::assertSame([null, null, null, null], nur_func::call("func_v", null, null, null, null)); - self::assertSame([1], nur_func::call("func_v", 1)); - self::assertSame([1, 2], nur_func::call("func_v", 1, 2)); - self::assertSame([1, 2, 3], nur_func::call("func_v", 1, 2, 3)); - self::assertSame([1, 2, 3, 4], nur_func::call("func_v", 1, 2, 3, 4)); - - # m1o1 - self::assertSame([null, 9], nur_func::call("func_m1o1")); - self::assertSame([null, 9], nur_func::call("func_m1o1", null)); - self::assertSame([null, null], nur_func::call("func_m1o1", null, null)); - self::assertSame([null, null], nur_func::call("func_m1o1", null, null, null)); - self::assertSame([null, null], nur_func::call("func_m1o1", null, null, null, null)); - self::assertSame([1, 9], nur_func::call("func_m1o1", 1)); - self::assertSame([1, 2], nur_func::call("func_m1o1", 1, 2)); - self::assertSame([1, 2], nur_func::call("func_m1o1", 1, 2, 3)); - self::assertSame([1, 2], nur_func::call("func_m1o1", 1, 2, 3, 4)); - - # m1v - self::assertSame([null], nur_func::call("func_m1v")); - self::assertSame([null], nur_func::call("func_m1v", null)); - self::assertSame([null, null], nur_func::call("func_m1v", null, null)); - self::assertSame([null, null, null], nur_func::call("func_m1v", null, null, null)); - self::assertSame([null, null, null, null], nur_func::call("func_m1v", null, null, null, null)); - self::assertSame([1], nur_func::call("func_m1v", 1)); - self::assertSame([1, 2], nur_func::call("func_m1v", 1, 2)); - self::assertSame([1, 2, 3], nur_func::call("func_m1v", 1, 2, 3)); - self::assertSame([1, 2, 3, 4], nur_func::call("func_m1v", 1, 2, 3, 4)); - - # m1o1v - self::assertSame([null, 9], nur_func::call("func_m1o1v")); - self::assertSame([null, 9], nur_func::call("func_m1o1v", null)); - self::assertSame([null, null], nur_func::call("func_m1o1v", null, null)); - self::assertSame([null, null, null], nur_func::call("func_m1o1v", null, null, null)); - self::assertSame([null, null, null, null], nur_func::call("func_m1o1v", null, null, null, null)); - self::assertSame([1, 9], nur_func::call("func_m1o1v", 1)); - self::assertSame([1, 2], nur_func::call("func_m1o1v", 1, 2)); - self::assertSame([1, 2, 3], nur_func::call("func_m1o1v", 1, 2, 3)); - self::assertSame([1, 2, 3, 4], nur_func::call("func_m1o1v", 1, 2, 3, 4)); - - # o1v - self::assertSame([9], nur_func::call("func_o1v")); - self::assertSame([null], nur_func::call("func_o1v", null)); - self::assertSame([null, null], nur_func::call("func_o1v", null, null)); - self::assertSame([null, null, null], nur_func::call("func_o1v", null, null, null)); - self::assertSame([null, null, null, null], nur_func::call("func_o1v", null, null, null, null)); - self::assertSame([1], nur_func::call("func_o1v", 1)); - self::assertSame([1, 2], nur_func::call("func_o1v", 1, 2)); - self::assertSame([1, 2, 3], nur_func::call("func_o1v", 1, 2, 3)); - self::assertSame([1, 2, 3, 4], nur_func::call("func_o1v", 1, 2, 3, 4)); - } - - function testCall_all() { - $c1 = new C1(); - $c2 = new C2(); - $c3 = new C3(); - - self::assertSameValues([11, 12], nur_func::call_all(C1::class)); - self::assertSameValues([11, 12, 21, 22], nur_func::call_all($c1)); - self::assertSameValues([13, 11, 12], nur_func::call_all(C2::class)); - self::assertSameValues([13, 23, 11, 12, 21, 22], nur_func::call_all($c2)); - self::assertSameValues([111, 13, 12], nur_func::call_all(C3::class)); - self::assertSameValues([111, 121, 13, 23, 12, 22], nur_func::call_all($c3)); - - $options = "conf"; - self::assertSameValues([11], nur_func::call_all(C1::class, $options)); - self::assertSameValues([11, 21], nur_func::call_all($c1, $options)); - self::assertSameValues([11], nur_func::call_all(C2::class, $options)); - self::assertSameValues([11, 21], nur_func::call_all($c2, $options)); - self::assertSameValues([111], nur_func::call_all(C3::class, $options)); - self::assertSameValues([111, 121], nur_func::call_all($c3, $options)); - - $options = ["prefix" => "conf"]; - self::assertSameValues([11], nur_func::call_all(C1::class, $options)); - self::assertSameValues([11, 21], nur_func::call_all($c1, $options)); - self::assertSameValues([11], nur_func::call_all(C2::class, $options)); - self::assertSameValues([11, 21], nur_func::call_all($c2, $options)); - self::assertSameValues([111], nur_func::call_all(C3::class, $options)); - self::assertSameValues([111, 121], nur_func::call_all($c3, $options)); - - self::assertSameValues([11, 12], nur_func::call_all($c1, ["include" => "x"])); - self::assertSameValues([11, 21], nur_func::call_all($c1, ["include" => "y"])); - self::assertSameValues([11, 12, 21], nur_func::call_all($c1, ["include" => ["x", "y"]])); - - self::assertSameValues([21, 22], nur_func::call_all($c1, ["exclude" => "x"])); - self::assertSameValues([12, 22], nur_func::call_all($c1, ["exclude" => "y"])); - self::assertSameValues([22], nur_func::call_all($c1, ["exclude" => ["x", "y"]])); - - self::assertSameValues([12], nur_func::call_all($c1, ["include" => "x", "exclude" => "y"])); - } - - function testCons() { - $obj1 = nur_func::cons(WoCons::class, 1, 2, 3); - self::assertInstanceOf(WoCons::class, $obj1); - - $obj2 = nur_func::cons(WithEmptyCons::class, 1, 2, 3); - self::assertInstanceOf(WithEmptyCons::class, $obj2); - - $obj3 = nur_func::cons(WithCons::class, 1, 2, 3); - self::assertInstanceOf(WithCons::class, $obj3); - self::assertSame(1, $obj3->first); - } - } - - class WoCons { - } - class WithEmptyCons { - function __construct() { - } - } - class WithCons { - public $first; - function __construct($first) { - $this->first = $first; - } - } - - class TC { - static function method() { - return 12; - } - } - - class C1 { - static function confps1_xy() { - return 11; - } - static function ps2_x() { - return 12; - } - function confp1_y() { - return 21; - } - function p2() { - return 22; - } - } - class C2 extends C1 { - static function ps3() { - return 13; - } - function p3() { - return 23; - } - } - class C3 extends C2 { - static function confps1_xy() { - return 111; - } - function confp1_y() { - return 121; - } - } -} diff --git a/tests/php/time/DateTest.php b/tests/php/time/DateTest.php deleted file mode 100644 index 41d8da4..0000000 --- a/tests/php/time/DateTest.php +++ /dev/null @@ -1,85 +0,0 @@ -format()); - self::assertSame("05/04/2024", strval($date)); - self::assertSame(2024, $date->year); - self::assertSame(4, $date->month); - self::assertSame(5, $date->day); - self::assertSame(0, $date->hour); - self::assertSame(0, $date->minute); - self::assertSame(0, $date->second); - self::assertSame(5, $date->wday); - self::assertSame(14, $date->wnum); - self::assertSame("+04:00", $date->timezone); - self::assertSame("05/04/2024 00:00:00", $date->datetime); - self::assertSame("05/04/2024", $date->date); - } - - function testClone() { - $date = self::dt("now"); - $clone = Date::clone($date); - self::assertInstanceOf(DateTime::class, $clone); - } - - function testConstruct() { - $y = date("Y"); - self::assertSame("05/04/$y", strval(new Date("5/4"))); - self::assertSame("05/04/2024", strval(new Date("5/4/24"))); - self::assertSame("05/04/2024", strval(new Date("5/4/2024"))); - self::assertSame("05/04/2024", strval(new Date("05/04/2024"))); - self::assertSame("05/04/2024", strval(new Date("20240405"))); - self::assertSame("05/04/2024", strval(new Date("240405"))); - self::assertSame("05/04/2024", strval(new Date("20240405T091523"))); - self::assertSame("05/04/2024", strval(new Date("20240405T091523Z"))); - self::assertSame("05/04/2024", strval(new Date("5/4/2024 9:15:23"))); - self::assertSame("05/04/2024", strval(new Date("5/4/2024 9.15.23"))); - self::assertSame("05/04/2024", strval(new Date("5/4/2024 9:15"))); - self::assertSame("05/04/2024", strval(new Date("5/4/2024 9.15"))); - self::assertSame("05/04/2024", strval(new Date("5/4/2024 9h15"))); - self::assertSame("05/04/2024", strval(new Date("5/4/2024 09:15:23"))); - self::assertSame("05/04/2024", strval(new Date("5/4/2024 09:15"))); - self::assertSame("05/04/2024", strval(new Date("5/4/2024 09h15"))); - } - - function testCompare() { - $a = new Date("10/02/2024"); - $b = new Date("15/02/2024"); - $c = new Date("20/02/2024"); - $a2 = new Date("10/02/2024"); - $b2 = new Date("15/02/2024"); - $c2 = new Date("20/02/2024"); - - self::assertTrue($a == $a2); - self::assertFalse($a === $a2); - self::assertTrue($b == $b2); - self::assertTrue($c == $c2); - - self::assertFalse($a < $a); - self::assertTrue($a < $b); - self::assertTrue($a < $c); - - self::assertTrue($a <= $a); - self::assertTrue($a <= $b); - self::assertTrue($a <= $c); - - self::assertFalse($c > $c); - self::assertTrue($c > $b); - self::assertTrue($c > $a); - - self::assertTrue($c >= $c); - self::assertTrue($c >= $b); - self::assertTrue($c >= $a); - } -} diff --git a/tests/php/time/DateTimeTest.php b/tests/php/time/DateTimeTest.php deleted file mode 100644 index c0cd5ff..0000000 --- a/tests/php/time/DateTimeTest.php +++ /dev/null @@ -1,109 +0,0 @@ -format()); - self::assertEquals("05/04/2024 09:15:23", strval($date)); - self::assertSame(2024, $date->year); - self::assertSame(4, $date->month); - self::assertSame(5, $date->day); - self::assertSame(9, $date->hour); - self::assertSame(15, $date->minute); - self::assertSame(23, $date->second); - self::assertSame(5, $date->wday); - self::assertSame(14, $date->wnum); - self::assertEquals("+04:00", $date->timezone); - self::assertSame("05/04/2024 09:15:23", $date->datetime); - self::assertSame("05/04/2024", $date->date); - self::assertSame("20240405", $date->Ymd); - self::assertSame("20240405T091523", $date->YmdHMS); - self::assertSame("20240405T091523+04:00", $date->YmdHMSZ); - } - - function testDateTimeZ() { - $date = new DateTime("20240405T091523Z"); - self::assertSame("20240405T091523", $date->YmdHMS); - self::assertSame("20240405T091523Z", $date->YmdHMSZ); - } - - function testClone() { - $date = self::dt("now"); - $clone = DateTime::clone($date); - self::assertInstanceOf(DateTime::class, $clone); - } - - function testConstruct() { - $y = date("Y"); - self::assertSame("05/04/$y 00:00:00", strval(new DateTime("5/4"))); - self::assertSame("05/04/2024 00:00:00", strval(new DateTime("5/4/24"))); - self::assertSame("05/04/2024 00:00:00", strval(new DateTime("5/4/2024"))); - self::assertSame("05/04/2024 00:00:00", strval(new DateTime("05/04/2024"))); - self::assertSame("05/04/2024 00:00:00", strval(new DateTime("20240405"))); - self::assertSame("05/04/2024 00:00:00", strval(new DateTime("240405"))); - self::assertSame("05/04/2024 09:15:23", strval(new DateTime("20240405T091523"))); - self::assertSame("05/04/2024 09:15:23", strval(new DateTime("20240405T091523Z"))); - self::assertSame("05/04/2024 09:15:23", strval(new DateTime("5/4/2024 9:15:23"))); - self::assertSame("05/04/2024 09:15:23", strval(new DateTime("5/4/2024 9.15.23"))); - self::assertSame("05/04/2024 09:15:00", strval(new DateTime("5/4/2024 9:15"))); - self::assertSame("05/04/2024 09:15:00", strval(new DateTime("5/4/2024 9.15"))); - self::assertSame("05/04/2024 09:15:00", strval(new DateTime("5/4/2024 9h15"))); - self::assertSame("05/04/2024 09:15:23", strval(new DateTime("5/4/2024 09:15:23"))); - self::assertSame("05/04/2024 09:15:00", strval(new DateTime("5/4/2024 09:15"))); - self::assertSame("05/04/2024 09:15:00", strval(new DateTime("5/4/2024 09h15"))); - } - - function testCompare() { - $a = new DateTime("10/02/2024"); - $a2 = new DateTime("10/02/2024 8:30"); - $a3 = new DateTime("10/02/2024 15:45"); - $b = new DateTime("15/02/2024"); - $b2 = new DateTime("15/02/2024 8:30"); - $b3 = new DateTime("15/02/2024 15:45"); - $x = new DateTime("10/02/2024"); - $x2 = new DateTime("10/02/2024 8:30"); - $x3 = new DateTime("10/02/2024 15:45"); - - self::assertTrue($a == $x); - self::assertFalse($a === $x); - self::assertTrue($a2 == $x2); - self::assertTrue($a3 == $x3); - - self::assertFalse($a < $a); - self::assertTrue($a < $a2); - self::assertTrue($a < $a3); - self::assertTrue($a < $b); - self::assertTrue($a < $b2); - self::assertTrue($a < $b3); - - self::assertTrue($a <= $a); - self::assertTrue($a <= $a2); - self::assertTrue($a <= $a3); - self::assertTrue($a <= $b); - self::assertTrue($a <= $b2); - self::assertTrue($a <= $b3); - - self::assertTrue($b > $a); - self::assertTrue($b > $a2); - self::assertTrue($b > $a3); - self::assertFalse($b > $b); - self::assertFalse($b > $b2); - self::assertFalse($b > $b3); - - self::assertTrue($b >= $a); - self::assertTrue($b >= $a2); - self::assertTrue($b >= $a3); - self::assertTrue($b >= $b); - self::assertFalse($b >= $b2); - self::assertFalse($b >= $b3); - } -} diff --git a/tests/php/time/DelayTest.php b/tests/php/time/DelayTest.php deleted file mode 100644 index 55cb054..0000000 --- a/tests/php/time/DelayTest.php +++ /dev/null @@ -1,83 +0,0 @@ -getDest()); - - $delay = new Delay("10", $from); - self::assertEquals(self::dt("2024-04-05 09:15:33"), $delay->getDest()); - - $delay = new Delay("10s", $from); - self::assertEquals(self::dt("2024-04-05 09:15:33"), $delay->getDest()); - - $delay = new Delay("s", $from); - self::assertEquals(self::dt("2024-04-05 09:15:24"), $delay->getDest()); - - $delay = new Delay("5m", $from); - self::assertEquals(self::dt("2024-04-05 09:20:00"), $delay->getDest()); - - $delay = new Delay("5m0", $from); - self::assertEquals(self::dt("2024-04-05 09:20:00"), $delay->getDest()); - - $delay = new Delay("5m2", $from); - self::assertEquals(self::dt("2024-04-05 09:20:02"), $delay->getDest()); - - $delay = new Delay("m", $from); - self::assertEquals(self::dt("2024-04-05 09:16:00"), $delay->getDest()); - - $delay = new Delay("5h", $from); - self::assertEquals(self::dt("2024-04-05 14:00:00"), $delay->getDest()); - - $delay = new Delay("5h0", $from); - self::assertEquals(self::dt("2024-04-05 14:00:00"), $delay->getDest()); - - $delay = new Delay("5h2", $from); - self::assertEquals(self::dt("2024-04-05 14:02:00"), $delay->getDest()); - - $delay = new Delay("h", $from); - self::assertEquals(self::dt("2024-04-05 10:00:00"), $delay->getDest()); - - $delay = new Delay("5d", $from); - self::assertEquals(self::dt("2024-04-10 05:00:00"), $delay->getDest()); - - $delay = new Delay("5d2", $from); - self::assertEquals(self::dt("2024-04-10 02:00:00"), $delay->getDest()); - - $delay = new Delay("5d0", $from); - self::assertEquals(self::dt("2024-04-10 00:00:00"), $delay->getDest()); - - $delay = new Delay("d", $from); - self::assertEquals(self::dt("2024-04-06 05:00:00"), $delay->getDest()); - - $delay = new Delay("2w", $from); - self::assertEquals(self::dt("2024-04-21 05:00:00"), $delay->getDest()); - - $delay = new Delay("2w2", $from); - self::assertEquals(self::dt("2024-04-21 02:00:00"), $delay->getDest()); - - $delay = new Delay("2w0", $from); - self::assertEquals(self::dt("2024-04-21 00:00:00"), $delay->getDest()); - - $delay = new Delay("w", $from); - self::assertEquals(self::dt("2024-04-07 05:00:00"), $delay->getDest()); - } - - function testElapsed() { - $delay = new Delay(5); - sleep(2); - self::assertFalse($delay->isElapsed()); - sleep(5); - self::assertTrue($delay->isElapsed()); - } -} diff --git a/tests/strTest.php b/tests/strTest.php deleted file mode 100644 index 6fecc9d..0000000 --- a/tests/strTest.php +++ /dev/null @@ -1,28 +0,0 @@ - [ - 'name' => '', - 'type' => '', - 'tmp_name' => '', - 'error' => 4, - 'size' => 0, - ], - # name=multiple[], name=multiple[] - 'multiple' => [ - 'name' => [ - 0 => '', - 1 => '', - ], - 'type' => [ - 0 => '', - 1 => '', - ], - 'tmp_name' => [ - 0 => '', - 1 => '', - ], - 'error' => [ - 0 => 4, - 1 => 4, - ], - 'size' => [ - 0 => 0, - 1 => 0, - ], - ], - # name=onelevel[a], name=onelevel[b] - 'onelevel' => [ - 'name' => [ - 'a' => '', - 'b' => '', - ], - 'type' => [ - 'a' => '', - 'b' => '', - ], - 'tmp_name' => [ - 'a' => '', - 'b' => '', - ], - 'error' => [ - 'a' => 4, - 'b' => 4, - ], - 'size' => [ - 'a' => 0, - 'b' => 0, - ], - ], - # name=multiplelevel[a][], name=multiplelevel[a][], name=multiplelevel[b][], name=multiplelevel[b][] - 'multiplelevel' => [ - 'name' => [ - 'a' => [ - 0 => '', - 1 => '', - ], - 'b' => [ - 0 => '', - 1 => '', - ], - ], - 'type' => [ - 'a' => [ - 0 => '', - 1 => '', - ], - 'b' => [ - 0 => '', - 1 => '', - ], - ], - 'tmp_name' => [ - 'a' => [ - 0 => '', - 1 => '', - ], - 'b' => [ - 0 => '', - 1 => '', - ], - ], - 'error' => [ - 'a' => [ - 0 => 4, - 1 => 4, - ], - 'b' => [ - 0 => 4, - 1 => 4, - ], - ], - 'size' => [ - 'a' => [ - 0 => 0, - 1 => 0, - ], - 'b' => [ - 0 => 0, - 1 => 0, - ], - ], - ], - ]; - - const PARSED = [ - # name="simple" - 'simple' => [ - 'name' => '', - 'type' => '', - 'tmp_name' => '', - 'error' => 4, - 'size' => 0, - ], - # name=multiple[], name=multiple[] - 'multiple' => [ - 0 => [ - 'name' => '', - 'type' => '', - 'tmp_name' => '', - 'error' => 4, - 'size' => 0, - ], - 1 => [ - 'name' => '', - 'type' => '', - 'tmp_name' => '', - 'error' => 4, - 'size' => 0, - ], - ], - # name=onelevel[a], name=onelevel[b] - 'onelevel' => [ - 'a' => [ - 'name' => '', - 'type' => '', - 'tmp_name' => '', - 'error' => 4, - 'size' => 0, - ], - 'b' => [ - 'name' => '', - 'type' => '', - 'tmp_name' => '', - 'error' => 4, - 'size' => 0, - ], - ], - # name=multiplelevel[a][], name=multiplelevel[a][], name=multiplelevel[b][], name=multiplelevel[b][] - 'multiplelevel' => [ - 'a' => [ - 0 => [ - 'name' => '', - 'type' => '', - 'tmp_name' => '', - 'error' => 4, - 'size' => 0, - ], - 1 => [ - 'name' => '', - 'type' => '', - 'tmp_name' => '', - 'error' => 4, - 'size' => 0, - ], - ], - 'b' => [ - 0 => [ - 'name' => '', - 'type' => '', - 'tmp_name' => '', - 'error' => 4, - 'size' => 0, - ], - 1 => [ - 'name' => '', - 'type' => '', - 'tmp_name' => '', - 'error' => 4, - 'size' => 0, - ], - ], - ], - ]; - - function test_files() { - self::assertSame(self::PARSED, uploads::_files(self::_FILES)); - } -} diff --git a/tests/php/access/KeyAccessTest.php b/tests/wip/php/access/KeyAccessTest.php similarity index 96% rename from tests/php/access/KeyAccessTest.php rename to tests/wip/php/access/KeyAccessTest.php index b83c204..2b1c8ff 100644 --- a/tests/php/access/KeyAccessTest.php +++ b/tests/wip/php/access/KeyAccessTest.php @@ -1,8 +1,7 @@ null, "format" => null, "" => ["scalar"], + "schema" => null, "name" => null, "pkey" => null, "header" => null, diff --git a/tests/schema/types/boolTest.php b/tests/wip/schema/types/boolTest.php similarity index 96% rename from tests/schema/types/boolTest.php rename to tests/wip/schema/types/boolTest.php index 82dd766..b8d99c3 100644 --- a/tests/schema/types/boolTest.php +++ b/tests/wip/schema/types/boolTest.php @@ -1,10 +1,10 @@ Date: Tue, 4 Mar 2025 09:52:23 +0400 Subject: [PATCH 07/27] tstring et trawstring --- src/schema/_assoc/AssocResult.php | 2 +- src/schema/_assoc/AssocSchema.php | 4 +- src/schema/_assoc/AssocValue.php | 2 +- src/schema/_list/ListResult.php | 2 +- src/schema/_list/ListSchema.php | 2 +- src/schema/_list/ListValue.php | 2 +- src/schema/_scalar/ScalarSchema.php | 9 +- src/schema/_scalar/ScalarValue.php | 6 +- src/schema/types.php | 3 +- src/schema/types/Registry.php | 8 +- src/schema/types/_tsimple.php | 6 + src/schema/types/trawstring.php | 79 +++++++++ src/schema/types/tstring.php | 46 +----- tests/wip/schema/_scalar/ScalarValueTest.php | 162 +++++++++++++++++++ 14 files changed, 275 insertions(+), 58 deletions(-) create mode 100644 src/schema/types/trawstring.php create mode 100644 tests/wip/schema/_scalar/ScalarValueTest.php 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); + }); + } +} From 68023b72eeee6dcfaf5ff79c2f27b84caaf19017 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Tue, 4 Mar 2025 14:04:09 +0400 Subject: [PATCH 08/27] modifs.mineures sans commentaires --- .pman.conf | 8 +- src/schema/AnalyzerContext.php | 25 ++++ src/schema/Schema.php | 7 +- src/schema/_scalar/ScalarResult.php | 17 ++- src/schema/_scalar/ScalarValue.php | 66 +++++++-- src/schema/types.php | 4 +- src/schema/types/IType.php | 6 + src/schema/types/Registry.php | 10 +- src/schema/types/_tsimple.php | 12 ++ src/schema/types/tint.php | 22 ++- tests/wip/schema/_scalar/ScalarValueTest.php | 141 +++++++++++++++---- 11 files changed, 261 insertions(+), 57 deletions(-) create mode 100644 src/schema/AnalyzerContext.php diff --git a/.pman.conf b/.pman.conf index 483215c..db579e6 100644 --- a/.pman.conf +++ b/.pman.conf @@ -12,12 +12,16 @@ DIST= NOAUTO= AFTER_CREATE_RELEASE=' +set -x pman --composer-select-profile dist -composer u +composer u || exit 1 git commit -am "deps de dist" +true ' AFTER_MERGE_RELEASE=' +set -x pman --composer-select-profile dev -composer u +composer u || exit 1 git commit -am "deps de dev" +true ' diff --git a/src/schema/AnalyzerContext.php b/src/schema/AnalyzerContext.php new file mode 100644 index 0000000..3e540c9 --- /dev/null +++ b/src/schema/AnalyzerContext.php @@ -0,0 +1,25 @@ +schema = $schema; + $this->input = $input; + $this->destKey = $destKey; + $this->result = $result; + $this->type = null; + $this->value = null; + } + + public Schema $schema; + public Input $input; + /** @var int|string|null */ + public $destKey; + public Result $result; + public ?IType $type; + /** @var mixed */ + public $value; +} diff --git a/src/schema/Schema.php b/src/schema/Schema.php index bd5d11b..0e67c9d 100644 --- a/src/schema/Schema.php +++ b/src/schema/Schema.php @@ -57,8 +57,11 @@ abstract class Schema implements ArrayAccess { */ const SCHEMA = null; - /** @var array */ - protected $definition; + protected array $definition; + + function getDefinition(): array { + return $this->definition; + } /** retourner true si le schéma est de nature tableau associatif */ function isAssoc(?AssocSchema &$assoc=null): bool { return false; } diff --git a/src/schema/_scalar/ScalarResult.php b/src/schema/_scalar/ScalarResult.php index 3cd0e60..1ef71ee 100644 --- a/src/schema/_scalar/ScalarResult.php +++ b/src/schema/_scalar/ScalarResult.php @@ -16,11 +16,12 @@ use nur\sery\wip\schema\Result; * @property bool $null si la valeur est disponible, est-elle nulle? * @property bool $valid si la valeur est disponible, est-elle valide? * @property bool $normalized si la valeur est valide, est-elle normalisée? - * @property string|null $orig valeur originale avant analyse avec parse() + * @property string|null $orig valeur originale avant extraction et analyse + * @property string|null $messageKey clé de message si la valeur n'est pas valide * @property string|null $message message si la valeur n'est pas valide */ class ScalarResult extends Result { - const KEYS = ["resultAvailable", "present", "available", "null", "valid", "normalized", "orig", "message"]; + const KEYS = ["resultAvailable", "present", "available", "null", "valid", "normalized", "orig", "messageKey", "message"]; function isScalar(?ScalarResult &$scalar=null): bool { $scalar = $this; return true; } @@ -85,7 +86,8 @@ class ScalarResult extends Result { $this->normalized = true; return ref_analyze::NORMALIZED; } else { - $message = $this->getMessage("missing", $schema); + $messageKey = $this->messageKey = "missing"; + $message = $this->getMessage($messageKey, $schema); self::replace_key($message, $schema->name); $this->message = $message; return ref_analyze::MISSING; @@ -102,7 +104,8 @@ class ScalarResult extends Result { $this->normalized = true; return ref_analyze::NORMALIZED; } else { - $message = $this->getMessage("unavailable", $schema); + $messageKey = $this->messageKey = "unavailable"; + $message = $this->getMessage($messageKey, $schema); self::replace_key($message, $schema->name); $this->message = $message; return ref_analyze::UNAVAILABLE; @@ -119,7 +122,8 @@ class ScalarResult extends Result { $this->normalized = true; return ref_analyze::NORMALIZED; } else { - $message = $this->getMessage("null", $schema); + $messageKey = $this->messageKey = "null"; + $message = $this->getMessage($messageKey, $schema); self::replace_key($message, $schema->name); $this->message = $message; return ref_analyze::NULL; @@ -133,7 +137,8 @@ class ScalarResult extends Result { $this->null = false; $this->valid = false; $this->orig = $value; - $message = $this->getMessage("invalid", $schema); + $messageKey = $this->messageKey = "invalid"; + $message = $this->getMessage($messageKey, $schema); self::replace_key($message, $schema->name); self::replace_orig($message, $schema->orig); $this->message = $message; diff --git a/src/schema/_scalar/ScalarValue.php b/src/schema/_scalar/ScalarValue.php index b836465..b4d6269 100644 --- a/src/schema/_scalar/ScalarValue.php +++ b/src/schema/_scalar/ScalarValue.php @@ -1,9 +1,13 @@ input = $input; $this->destKey = $destKey; $this->type = null; - $this->_analyze(); + $this->analyzeExtractParse(); if ($verifix === null) $verifix = $this->defaultVerifix; if ($verifix) $this->verifix(); return $this; @@ -68,12 +72,12 @@ class ScalarValue extends Value { } /** analyser la valeur et résoudre son type */ - function _analyze(): int { + function _analyze(AnalyzerContext $context): int { $schema = $this->schema; $input = $this->input; $destKey = $this->destKey; $result = $this->result; - $result->reset(); + if (!$input->isPresent($destKey)) return $result->setMissing($schema); $haveType = false; @@ -82,8 +86,16 @@ class ScalarValue extends Value { $haveValue = false; $value = null; # d'abord chercher un type pour lequel c'est une valeur normalisée - foreach ($schema->type as $name) { - $type = types::get($name); + $index = 0; + foreach ($schema->type as $key => $name) { + if ($key === $index) { + $index++; + $params = null; + } else { + $params = $name; + $name = $key; + } + $type = types::get($name, $params, $this->schema->getDefinition()); if ($firstType === null) $firstType = $type; $types[] = $type; if ($type->isAvailable($input, $destKey)) { @@ -113,7 +125,7 @@ class ScalarValue extends Value { if (!$haveType) $type = $this->type = $firstType; if (!$type->isAvailable($input, $destKey)) return $result->setUnavailable($schema); - $value = $input->get($destKey); + $value = $context->value = $input->get($destKey); if ($type->isNull($value)) return $result->setNull($schema); if ($type->isValid($value, $normalized)) { if ($normalized) return $result->setNormalized(); @@ -124,6 +136,44 @@ class ScalarValue extends Value { else return $result->setInvalid($value, $schema); } + function _extract(AnalyzerContext $context): void { + $value = $context->value; + $value = $context->type->extract($value); + $context->value = $value; + } + + function _parse(AnalyzerContext $context): void { + $value = $context->value; + $value = $context->type->parse($value); + $context->value = $value; + } + + function analyzeExtractParse(): void { + $schema = $this->schema; + $input = $this->input; + $destKey = $this->destKey; + $result = $this->result; + $result->reset(); + $context = new AnalyzerContext($schema, $input, $destKey, $result); + + /** @var func $analyzerFunc */ + $analyzerFunc = $schema->analyzerFunc; + if ($analyzerFunc !== null) $what = $analyzerFunc->invoke([$context]); + else $what = $this->_analyze($context); + + if ($what === ref_analyze::STRING) { + /** @var func $extractorFunc */ + $extractorFunc = $schema->extractorFunc; + if ($extractorFunc !== null) $extractorFunc->invoke([$context]); + else $this->_extract($context); + + /** @var func $parserFunc */ + $parserFunc = $schema->parserFunc; + if ($parserFunc !== null) $parserFunc->invoke([$context]); + else $this->_parse($context); + } + } + function verifix(?bool $throw=null): bool { if ($throw === null) $throw = $this->defaultThrow; $destKey = $this->destKey; @@ -182,7 +232,7 @@ class ScalarValue extends Value { function set($value, ?bool $verifix=null): ScalarValue { $this->input->set($value, $this->destKey); - $this->_analyze(); + $this->analyzeExtractParse(); if ($verifix === null) $verifix = $this->defaultVerifix; if ($verifix) $this->verifix(); return $this; @@ -190,7 +240,7 @@ class ScalarValue extends Value { function unset(?bool $verifix=null): ScalarValue { $this->input->unset($this->destKey); - $this->_analyze(); + $this->analyzeExtractParse(); if ($verifix === null) $verifix = $this->defaultVerifix; if ($verifix) $this->verifix(); return $this; diff --git a/src/schema/types.php b/src/schema/types.php index ae3a11f..4c5c8f2 100644 --- a/src/schema/types.php +++ b/src/schema/types.php @@ -24,8 +24,8 @@ class types { return self::$registry; } - static function get(string $name): IType { - return self::registry()->get($name); + static function get(string $name, ?array $params=null, ?array $definition=null): IType { + return self::registry()->get($name, $params, $definition); } static function rawstring(): trawstring { return self::get("rawstring"); } diff --git a/src/schema/types/IType.php b/src/schema/types/IType.php index e470811..30969e1 100644 --- a/src/schema/types/IType.php +++ b/src/schema/types/IType.php @@ -18,6 +18,12 @@ interface IType { /** la valeur $value est-elle valide et normalisée le cas échéant? */ function isValid($value, ?bool &$normalized=null): bool; + /** extraire de la chaine la valeur à analyser */ + function extract(string $value): string; + + /** analyser la chaine et retourner la valeur "convertie" */ + function parse(string $value); + /** * analyser, corriger éventuellement et normaliser la valeur * diff --git a/src/schema/types/Registry.php b/src/schema/types/Registry.php index be8fe0c..b3c14a6 100644 --- a/src/schema/types/Registry.php +++ b/src/schema/types/Registry.php @@ -27,16 +27,14 @@ class Registry { /** @var IType[] */ protected $types; - function get(string $name, ?array $params=null): IType { + function get(string $name, ?array $params=null, ?array $definition=null): IType { + $class = self::TYPES[$name]; + $params = cl::merge($class::get_params($definition), $params); 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]; - $type = $this->types[$name] = new $class(); - } + if ($type === null) $type = $this->types[$name] = new $class(); return $type; } } diff --git a/src/schema/types/_tsimple.php b/src/schema/types/_tsimple.php index a300743..b858461 100644 --- a/src/schema/types/_tsimple.php +++ b/src/schema/types/_tsimple.php @@ -4,6 +4,10 @@ namespace nur\sery\wip\schema\types; use nur\sery\wip\schema\input\Input; abstract class _tsimple implements IType { + static function get_params(?array $definition): ?array { + return null; + } + function __construct(?array $params=null) { $this->params = $params; } @@ -17,4 +21,12 @@ abstract class _tsimple implements IType { function isNull($value): bool { return $value === null || (is_string($value) && trim($value) === ""); } + + function extract(string $value): string { + return $value; + } + + function parse(string $value) { + return $value; + } } diff --git a/src/schema/types/tint.php b/src/schema/types/tint.php index fb511e7..1f3b9b6 100644 --- a/src/schema/types/tint.php +++ b/src/schema/types/tint.php @@ -7,6 +7,13 @@ use nur\sery\wip\schema\Result; use nur\sery\wip\schema\Schema; class tint extends _tsimple { + static function get_params(?array $definition): ?array { + if ($definition === null) return null; + $format = $definition["format"] ?? null; + if ($format === null) return null; + return ["format" => $format]; + } + static function ensure_int(&$int): void { if (!is_int($int)) $int = intval($int); } @@ -15,12 +22,16 @@ class tint extends _tsimple { if ($int !== null) self::ensure_int($int); } - const INT_PATTERN = '/^[-+]?[0-9]+(?:\.[0-9]*)?$/'; + //const INT_PATTERN = '/^[-+]?[0-9]+(?:\.[0-9]*)?$/'; function isValid($value, ?bool &$normalized=null): bool { $normalized = is_int($value); - if (is_string($value)) $valid = is_numeric(trim($value)); - else $valid = is_scalar($value); + if (is_string($value)) { + $value = str_replace(",", ".", trim($value)); + $valid = is_numeric($value); + } else { + $valid = is_scalar($value); + } return $valid; } @@ -33,7 +44,7 @@ class tint extends _tsimple { $result->setNormalized(); return false; } elseif (is_string($value)) { - $int = trim($value); + $int = str_replace(",", ".", trim($value)); if (is_numeric($int)) $value = intval($int); else return $result->setInvalid($value, $schema); } elseif (is_scalar($value)) { @@ -41,11 +52,12 @@ class tint extends _tsimple { } else { return $result->setInvalid($value, $schema); } - $result->setValid(); + $result->setNormalized(); return true; } function format($value, $format=null): string { + $format ??= $this->params["format"] ?? null; if ($format !== null) return sprintf($format, $value); else return strval($value); } diff --git a/tests/wip/schema/_scalar/ScalarValueTest.php b/tests/wip/schema/_scalar/ScalarValueTest.php index a8bdc70..db29d83 100644 --- a/tests/wip/schema/_scalar/ScalarValueTest.php +++ b/tests/wip/schema/_scalar/ScalarValueTest.php @@ -35,26 +35,26 @@ class ScalarValueTest extends TestCase { $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 = "text"; $value->reset($string, null, false); + $this->checkValue($value, "text", true, true, true, true); + $string = "text"; $value->reset($string); + $this->checkValue($value, "text", 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 = " text "; $value->reset($string, null, false); + $this->checkValue($value, " text ", true, true, true, true); + $string = " text "; $value->reset($string); + $this->checkValue($value, " text ", 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 = 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 = 42; $value->reset($string, null, false); $this->checkValue($value, 42, true, true, true, false); $string = 42; $value->reset($string); @@ -108,26 +108,26 @@ class ScalarValueTest extends TestCase { $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 = "text"; $value->reset($string, null, false); + $this->checkValue($value, "text", true, true, true, true); + $string = "text"; $value->reset($string); + $this->checkValue($value, "text", 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 = " text "; $value->reset($string, null, false); + $this->checkValue($value, " text ", true, true, true, false); + $string = " text "; $value->reset($string); + $this->checkValue($value, "text", 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 = 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 = 42; $value->reset($string, null, false); $this->checkValue($value, 42, true, true, true, false); $string = 42; $value->reset($string); @@ -159,4 +159,93 @@ class ScalarValueTest extends TestCase { $string = false; $value->reset($string); }); } + + function testInt() { + $schema = new ScalarSchema("int"); + $value = $schema->newValue(); + + $int = null; $value->reset($int, null, false); + $this->checkValue($value, null, true, true, false, false); + self::assertException(ValueException::class, function() use (&$value) { + $int = null; + $value->reset($int); + }); + + $int = 42; $value->reset($int, null, false); + $this->checkValue($value, 42, true, true, true, true); + $int = 42; $value->reset($int); + $this->checkValue($value, 42, true, true, true, true); + + $int = "42"; $value->reset($int, null, false); + $this->checkValue($value, "42", true, true, true, false); + $int = "42"; $value->reset($int); + $this->checkValue($value, 42, true, true, true, true); + + $int = "42.5"; $value->reset($int, null, false); + $this->checkValue($value, "42.5", true, true, true, false); + $int = "42.5"; $value->reset($int); + $this->checkValue($value, 42, true, true, true, true); + + $int = "42,5"; $value->reset($int, null, false); + $this->checkValue($value, "42,5", true, true, true, false); + $int = "42,5"; $value->reset($int); + $this->checkValue($value, 42, true, true, true, true); + + $int = ""; $value->reset($int, null, false); + $this->checkValue($value, "", true, true, false, false); + self::assertException(ValueException::class, function() use (&$value) { + $int = ""; + $value->reset($int); + }); + + $int = " "; $value->reset($int, null, false); + $this->checkValue($value, " ", true, true, false, false); + self::assertException(ValueException::class, function() use (&$value) { + $int = " "; + $value->reset($int); + }); + + $int = "text"; $value->reset($int, null, false); + $this->checkValue($value, "text", true, true, false, true); + self::assertException(ValueException::class, function() use (&$value) { + $int = "text"; + $value->reset($int); + }); + + $int = false; $value->reset($int, null, false); + $this->checkValue($value, null, true, false, true, true); + $int = false; $value->reset($int); + $this->checkValue($value, null, true, false, true, true); + + $int = true; $value->reset($int, null, false); + $this->checkValue($value, true, true, true, true, false); + $int = true; $value->reset($int); + $this->checkValue($value, 1, true, true, true, true); + + $int = []; $value->reset($int, 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("?int"); + $value = $schema->newValue(); + + $int = null; $value->reset($int, null, false); + $this->checkValue($value, null, true, true, true, true); + $int = null; $value->reset($int, null); + $this->checkValue($value, null, true, true, true, true); + + ## Tester required + $schema = new ScalarSchema(["int", "required" => true]); + $value = $schema->newValue(); + + $int = false; $value->reset($int, null, false); + $this->checkValue($value, null, true, false, false, false); + self::assertException(ValueException::class, function() use (&$value) { + $string = false; $value->reset($string); + }); + } } From 74487a0ab95aa72bf8c675d0cb9a8cbb060b1f5e Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Wed, 5 Mar 2025 07:50:38 +0400 Subject: [PATCH 09/27] modifs.mineures sans commentaires --- .idea/inspectionProfiles/Project_Default.xml | 7 ++ .idea/php.xml | 15 ++++ src/schema/AnalyzerContext.php | 3 + src/schema/_scalar/ScalarValue.php | 85 +++++++++++++------- src/schema/types.php | 2 + src/schema/types/IType.php | 24 ++++-- src/schema/types/Registry.php | 3 +- src/schema/types/_tformatable.php | 19 +++++ src/schema/types/_tsimple.php | 12 +-- src/schema/types/_tstring.php | 26 ++++++ src/schema/types/tarray.php | 41 +++++++++- src/schema/types/tbool.php | 41 +++++----- src/schema/types/tcallable.php | 31 ++++++- src/schema/types/tcontent.php | 25 +++++- src/schema/types/tfloat.php | 36 +++++---- src/schema/types/tint.php | 50 +++++------- src/schema/types/tkey.php | 28 ++++++- src/schema/types/tpkey.php | 32 +++++++- src/schema/types/trawstring.php | 45 +++-------- src/schema/types/ttext.php | 7 ++ tests/wip/schema/_scalar/ScalarValueTest.php | 70 ++++++++++++---- 21 files changed, 432 insertions(+), 170 deletions(-) create mode 100644 src/schema/types/_tformatable.php create mode 100644 src/schema/types/_tstring.php create mode 100644 src/schema/types/ttext.php diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 03d9549..04f133a 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -2,5 +2,12 @@ \ No newline at end of file diff --git a/.idea/php.xml b/.idea/php.xml index 6a1b2d2..9891bef 100644 --- a/.idea/php.xml +++ b/.idea/php.xml @@ -10,6 +10,11 @@