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 @@
+
+
+
+
+
@@ -64,6 +69,11 @@
+
+
+
+
+
@@ -72,6 +82,11 @@
+
+
+
+
+
diff --git a/.pman.conf b/.pman.conf
index 68792b5..b25e544 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/CHANGES.md b/CHANGES.md
index 473dd3d..eca9977 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,14 @@
+## Release 0.4.0p74 du 14/03/2025-15:44
+
+* `4b84f11` début assocSchema
+* `7227cd7` maj TODO
+* `089e487` renommer dest en value; tenir compte de la valeur par défaut
+* `fc523bf` instancier type le plus vite possible
+* `f8eec57` renommer Value en Wrapper
+* `1aa266b` tstring et trawstring
+* `1a5ca79` support des colonnes
+* `9438aaf` ajout config .pman.yml
+
## Release 0.3.0p82 du 01/03/2025-13:49
## Release 0.3.0p74 du 01/03/2025-13:44
diff --git a/VERSION.txt b/VERSION.txt
index 0d91a54..1d0ba9e 100644
--- a/VERSION.txt
+++ b/VERSION.txt
@@ -1 +1 @@
-0.3.0
+0.4.0
diff --git a/composer.lock b/composer.lock
index d61a5e3..ee57541 100644
--- a/composer.lock
+++ b/composer.lock
@@ -589,7 +589,7 @@
"dist": {
"type": "path",
"url": "../nulib",
- "reference": "939f7726ab139071e8a3ef5c83fc147fba859d9d"
+ "reference": "927915093af5196099ae26645c07e90ddf1b2330"
},
"require": {
"ext-json": "*",
@@ -637,7 +637,7 @@
"dist": {
"type": "path",
"url": "../nulib-phpss",
- "reference": "a78623f5ae6891144b9581709847328b93342e1d"
+ "reference": "9e4f41e38deef10993d859202988567db9d4fada"
},
"require": {
"nulib/php": "^7.4-dev",
@@ -681,7 +681,7 @@
"dist": {
"type": "path",
"url": "../nulib-spout",
- "reference": "f9c420058015d02e913f0d65c41242ec7b8a0cee"
+ "reference": "65c74a1db6dda718aa20970ede3dfa4b4d32c791"
},
"require": {
"ext-dom": "*",
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 @@
dest =& $dest;
+ function __construct(&$array, $key, ?array $params=null) {
+ $this->array =& $array;
$this->key = $key;
$this->allowNull = $params["allow_null"] ?? true;
$this->allowFalse = $params["allow_false"] ?? false;
@@ -17,10 +17,10 @@ class KeyAccess extends AbstractAccess {
}
/** @var array|ArrayAccess */
- protected $dest;
+ protected $array;
- function reset(&$dest): self {
- $this->dest =& $dest;
+ function reset(&$array): self {
+ $this->array =& $array;
return $this;
}
@@ -36,12 +36,12 @@ class KeyAccess extends AbstractAccess {
function exists(): bool {
$key = $this->key;
if ($key === null) return false;
- return cl::has($this->dest, $key);
+ return cl::has($this->array, $key);
}
function available(): bool {
if (!$this->exists()) return false;
- $value = cl::get($this->dest, $this->key);
+ $value = cl::get($this->array, $this->key);
if ($value === null) return $this->allowNull;
if ($value === false) return $this->allowFalse;
if ($value === "") return $this->allowEmpty;
@@ -50,7 +50,7 @@ class KeyAccess extends AbstractAccess {
function get($default=null) {
if ($this->key === null) return $default;
- $value = cl::get($this->dest, $this->key, $default);
+ $value = cl::get($this->array, $this->key, $default);
if ($value === null && !$this->allowNull) return $default;
if ($value === false && !$this->allowFalse) return $default;
if ($value === "" && !$this->allowEmpty) return $default;
@@ -59,11 +59,11 @@ class KeyAccess extends AbstractAccess {
function set($value): void {
if ($this->key === null) return;
- cl::set($this->dest, $this->key, $value);
+ cl::set($this->array, $this->key, $value);
}
function del(): void {
if ($this->key === null) return;
- cl::del($this->dest, $this->key);
+ cl::del($this->array, $this->key);
}
}
diff --git a/src/php/access/PostAccess.php b/src/php/access/PostAccess.php
index ddc6329..1756964 100644
--- a/src/php/access/PostAccess.php
+++ b/src/php/access/PostAccess.php
@@ -1,7 +1,7 @@
dest =& $dest;
+ function __construct(&$value, ?array $params=null) {
+ $this->value =& $value;
$this->allowNull = $params["allow_null"] ?? false;
$this->allowFalse = $params["allow_false"] ?? true;
$this->allowEmpty = $params["allow_empty"] ?? true;
}
/** @var mixed */
- protected $dest;
+ protected $value;
- function reset(&$dest): self {
- $this->dest =& $dest;
+ function reset(&$value): self {
+ $this->value =& $value;
return $this;
}
@@ -27,19 +27,19 @@ class ValueAccess extends AbstractAccess {
protected bool $allowEmpty;
function exists(): bool {
- return $this->allowNull || $this->dest !== null;
+ return $this->allowNull || $this->value !== null;
}
function available(): bool {
if (!$this->exists()) return false;
- $value = $this->dest;
+ $value = $this->value;
if ($value === false) return $this->allowFalse;
if ($value === "") return $this->allowEmpty;
return true;
}
function get($default=null) {
- $value = $this->dest;
+ $value = $this->value;
if ($value === null && !$this->allowNull) return $default;
if ($value === false && !$this->allowFalse) return $default;
if ($value === "" && !$this->allowEmpty) return $default;
@@ -47,10 +47,10 @@ class ValueAccess extends AbstractAccess {
}
function set($value): void {
- $this->dest = $value;
+ $this->value = $value;
}
function del(): void {
- $this->dest = null;
+ $this->value = null;
}
}
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/src/schema/AnalyzerContext.php b/src/schema/AnalyzerContext.php
new file mode 100644
index 0000000..3136c04
--- /dev/null
+++ b/src/schema/AnalyzerContext.php
@@ -0,0 +1,30 @@
+schema = $schema;
+ $this->wrapper = $wrapper;
+ $this->input = $input;
+ $this->result = $result;
+ $this->type = null;
+ $this->origValue = null;
+ $this->value = null;
+ $this->valueKey = $valueKey;
+ }
+
+ public Schema $schema;
+ public Wrapper $wrapper;
+ public Input $input;
+ public Result $result;
+ public ?IType $type;
+ /** @var mixed */
+ public $origValue;
+ /** @var mixed */
+ public $value;
+ /** @var int|string|null */
+ public $valueKey;
+}
diff --git a/src/schema/README.md b/src/schema/README.md
index 48eed33..168c918 100644
--- a/src/schema/README.md
+++ b/src/schema/README.md
@@ -1,70 +1,60 @@
-# 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
-* tableau associatif
-* liste (tableau séquentiel ou associatif d'éléments du même type)
+les données dont on peut modéliser le schéma sont de 3 types: scalaire, tableau
+associatif ou liste. la nature du schéma (la valeur de la clé `"""`) indique le
+type de donnée modélisée
+* donnée scalaire
-chaque type de données a une syntaxe spécifique pour la définition du schéma.
-
-## Nature de schéma
-
-Un schéma se présente sous la forme d'un tableau associatif avec des clés qui
-dépendent de la nature du schéma. La nature du schéma est indiquée avec la clé
-`""` (chaine vide), e.g
-~~~php
-const SCHEMA = [
- "" => NATURE,
-];
-~~~
-
-La nature indique le type de données représenté par le schéma.
-* nature scalaire: modélise une donnée scalaire
+ forme courante:
+ ~~~php
+ const SCALAR_SCHEMA = [
+ $type, [$default, $title, ...]
+ ];
+ ~~~
+ forme normalisée:
~~~php
const SCALAR_SCHEMA = [
$type, [$default, $title, ...]
"" => "scalar",
];
~~~
- Si le type est "array" ou "?array", on peut préciser le schéma de la donnée
- ~~~php
- const SCALAR_SCHEMA = [
- "?array", [$default, $title, ...]
- "" => "scalar",
- "schema" => NAKED_SCHEMA,
- ];
- ~~~
-* nature tableau associatif: modélise un tableau associatif (le tableau peut
- avoir des clés numériques ou chaines --> seules les clés décrites par le
- schéma sont validées)
+* tableau associatif
+ le tableau modélisé peut avoir des clés numériques ou chaines --> seules les
+ clés décrites par le schéma sont validées
+
+ forme courante:
~~~php
const ASSOC_SCHEMA = [
KEY => VALUE_SCHEMA,
...
- "" => "assoc",
];
~~~
- la nature "tableau associatif" est du sucre syntaxique pour une valeur
- scalaire de type "?array" dont on précise le schéma
+ forme normalisée:
~~~php
- // la valeur ci-dessus est strictement équivalent à
const ASSOC_SCHEMA = [
- "?array",
- "" => "scalar",
+ "?array", [$default, $title, ...]
+ "" => "assoc",
"schema" => [
KEY => VALUE_SCHEMA,
...
],
];
~~~
+* liste (tableau d'éléments du même type)
+ le tableau modélisé peut avoir des clés numériques ou chaines --> on ne
+ modélise ni le type ni la valeur des clés
-* nature liste: modélise une liste de valeurs du même type (le tableau peut
- avoir des clés numériques ou chaines --> on ne modélise ni le type ni la
- valeur des clés)
+ forme courante:
+ ~~~php
+ const LIST_SCHEMA = [[
+ ITEM_SCHEMA,
+ ]];
+ ~~~
+ forme normalisée:
~~~php
const LIST_SCHEMA = [
"?array", [$default, $title, ...]
@@ -85,7 +75,8 @@ const SCALAR_SCHEMA = [
"required" => "la valeur est-elle requise? si oui, elle doit exister",
"nullable" => "si la valeur existe, peut-elle être nulle?",
"desc" => "description de la valeur",
- "checker_func" => "une fonction qui vérifie une valeur et la classifie",
+ "analyzer_func" => "XXX",
+ "extractor_func" => "XXX",
"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 +109,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 `analyzer_func`
~~~php
const MESSAGE_SCHEMA = [
"missing" => "message si la valeur n'existe pas dans la source et qu'elle est requise",
@@ -133,23 +124,27 @@ const MESSAGE_SCHEMA = [
## Schéma d'un tableau associatif
-Dans sa forme *non normalisée*, un tableau associatif est généralement modélisé
-de cette manière:
-~~~php
-const ASSOC_SCHEMA = [
- KEY => VALUE_SCHEMA,
- ...
- "" => "assoc",
-];
-~~~
-où chaque occurrence de `KEY => VALUE_SCHEMA` définit le schéma de la valeur
-dont la clé est `KEY`
-
-Si la nature du schéma n'est pas spécifiée, on considère que c'est un schéma de
-nature associative si:
+Dans la forme courante, on considère que c'est un schéma de nature associative si:
* c'est un tableau uniquement associatif avec aucun élément séquentiel, e.g
`["name" => "string", "age" => "int"]`
+La forme normalisée est
+~~~php
+const ASSOC_SCHEMA = [
+ "?array",
+ "" => "assoc",
+ "schema" => [
+ KEY => VALUE_SCHEMA,
+ ...
+ ],
+];
+~~~
+le type "?array" ou "array" indique si la liste est nullable ou non. la valeur
+par défaut est "?array"
+
+chaque occurrence de `KEY => VALUE_SCHEMA` définit le schéma de la valeur dont
+la clé est `KEY`
+
VALUE_SCHEMA peut-être n'importe quel schéma valide, qui sera analysé
récursivement, avec cependant l'ajout de quelques clés supplémentaires:
* description de la valeur dans le contexte du tableau
@@ -171,14 +166,11 @@ récursivement, avec cependant l'ajout de quelques clés supplémentaires:
## Schéma d'une liste (tableau séquentiel ou associatif d'éléments du même type)
-Dans sa forme *non normalisée*, une liste est généralement modélisée de cette
-manière:
-~~~php
-const LIST_SCHEMA = [ITEM_SCHEMA];
-~~~
-où ITEM_SCHEMA est le schéma des éléments de la liste
+Dans la forme courante, on considère que c'est un schéma de nature liste si:
+* c'est un tableau avec un unique élément de type tableau à l'index 0, e.g
+ `[["string", null, "required" => true]]`
-Pour information, la forme normalisée est plutôt de la forme
+La forme normalisée est
~~~php
const LIST_SCHEMA = [
"?array",
@@ -189,9 +181,4 @@ const LIST_SCHEMA = [
le type "?array" ou "array" indique si la liste est nullable ou non. la valeur
par défaut est "?array"
-Si la nature du schéma n'est pas spécifiée, on considère que c'est un schéma de
-nature liste si:
-* c'est un tableau avec un unique élément de type tableau à l'index 0, e.g
- `[["string", null, "required" => true]]`
-
-*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary
\ No newline at end of file
diff --git a/src/schema/Result.php b/src/schema/Result.php
index e3d696b..3ccb261 100644
--- a/src/schema/Result.php
+++ b/src/schema/Result.php
@@ -1,21 +1,42 @@
reset();
}
- function isAssoc(?AssocResult &$assoc=null): bool { return false; }
- function isList(?ListResult &$list=null): bool { return false; }
- function isScalar(?ScalarResult &$scalar=null): bool { return false; }
+ function isAssoc(?AssocResult &$result=null): bool { return false; }
+ function isList(?ListResult &$result=null): bool { return false; }
+ function isScalar(?ScalarResult &$result=null): bool { return false; }
/**
* Obtenir la liste des clés valides pour les valeurs accessibles via cet
@@ -23,8 +44,21 @@ abstract class Result {
*/
abstract function getKeys(): array;
- /** obtenir un objet pour gérer la valeur spécifiée */
- abstract function getResult($key=null): Result;
+ /**
+ * sélectionner le résultat associé à la clé spécifiée
+ *
+ * @param string|int|null $key
+ * @return Result $this
+ */
+ abstract function select($key): Result;
+ function getIterator() {
+ foreach ($this->getKeys() as $key) {
+ yield $key => $this->select($key);
+ }
+ $this->select(null);
+ }
+
+ /** réinitialiser tous les objets résultats accessibles via cet objet */
abstract function reset(): void;
}
diff --git a/src/schema/Schema.php b/src/schema/Schema.php
index d8bcc8a..0bbd86e 100644
--- a/src/schema/Schema.php
+++ b/src/schema/Schema.php
@@ -2,15 +2,24 @@
namespace nur\sery\wip\schema;
use ArrayAccess;
-use nur\sery\AccessException;
-use nur\sery\cl;
+use nulib\AccessException;
+use nulib\cl;
+use nulib\ref\schema\ref_schema;
+use nulib\ref\schema\ref_types;
use nur\sery\wip\schema\_assoc\AssocSchema;
use nur\sery\wip\schema\_list\ListSchema;
use nur\sery\wip\schema\_scalar\ScalarSchema;
+use nur\sery\wip\schema\types\IType;
+use nur\sery\wip\schema\types\tarray;
+use nur\sery\wip\schema\types\tbool;
+use nur\sery\wip\schema\types\tcallable;
+use nur\sery\wip\schema\types\tcontent;
+use nur\sery\wip\schema\types\tpkey;
+use nur\sery\wip\schema\types\trawstring;
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
@@ -18,18 +27,18 @@ abstract class Schema implements ArrayAccess {
* l'instance de Schema nouvelle créée
* - sinon, prendre $definition comme définition
*/
- static function ns(&$schema, $definition=null, $definitionKey=null): self {
+ static function ns(&$schema, $definition=null, $definitionKey=null, bool $normalize=true): self {
if (is_array($schema)) {
$definition = $schema;
$schema = null;
}
if ($schema === null) {
if (AssocSchema::isa_definition($definition)) {
- $schema = new AssocSchema($definition, $definitionKey);
+ $schema = new AssocSchema($definition, $definitionKey, $normalize);
} elseif (ListSchema::isa_definition($definition)) {
- $schema = new ListSchema($definition, $definitionKey);
+ $schema = new ListSchema($definition, $definitionKey, $normalize);
} elseif (ScalarSchema::isa_definition($definition)) {
- $schema = new ScalarSchema($definition, $definitionKey);
+ $schema = new ScalarSchema($definition, $definitionKey, $normalize);
} else {
throw SchemaException::invalid_schema();
}
@@ -38,17 +47,189 @@ abstract class Schema implements ArrayAccess {
}
/**
- * Créer si besoin 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
+ * Créer une nouvelle instance de {@link Wrapper} qui référence la
+ * variable $value (si $valueKey===null) ou $value[$valueKey] si $valueKey
+ * n'est pas null
*/
- static function nv(?Value &$destv=null, &$dest=null, $destKey=null, &$schema=null, $definition=null): Value {
+ static function nw(&$value=null, $valueKey=null, &$schema=null, $definition=null, ?Wrapper &$wrapper=null): Wrapper {
if ($definition === null) {
# bien que techniquement, $definition peut être null (il s'agit alors du
# schéma d'un scalaire quelconque), on ne l'autorise pas ici
throw SchemaException::invalid_schema("definition is required");
}
- return self::ns($schema, $definition)->newValue($destv, $dest, $destKey);
+ return self::ns($schema, $definition)->getWrapper($value, $valueKey, $wrapper);
+ }
+
+ protected static function have_nature(array $definition, ?string &$nature=null): bool {
+ $definitionNature = $definition[""] ?? null;
+ if (is_string($definitionNature)) {
+ $nature = $definitionNature;
+ return true;
+ }
+ if (is_array($definitionNature)
+ && array_key_exists(0, $definitionNature)
+ && is_string($definitionNature[0])) {
+ $nature = $definitionNature;
+ return true;
+ }
+ return false;
+ }
+
+ protected static function _normalize(&$definition, $definitionKey=null): void {
+ if (!is_array($definition)) $definition = [$definition];
+ # s'assurer que toutes les clés existent avec leur valeur par défaut
+ $index = 0;
+ foreach (array_keys(ref_schema::SCALAR_METASCHEMA) as $key) {
+ if (!array_key_exists($key, $definition)) {
+ if (array_key_exists($index, $definition)) {
+ $definition[$key] = $definition[$index];
+ unset($definition[$index]);
+ $index++;
+ } else {
+ $definition[$key] = ref_schema::SCALAR_METASCHEMA[$key][1];
+ }
+ }
+ }
+ # réordonner les clés numériques
+ if (cl::have_num_keys($definition)) {
+ $keys = array_keys($definition);
+ $index = 0;
+ foreach ($keys as $key) {
+ if (!is_int($key)) continue;
+ if ($key !== $index) {
+ $definition[$index] = $definition[$key];
+ unset($definition[$key]);
+ }
+ $index++;
+ }
+ }
+ # type
+ $types = [];
+ $deftype = $definition["type"];
+ $nullable = $definition["nullable"] ?? false;
+ if ($deftype === null) {
+ $types[] = null;
+ $nullable = true;
+ } else {
+ if (!is_array($deftype)) {
+ if (!is_string($deftype)) throw SchemaException::invalid_type($deftype);
+ $deftype = explode("|", $deftype);
+ }
+ foreach ($deftype as $type) {
+ if ($type !== null) $type = trim($type);
+ if ($type === null || $type === "null") {
+ $nullable = true;
+ continue;
+ }
+ if (!is_string($type)) throw SchemaException::invalid_type($type);
+ if (substr($type, 0, 1) == "?") {
+ $type = substr($type, 1);
+ $nullable = true;
+ }
+ if ($type === "") throw SchemaException::invalid_type($type);
+ $type = cl::get(ref_types::ALIASES, $type, $type);
+ $types = array_merge($types, explode("|", $type));
+ }
+ if (!$types) throw SchemaException::invalid_schema("scalar: type is required");
+ $types = array_keys(array_fill_keys($types, true));
+ }
+ $definition["type"] = $types;
+ $definition["nullable"] = $nullable;
+ # nature
+ $nature = $definition[""];
+ tarray::ensure_array($nature);
+ $definition[""] = $nature;
+ # name, pkey, header
+ $name = $definition["name"];
+ $pkey = $definition["pkey"];
+ $header = $definition["header"];
+ if ($name === null) $name = $definitionKey;
+ trawstring::ensure_nstring($name);
+ tpkey::ensure_npkey($pkey);
+ trawstring::ensure_nstring($header);
+ if ($pkey === null) $pkey = $name;
+ if ($header === null) $header = $name;
+ $definition["name"] = $name;
+ $definition["pkey"] = $pkey;
+ $definition["header"] = $header;
+ # autres éléments
+ tarray::ensure_narray($definition["schema"]);
+ trawstring::ensure_nstring($definition["title"]);
+ tbool::ensure_bool($definition["required"]);
+ tbool::ensure_bool($definition["nullable"]);
+ tcontent::ensure_ncontent($definition["desc"]);
+ tcallable::ensure_ncallable($definition["analyzer_func"]);
+ tcallable::ensure_ncallable($definition["extractor_func"]);
+ tcallable::ensure_ncallable($definition["parser_func"]);
+ tcallable::ensure_ncallable($definition["normalizer_func"]);
+ tarray::ensure_narray($definition["messages"]);
+ tcallable::ensure_ncallable($definition["formatter_func"]);
+ tbool::ensure_nbool($definition["composite"]);
+
+ switch ($nature[0] ?? null) {
+ case "assoc":
+ foreach ($definition["schema"] as $key => &$keydef) {
+ self::_normalize($keydef, $key);
+ }; unset($keydef);
+ break;
+ case "list":
+ self::_normalize($definition["schema"]);
+ break;
+ }
+ }
+
+ protected static function _ensure_nature(array $definition, string $expectedNature, ?string $expectedType=null): void {
+ $nature = $definition[""];
+ if (!array_key_exists(0, $nature) || $nature[0] !== $expectedNature) {
+ throw SchemaException::invalid_schema("$nature: invalid nature. expected $expectedNature");
+ }
+ if ($expectedType !== null) {
+ $types = $definition["type"];
+ if (count($types) !== 1 || $types[0] !== $expectedType) {
+ throw new SchemaException("{$types[O]}: invalide type. expected $expectedType");
+ }
+ }
+ }
+
+ protected static function _ensure_type(array &$definition): void {
+ $types = $definition["type"];
+ $nullable = $definition["nullable"];
+ # s'il n'y a qu'une seul type, l'instancier tout de suite
+ if (is_array($types) && count($types) == 1 && $types[0] !== null) {
+ foreach ($types as $key => $name) {
+ if ($key === 0) {
+ $args = null;
+ } else {
+ $args = $name;
+ $name = $key;
+ }
+ $definition["type"] = types::get($nullable, $name, $args, $definition);
+ }
+ }
+ switch ($definition[""][0]) {
+ case "assoc":
+ foreach ($definition["schema"] as &$keydef) {
+ self::_ensure_type($keydef);
+ }; unset($keydef);
+ break;
+ case "list":
+ self::_ensure_type($definition["schema"]);
+ break;
+ }
+ }
+
+ protected static function _ensure_schema_instances(array &$definition): void {
+ switch ($definition[""][0]) {
+ case "assoc":
+ foreach ($definition["schema"] as &$keydef) {
+ self::_ensure_schema_instances($keydef);
+ Schema::ns($keydef, null, null, false);
+ }; unset($keydef);
+ break;
+ case "list":
+ Schema::ns($definition["schema"], null, null, false);
+ break;
+ }
}
/**
@@ -57,17 +238,22 @@ abstract class Schema implements ArrayAccess {
*/
const SCHEMA = null;
- /** @var array */
- protected $definition;
+ protected array $_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; }
+ function isAssoc(?AssocSchema &$schema=null): bool { return false; }
/** retourner true si le schéma est de nature liste */
- function isList(?ListSchema &$list=null): bool { return false; }
+ function isList(?ListSchema &$schema=null): bool { return false; }
/** retourner true si le schéma est de nature scalaire */
- function isScalar(?ScalarSchema &$scalar=null): bool { return false; }
+ function isScalar(?ScalarSchema &$schema=null): bool { return false; }
- abstract function newValue(?Value &$destv=null, &$dest=null, $destKey=null): Value;
+ abstract function getWrapper(&$value=null, $valueKey=null, ?Wrapper &$wrapper=null): Wrapper;
#############################################################################
# key & properties
diff --git a/src/schema/TODO.md b/src/schema/TODO.md
index 5184f37..a7a5233 100644
--- a/src/schema/TODO.md
+++ b/src/schema/TODO.md
@@ -1,19 +1,36 @@
-# nur\sery\schema
+# nulib\schema
+
+* tdate et tdatetime. qu'en est-il des autres classes (delay, etc.)
+ * possibilité de spécifier le format de la date à analyser
+* ScalarSchema::from_property()
+* possibilité de spécifier un type via sa classe, e.g
+ ~~~php
+ Schema::ns($schema, [
+ MyType::class, null, "une valeur de type MyType"
+ ]);
+ ~~~
+ MyType doit implémenter IType
+* type générique construit à partir d'un nom de classe, e.g
+ ~~~php
+ Schema::ns($schema, [
+ MyClass::class, null, "une valeur de type MyClass"
+ ]);
+ ~~~
+ MyClass ne doit pas implémenter IType, et le type correspondant est créé avec
+ `new tgeneric(MyClass::class)`
-* implémenter support `analyzer_func`, `extractor_func`, `parser_func`,
- `normalizer_func`, `formatter_func`
* dans AssocSchema, support `[key_prefix]` qui permet de spécifier un préfixe
commun aux champs dans le tableau destination, e.g
~~~php
- $value = Schema::ns($schema, [
+ $wrapper = Schema::ns($schema, [
"a" => "?string",
"b" => "?int",
- ])->newValue();
- $dest = ["x_a" => 5, "x_b" => "10"],
- $value->reset($dest, null, [
+ ])->newWrapper();
+ $value = ["x_a" => 5, "x_b" => "10"],
+ $wrapper->reset($value, null, [
"key_prefix" => "x_",
]);
- # $dest vaut ["x_a" => "5", "x_b" => 10];
+ # $value vaut ["x_a" => "5", "x_b" => 10];
~~~
définir si le préfixe doit être spécifié sur le schéma ou sur la valeur...
actuellement, le code ne permet pas de définir de tels paramètres...
@@ -21,48 +38,16 @@
alternative: c'est lors de la *définition* du schéma que le préfixe est ajouté
e.g
~~~php
- $value = Schema::ns($schema, [
+ $wrapper = Schema::ns($schema, [
"a" => "?string",
"b" => "?int",
], [
"key_prefix" => "x_",
- ])->newValue();
- $dest = ["x_a" => 5, "x_b" => "10"],
- $value->reset($dest);
- # $dest vaut ["x_a" => "5", "x_b" => 10];
+ ])->newWrapper();
+ $value = ["x_a" => 5, "x_b" => "10"],
+ $wrapper->reset($value);
+ # $value vaut ["x_a" => "5", "x_b" => 10];
~~~
-* dans la définition, `[type]` est remplacé par l'instance de IType lors de sa
- résolution?
-* implémenter l'instanciation de types avec des paramètres particuliers. *si*
- des paramètres sont fournis, le type est instancié avec la signature
- `IType($typeDefinition, $schemaDefinition)` e.g
- ~~~php
- const SCHEMA = ["type", default, "required" => true];
- # le type est instancié comme suit:
- $type = new ttype();
-
- 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
- $type = new ttype(["type", ...], SCHEMA);
- ~~~
-* ajouter à IType les méthodes getName() pour le nom officiel du type,
- getAliases() pour les alias supportés, et getClass() pour la définition de la
- classe dans les méthodes et propriétés
- getName() et getAliases() sont juste pour information, ils ne sont pas utilisés
- lors de la résolution du type effectif.
-* si cela a du sens, dans AssocSchema, n'instancier les schémas de chaque clé qu'à la demande.
- l'idée est de ne pas perdre du temps à instancier un schéma qui ne serait pas utilisé
-
- on pourrait avoir d'une manière générale quelque chose comme:
- ~~~
- Schema::ensure(&$schema, ?array $def=null, $defKey=null): Schema;
- ~~~
- * si $schema est une instance de Schema, la retourner
- * si c'est un array, c'est une définition et il faut la remplacer par l'instance de Schema correspondant
- * sinon, prendre $def comme définition
- $key est la clé si $schema est dans un autre schema
* actuellement, pour un schéma associatif, si on normalise un tableau séquentiel,
chaque valeur correspond à la clé de même rang, eg. pour un schéma
~~~php
diff --git a/src/schema/Value.php b/src/schema/Wrapper.php
similarity index 65%
rename from src/schema/Value.php
rename to src/schema/Wrapper.php
index f09341f..d8cafed 100644
--- a/src/schema/Value.php
+++ b/src/schema/Wrapper.php
@@ -3,18 +3,18 @@ namespace nur\sery\wip\schema;
use ArrayAccess;
use IteratorAggregate;
-use nur\sery\wip\schema\_assoc\AssocValue;
-use nur\sery\wip\schema\_list\ListValue;
-use nur\sery\wip\schema\_scalar\ScalarValue;
+use nur\sery\wip\schema\_assoc\AssocWrapper;
+use nur\sery\wip\schema\_list\ListWrapper;
+use nur\sery\wip\schema\_scalar\ScalarWrapper;
use nur\sery\wip\schema\types\IType;
-abstract class Value implements ArrayAccess, IteratorAggregate {
- function isAssoc(?AssocValue &$assoc=null): bool { return false; }
- function isList(?ListValue &$list=null): bool { return false; }
- function isScalar(?ScalarValue &$scalar=null): bool { return false; }
+abstract class Wrapper implements ArrayAccess, IteratorAggregate {
+ function isAssoc(?AssocWrapper &$wrapper=null): bool { return false; }
+ function isList(?ListWrapper &$wrapper=null): bool { return false; }
+ function isScalar(?ScalarWrapper &$wrapper=null): bool { return false; }
/** spécifier la valeur destination gérée par cet objet */
- abstract function reset(&$dest, $destKey=null, ?bool $verifix=null): self;
+ abstract function reset(&$value, $valueKey=null, ?bool $verifix=null): self;
/**
* Obtenir la liste des clés valides pour les valeurs accessibles via cet
@@ -22,13 +22,19 @@ abstract class Value implements ArrayAccess, IteratorAggregate {
*/
abstract function getKeys(): array;
- /** obtenir un objet pour gérer la valeur spécifiée */
- abstract function getValue($key=null): Value;
+ /**
+ * sélectionner le wrapper associé à la clé spécifiée
+ *
+ * @param string|int|null $key
+ * @return Wrapper $this
+ */
+ abstract function select($key): Wrapper;
function getIterator() {
foreach ($this->getKeys() as $key) {
- yield $key => $this->getValue($key);
+ yield $key => $this->select($key);
}
+ $this->select(null);
}
/**
@@ -72,14 +78,14 @@ abstract class Value implements ArrayAccess, IteratorAggregate {
}
function offsetGet($offset) {
- return $this->getValue($offset);
+ return $this->select($offset);
}
function offsetSet($offset, $value): void {
- $this->getValue($offset)->set($value);
+ $this->select($offset)->set($value);
}
function offsetUnset($offset): void {
- $this->getValue($offset)->unset();
+ $this->select($offset)->unset();
}
}
diff --git a/src/schema/_assoc/AssocResult.php b/src/schema/_assoc/AssocResult.php
index d55f723..8ac0c77 100644
--- a/src/schema/_assoc/AssocResult.php
+++ b/src/schema/_assoc/AssocResult.php
@@ -1,8 +1,53 @@
arrayResult = $arrayResult;
+ $this->keyResults =& $keyResults;
+ $this->result =& $this->arrayResult;
+ parent::__construct();
+ }
+
+ function isAssoc(?AssocResult &$result=null): bool { $result = $this; return true;}
+
+ protected Result $arrayResult;
+
+ /** @var Result[] */
+ protected array $keyResults;
+
+ function getKeys(): array {
+ return array_keys($this->keyResults);
+ }
+
+ protected Result $result;
+
+ function select($key): Result {
+ if ($key === null) {
+ $this->result =& $this->arrayResult;
+ } elseif (array_key_exists($key, $this->keyResults)) {
+ $this->result =& $this->keyResults[$key];
+ } else {
+ throw ValueException::invalid_key($key);
+ }
+ return $this;
+ }
+
+ function reset(): void {
+ $this->arrayResult->reset();
+ foreach ($this->keyResults as $result) {
+ $result->reset();
+ }
+ }
+
+ function __get(string $name) {
+ return $this->result[$name];
+ }
+
+ function __set(string $name, $value): void {
+ $this->result[$name] = $value;
+ }
}
diff --git a/src/schema/_assoc/AssocSchema.php b/src/schema/_assoc/AssocSchema.php
index e39e8e6..cabcc38 100644
--- a/src/schema/_assoc/AssocSchema.php
+++ b/src/schema/_assoc/AssocSchema.php
@@ -1,10 +1,10 @@
"assoc",
+ "schema" => $definition,
+ ];
+ }
+ self::_normalize($definition, $definitionKey);
+ self::_ensure_nature($definition, "assoc", "array");
+ return $definition;
}
function __construct($definition=null, $definitionKey=null, bool $normalize=true) {
if ($definition === null) $definition = static::SCHEMA;
- if ($normalize) $definition = self::normalize($definition, $definitionKey);
+ if ($normalize) {
+ $definition = self::normalize($definition, $definitionKey);
+ $this->_definition = $definition;
+ self::_ensure_type($definition);
+ self::_ensure_schema_instances($definition);
+ }
$this->definition = $definition;
}
- function isAssoc(?AssocSchema &$assoc=null): bool {
- $assoc = $this;
+ function isAssoc(?AssocSchema &$schema=null): bool {
+ $schema = $this;
return true;
}
- function newValue(?Value &$destv=null, &$dest=null, $destKey=null): AssocValue {
- if ($destv instanceof AssocValue) return $destv->reset($dest, $destKey);
- else return ($destv = new AssocValue($this, $dest, $destKey));
+ protected function newWrapper(): AssocWrapper {
+ return new AssocWrapper($this);
+ }
+
+ function getWrapper(&$array=null, $arrayKey=null, ?Wrapper &$wrapper=null): AssocWrapper {
+ if (!($wrapper instanceof AssocWrapper)) $wrapper = $this->newWrapper();
+ return $wrapper->reset($array, $arrayKey);
}
}
diff --git a/src/schema/_assoc/AssocValue.php b/src/schema/_assoc/AssocValue.php
deleted file mode 100644
index 06a5dc4..0000000
--- a/src/schema/_assoc/AssocValue.php
+++ /dev/null
@@ -1,18 +0,0 @@
-schema = $schema;
+ $this->verifix = $verifix;
+ $this->throw = $throw ?? false;
+ $this->result = new AssocResult();
+ $this->reset($array, $arrayKey);
+ $this->throw = $throw ?? true;
+ }
+
+ function isAssoc(?AssocWrapper &$wrapper=null): bool { $wrapper = $this; return true; }
+
+ protected bool $verifix;
+
+ protected bool $throw;
+
+ /** schéma de ce tableau */
+ protected AssocSchema $schema;
+
+ /** source et destination de la valeur */
+ protected Input $input;
+
+ /** @var string|int|null clé du tableau dans le tableau destination */
+ protected $arrayKey;
+
+ protected IType $arrayType;
+
+ protected ScalarResult $arrayResult;
+
+ /** @var IType[] */
+ protected array $keyTypes;
+
+ /** @var Result[] */
+ protected array $keyResults;
+
+ protected AssocResult $result;
+
+ protected ?array $keys;
+
+ protected ?array $wrappers;
+
+ protected function newInput(&$value): Input {
+ return new Input($value);
+ }
+
+ function reset(&$array, $arrayKey=null, ?bool $verifix=null): Wrapper {
+ if ($array instanceof Input) $input = $array;
+ else $input = $this->newInput($array);
+ $this->input = $input;
+ $this->arrayKey = $arrayKey;
+ $this->analyze();
+ if ($verifix ?? $this->verifix) $this->verifix();
+ return $this;
+ }
+
+ function getKeys(): array {
+ return $this->keys;
+ }
+
+ function select($key=null): ScalarWrapper {
+ $wrapper = $this->wrappers[$key] ?? null;
+ if ($key !== null) return $wrapper;
+ throw ValueException::invalid_key($key);
+ }
+
+ /** @param Result[] $results */
+ function verifix(?bool $throw=null, ?array &$results=null): bool {
+ }
+
+
+ function getResult(): AssocResult {
+ return $this->result;
+ }
+
+ function isPresent(): bool {
+ return $this->result->present;
+ }
+
+ function getType(): IType {
+ return $this->arrayType;
+ }
+
+ function isAvailable(): bool {
+ return $this->result->available;
+ }
+
+ function isValid(): bool {
+ return $this->result->valid;
+ }
+
+ function isNormalized(): bool {
+ return $this->result->normalized;
+ }
+
+ function get($default=null) {
+ if ($this->result->available) return $this->input->get($this->arrayKey);
+ else return $default;
+ }
+
+ function set($value, ?bool $verifix=null): AssocWrapper {
+ $this->input->set($value, $this->arrayKey);
+ $this->analyze();
+ if ($verifix ?? $this->verifix) $this->verifix();
+ return $this;
+ }
+
+ function unset(?bool $verifix=null): AssocWrapper {
+ $this->input->unset($this->arrayKey);
+ $this->analyze();
+ if ($verifix ?? $this->verifix) $this->verifix();
+ return $this;
+ }
+
+ function format($format = null): string {
+ // TODO: Implement format() method.
+ }
+
+ function ensureKeys(): bool {
+ }
+ function orderKeys(): bool {
+ }
+}
diff --git a/src/schema/_list/ListResult.php b/src/schema/_list/ListResult.php
index 1a2af4e..b40aadb 100644
--- a/src/schema/_list/ListResult.php
+++ b/src/schema/_list/ListResult.php
@@ -1,8 +1,53 @@
arrayResult = $arrayResult;
+ $this->keyResults =& $keyResults;
+ $this->result =& $this->arrayResult;
+ parent::__construct();
+ }
+
+ function isList(?ListResult &$result=null): bool { $result = $this; return true;}
+
+ protected Result $arrayResult;
+
+ /** @var Result[] */
+ protected array $keyResults;
+
+ function getKeys(): array {
+ return array_keys($this->keyResults);
+ }
+
+ protected Result $result;
+
+ function select($key): Result {
+ if ($key === null) {
+ $this->result =& $this->arrayResult;
+ } elseif (array_key_exists($key, $this->keyResults)) {
+ $this->result =& $this->keyResults[$key];
+ } else {
+ throw ValueException::invalid_key($key);
+ }
+ return $this;
+ }
+
+ function reset(): void {
+ $this->arrayResult->reset();
+ foreach ($this->keyResults as $result) {
+ $result->reset();
+ }
+ }
+
+ function __get(string $name) {
+ return $this->result[$name];
+ }
+
+ function __set(string $name, $value): void {
+ $this->result[$name] = $value;
+ }
}
diff --git a/src/schema/_list/ListSchema.php b/src/schema/_list/ListSchema.php
index a0565d0..f75b759 100644
--- a/src/schema/_list/ListSchema.php
+++ b/src/schema/_list/ListSchema.php
@@ -1,9 +1,9 @@
"list",
+ "schema" => $definition[0],
+ ];
+ }
+ self::_normalize($definition, $definitionKey);
+ self::_ensure_nature($definition, "list", "array");
+ return $definition;
}
function __construct($definition=null, $definitionKey=null, bool $normalize=true) {
if ($definition === null) $definition = static::SCHEMA;
- if ($normalize) $definition = self::normalize($definition, $definitionKey);
+ if ($normalize) {
+ $definition = self::normalize($definition, $definitionKey);
+ $this->_definition = $definition;
+ self::_ensure_type($definition);
+ self::_ensure_schema_instances($definition);
+ }
$this->definition = $definition;
}
- function isList(?ListSchema &$list=null): bool {
- $list = $this;
+ function isList(?ListSchema &$schema=null): bool {
+ $schema = $this;
return true;
}
- function newValue(?Value &$destv=null, &$dest=null, $destKey=null): ListValue {
- if ($destv instanceof ListValue) return $destv->reset($dest, $destKey);
- else return ($destv = new ListValue($this, $dest, $destKey));
+ protected function newWrapper(): ListWrapper {
+ return new ListWrapper($this);
+ }
+
+ function getWrapper(&$value=null, $valueKey=null, ?Wrapper &$wrapper=null): ListWrapper {
+ if (!($wrapper instanceof ListWrapper)) $wrapper = $this->newWrapper();
+ return $wrapper->reset($value, $valueKey);
}
}
diff --git a/src/schema/_list/ListValue.php b/src/schema/_list/ListWrapper.php
similarity index 59%
rename from src/schema/_list/ListValue.php
rename to src/schema/_list/ListWrapper.php
index fd1c82c..cae167b 100644
--- a/src/schema/_list/ListValue.php
+++ b/src/schema/_list/ListWrapper.php
@@ -2,10 +2,10 @@
namespace nur\sery\wip\schema\_list;
use nur\sery\wip\schema\Result;
-use nur\sery\wip\schema\Value;
+use nur\sery\wip\schema\Wrapper;
-class ListValue extends Value {
- function isList(?ListValue &$list=null): bool { $list = $this; return true; }
+abstract/*XXX*/ class ListWrapper extends Wrapper {
+ function isList(?ListWrapper &$wrapper=null): bool { $wrapper = $this; return true; }
function ensureKeys(): bool {
}
diff --git a/src/schema/_scalar/ScalarResult.php b/src/schema/_scalar/ScalarResult.php
index 82f7f24..ee28c05 100644
--- a/src/schema/_scalar/ScalarResult.php
+++ b/src/schema/_scalar/ScalarResult.php
@@ -1,36 +1,27 @@
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 +94,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,33 +112,40 @@ 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;
}
}
- function setInvalid($value, ScalarSchema $schema): int {
+ function setInvalid($value, ScalarSchema $schema, ?Throwable $t=null): int {
$this->resultAvailable = true;
$this->present = true;
$this->available = true;
$this->null = false;
$this->valid = false;
- $this->orig = $value;
- $message = $this->getMessage("invalid", $schema);
+ $this->origValue = $value;
+ $messageKey = $this->messageKey = "invalid";
+ $message = $this->getMessage($messageKey, $schema);
self::replace_key($message, $schema->name);
self::replace_orig($message, $schema->orig);
+ if ($t !== null) {
+ $tmessage = ValueException::get_message($t);
+ if ($tmessage) $message .= ": $tmessage";
+ }
$this->message = $message;
return ref_analyze::INVALID;
}
- function setValid(): int {
+ function setValid($normalizedValue=null): int {
$this->resultAvailable = true;
$this->present = true;
$this->available = true;
$this->null = false;
$this->valid = true;
+ $this->normalizedValue = $normalizedValue;
return ref_analyze::VALID;
}
diff --git a/src/schema/_scalar/ScalarSchema.php b/src/schema/_scalar/ScalarSchema.php
index d025c6b..95e07ed 100644
--- a/src/schema/_scalar/ScalarSchema.php
+++ b/src/schema/_scalar/ScalarSchema.php
@@ -1,23 +1,15 @@
_definition = $definition;
+ self::_ensure_type($definition);
+ self::_ensure_schema_instances($definition);
+ }
$this->definition = $definition;
}
- function isScalar(?ScalarSchema &$scalar=null): bool {
- $scalar = $this;
+ function isScalar(?ScalarSchema &$schema=null): bool {
+ $schema = $this;
return true;
}
- function newValue(?Value &$destv=null, &$dest=null, $destKey=null): ScalarValue {
- if ($destv instanceof ScalarValue) return $destv->reset($dest, $destKey);
- else return ($destv = new ScalarValue($this, $dest, $destKey));
+ protected function newWrapper(): ScalarWrapper {
+ return new ScalarWrapper($this);
+ }
+
+ function getWrapper(&$value=null, $valueKey=null, ?Wrapper &$wrapper=null): ScalarWrapper {
+ if (!($wrapper instanceof ScalarWrapper)) $wrapper = $this->newWrapper();
+ return $wrapper->reset($value, $valueKey);
}
#############################################################################
diff --git a/src/schema/_scalar/ScalarValue.php b/src/schema/_scalar/ScalarValue.php
deleted file mode 100644
index 381dd8c..0000000
--- a/src/schema/_scalar/ScalarValue.php
+++ /dev/null
@@ -1,198 +0,0 @@
-schema = $schema;
- $this->defaultVerifix = $defaultVerifix;
- $this->defaultThrow = $defaultThrow !== null? $defaultThrow: false;
- $this->result = new ScalarResult();
- $this->reset($dest, $destKey);
- $this->defaultThrow = $defaultThrow !== null? $defaultThrow: true;
- }
-
- function isScalar(?ScalarValue &$scalar=null): bool { $scalar = $this; return true; }
-
- /** @var ScalarSchema schéma de cette valeur */
- protected $schema;
-
- /** @var Input source et destination de la valeur */
- protected $input;
-
- /** @var string|int|null clé de la valeur dans le tableau destination */
- protected $destKey;
-
- /** @var bool */
- protected $defaultVerifix;
-
- /** @var bool */
- protected $defaultThrow;
-
- /** @var IType type de la valeur après analyse */
- protected $type;
-
- /** @var ?ScalarResult résultat de l'analyse de la valeur */
- protected $result;
-
- function reset(&$dest, $destKey=null, ?bool $verifix=null): Value {
- if ($dest instanceof Input) $input = $dest;
- else $input = new Input($dest);
- $this->input = $input;
- $this->destKey = $destKey;
- $this->type = null;
- $this->_analyze();
- if ($verifix == null) $verifix = $this->defaultVerifix;
- if ($verifix) $this->verifix();
- return $this;
- }
-
- function getKeys(): array {
- return [null];
- }
-
- function getValue($key=null): ScalarValue {
- if ($key === null) return $this;
- throw ValueException::invalid_key($key);
- }
-
- /** analyser la valeur et résoudre son type */
- function _analyze(): 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;
- $types = [];
- $type = $firstType = null;
- $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);
- if ($firstType === null) $firstType = $type;
- $types[] = $type;
- if ($type->isAvailable($input, $destKey)) {
- if (!$haveValue) {
- $value = $input->get($destKey);
- $haveValue = true;
- }
- if ($type->isValid($value, $normalized) && $normalized) {
- $haveType = true;
- $this->type = $type;
- break;
- }
- }
- }
- if (!$haveType) {
- # ensuite chercher un type pour lequel la valeur est valide
- foreach ($types as $type) {
- if ($type->isAvailable($input, $destKey) && $type->isValid($value)) {
- $haveType = true;
- $this->type = $type;
- break;
- }
- }
- }
- # 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);
- }
-
- function verifix(?bool $throw=null): bool {
- if ($throw === null) $throw = $this->defaultThrow;
- $destKey = $this->destKey;
- $verifix = false;
- $result =& $this->result;
- $modified = false;
- if ($result->resultAvailable) {
- if ($result->null) {
- # forcer la valeur null, parce que la valeur actuelle est peut-être une
- # valeur assimilée à null
- $this->input->set(null, $destKey);
- } elseif ($result->valid && !$result->normalized) {
- # normaliser la valeur
- $verifix = true;
- }
- } else {
- $verifix = true;
- }
- if ($verifix) {
- $value = $this->input->get($destKey);
- $modified = $this->type->verifix($value, $result, $this->schema);
- if ($result->valid) $this->input->set($value, $destKey);
- }
- if (!$result->valid) $result->throw($throw);
- return $modified;
- }
-
- function getResult(): ScalarResult {
- return $this->result;
- }
-
- function isPresent(): bool {
- return $this->result->present;
- }
-
- function getType(): IType {
- return $this->type;
- }
-
- function isAvailable(): bool {
- return $this->result->available;
- }
-
- function isValid(): bool {
- return $this->result->valid;
- }
-
- function isNormalized(): bool {
- return $this->result->normalized;
- }
-
- function get($default=null) {
- if ($this->result->available) return $this->input->get($this->destKey);
- else return $default;
- }
-
- function set($value, ?bool $verifix=null): ScalarValue {
- $this->input->set($value, $this->destKey);
- $this->_analyze();
- if ($verifix === null) $verifix = $this->defaultVerifix;
- if ($verifix) $this->verifix();
- return $this;
- }
-
- function unset(?bool $verifix=null): ScalarValue {
- $this->input->unset($this->destKey);
- $this->_analyze();
- if ($verifix === null) $verifix = $this->defaultVerifix;
- if ($verifix) $this->verifix();
- return $this;
- }
-
- function format($format=null): string {
- return $this->type->format($this->input->get($this->destKey), $format);
- }
-}
diff --git a/src/schema/_scalar/ScalarWrapper.php b/src/schema/_scalar/ScalarWrapper.php
new file mode 100644
index 0000000..bfd0a81
--- /dev/null
+++ b/src/schema/_scalar/ScalarWrapper.php
@@ -0,0 +1,317 @@
+verifix = $verifix;
+ $this->throw = $throw ?? false;
+ $this->schema = $schema;
+ $this->result = new ScalarResult();
+ $this->reset($value, $valueKey);
+ $this->throw = $throw ?? true;
+ }
+
+ function isScalar(?ScalarWrapper &$wrapper=null): bool { $wrapper = $this; return true; }
+
+ protected bool $verifix;
+
+ protected bool $throw;
+
+ /** schéma de cette valeur */
+ protected ScalarSchema $schema;
+
+ /** source et destination de la valeur */
+ protected Input $input;
+
+ /** @var string|int|null clé de la valeur dans le tableau destination */
+ protected $valueKey;
+
+ /** type de la valeur après analyse */
+ protected ?IType $type;
+
+ /** résultat de l'analyse de la valeur */
+ protected ScalarResult $result;
+
+ protected function newInput(&$value): Input {
+ return new Input($value);
+ }
+
+ function reset(&$value, $valueKey=null, ?bool $verifix=null): Wrapper {
+ if ($value instanceof Input) $input = $value;
+ else $input = $this->newInput($value);
+ $this->input = $input;
+ $this->valueKey = $valueKey;
+ $this->type = null;
+ $this->analyze();
+ if ($verifix ?? $this->verifix) $this->verifix();
+ return $this;
+ }
+
+ function getKeys(): array {
+ return [null];
+ }
+
+ /** @param string|int|null $key */
+ function select($key): ScalarWrapper {
+ if ($key !== null) throw ValueException::invalid_key($key);
+ return $this;
+ }
+
+ /** analyser la valeur et résoudre son type */
+ protected function analyze0(AnalyzerContext $context): int {
+ /** @var ScalarSchema $schema */
+ $schema = $context->schema;
+ $input = $context->input;
+ $valueKey = $context->valueKey;
+ /** @var ScalarResult $result */
+ $result = $context->result;
+
+ $default = $schema->default;
+ if (!$input->isPresent($valueKey)) {
+ if ($default !== null) {
+ $input->set($default, $valueKey);
+ return $result->setNormalized();
+ } else {
+ return $result->setMissing($schema);
+ }
+ }
+
+ $schemaTypes = $schema->type;
+ if ($schemaTypes instanceof IType) {
+ $type = $schemaTypes;
+ } else {
+ # type union
+ $haveType = false;
+ $types = [];
+ $type = $firstType = null;
+ $value = null;
+ # d'abord chercher un type pour lequel c'est une valeur normalisée
+ $index = 0;
+ $haveValue = false;
+ foreach ($schemaTypes as $key => $name) {
+ if ($key === $index) {
+ $index++;
+ $args = null;
+ } else {
+ $args = $name;
+ $name = $key;
+ }
+ $type = types::get($schema->nullable, $name, $args, $this->schema->getDefinition());
+ if ($firstType === null) $firstType = $type;
+ $types[] = $type;
+ if ($type->isAvailable($input, $valueKey)) {
+ if (!$haveValue) {
+ $value = $input->get($valueKey);
+ $haveValue = true;
+ }
+ if ($type->isValid($value, $normalized) && $normalized) {
+ $haveType = true;
+ break;
+ }
+ }
+ }
+ # ensuite chercher un type pour lequel la valeur est valide
+ if (!$haveType) {
+ foreach ($types as $type) {
+ if ($type->isAvailable($input, $valueKey) && $type->isValid($value)) {
+ $haveType = true;
+ break;
+ }
+ }
+ }
+ # sinon prendre le premier type
+ if (!$haveType) {
+ $type = $firstType;
+ }
+ }
+ $context->type = $this->type = $type;
+
+ if (!$type->isAvailable($input, $valueKey)) {
+ if ($default !== null) {
+ $input->set($default, $valueKey);
+ return $result->setNormalized();
+ } else {
+ return $result->setUnavailable($schema);
+ }
+ }
+
+ $value = $input->get($valueKey);
+ $context->origValue = $context->value = $value;
+ if ($type->isNull($value)) {
+ return $result->setNull($schema);
+ } elseif (is_string($value)) {
+ return ref_analyze::STRING;
+ } elseif ($type->isValid($value, $normalized)) {
+ if ($normalized) return $result->setNormalized();
+ else return $result->setValid();
+ } else {
+ return $result->setInvalid($value, $schema);
+ }
+ }
+
+ protected function analyze(): int {
+ $schema = $this->schema;
+ $input = $this->input;
+ $valueKey = $this->valueKey;
+ $result = $this->result;
+ $result->reset();
+ $context = new AnalyzerContext($schema, $this, $input, $valueKey, $result);
+
+ /** @var func $analyzerFunc */
+ $analyzerFunc = $schema->analyzerFunc;
+ if ($analyzerFunc !== null) $what = $analyzerFunc->invoke([$context]);
+ else $what = $this->analyze0($context);
+ if ($what !== ref_analyze::STRING) return $what;
+
+ $value = $context->value;
+ try {
+ /** @var func $extractorFunc */
+ $extractorFunc = $schema->extractorFunc;
+ if ($extractorFunc !== null) $extracted = $extractorFunc->invoke([$value, $context]);
+ else $extracted = $context->type->extract($value);
+ $context->value = $extracted;
+ } catch (ValueException $e) {
+ return $result->setInvalid($context->origValue, $schema, $e);
+ }
+ if ($context->type->isNull($extracted)) return $result->setNull($schema);
+
+ try {
+ /** @var func $parserFunc */
+ $parserFunc = $schema->parserFunc;
+ if ($parserFunc !== null) $parsed = $parserFunc->invoke([$extracted, $context]);
+ else $parsed = $context->type->parse($extracted);
+ $context->value = $parsed;
+ } catch (ValueException $e) {
+ return $result->setInvalid($context->origValue, $schema, $e);
+ }
+
+ $normalized = $parsed === $context->origValue;
+ if ($normalized) {
+ $input->set($parsed, $valueKey);
+ return $result->setNormalized();
+ } else {
+ $input->set($extracted, $valueKey);
+ return $result->setValid($parsed);
+ }
+ }
+
+ function verifix(?bool $throw=null): bool {
+ $result = $this->result;
+ $valueKey = $this->valueKey;
+ $verifix = false;
+ $modified = false;
+ if ($result->resultAvailable) {
+ if ($result->null) {
+ # forcer la valeur null, parce que la valeur actuelle est peut-être une
+ # valeur assimilée à null
+ $this->input->set(null, $valueKey);
+ } elseif ($result->valid && !$result->normalized) {
+ $normalizedValue = $result->normalizedValue;
+ if ($normalizedValue !== null) {
+ # la valeur normalisée est disponible
+ $this->input->set($normalizedValue);
+ $result->normalizedValue = null;
+ $modified = true;
+ } else {
+ # normaliser la valeur
+ $verifix = true;
+ }
+ }
+ } else {
+ $verifix = true;
+ }
+
+ if ($verifix) {
+ $value = $this->input->get($valueKey);
+ $schema = $this->schema;
+ /** @var func $normalizerFunc */
+ $normalizerFunc = $schema->normalizerFunc;
+ if ($normalizerFunc !== null) {
+ $context = new AnalyzerContext($schema, $this, $this->input, $valueKey, $result);
+ $orig = $value;
+ $value = $normalizerFunc->invoke([$orig, $context]);
+ $modified = $value !== $orig;
+ } else {
+ $modified = $this->type->verifix($value, $result, $this->schema);
+ }
+ if ($result->valid) $this->input->set($value, $valueKey);
+ }
+ if (!$result->valid) $result->throw($throw ?? $this->throw);
+ return $modified;
+ }
+
+ function getResult(): ScalarResult {
+ return $this->result;
+ }
+
+ function isPresent(): bool {
+ return $this->result->present;
+ }
+
+ function getType(): IType {
+ return $this->type;
+ }
+
+ function isAvailable(): bool {
+ return $this->result->available;
+ }
+
+ function isValid(): bool {
+ return $this->result->valid;
+ }
+
+ function isNormalized(): bool {
+ return $this->result->normalized;
+ }
+
+ function get($default=null) {
+ if ($this->result->available) return $this->input->get($this->valueKey);
+ else return $default;
+ }
+
+ function set($value, ?bool $verifix=null): ScalarWrapper {
+ $this->input->set($value, $this->valueKey);
+ $this->analyze();
+ if ($verifix ?? $this->verifix) $this->verifix();
+ return $this;
+ }
+
+ function unset(?bool $verifix=null): ScalarWrapper {
+ $this->input->unset($this->valueKey);
+ $this->analyze();
+ if ($verifix ?? $this->verifix) $this->verifix();
+ return $this;
+ }
+
+ function format($format=null): string {
+ $value = $this->input->get($this->valueKey);
+ /** @var func $formatterFunc */
+ $formatterFunc = $this->schema->formatterFunc;
+ if ($formatterFunc !== null) {
+ # la fonction formatter n'a pas forcément accès au format de la définition
+ # le lui fournir ici
+ $format ??= $this->schema->format;
+ return $formatterFunc->invoke([$value, $format]);
+ } else {
+ # on assume que le type a été initialisé avec le format de la définition
+ # le cas échéant
+ return $this->type->format($value, $format);
+ }
+ }
+}
diff --git a/src/schema/input/FormInput.php b/src/schema/input/FormInput.php
index 01b56c2..e708cd5 100644
--- a/src/schema/input/FormInput.php
+++ b/src/schema/input/FormInput.php
@@ -25,7 +25,7 @@ class FormInput extends Input {
}
protected function access($key): IAccess {
- return $this->keyAccess[$key] ??= new ShadowAccess($this->formAccess($key), new KeyAccess($this->dest, $key, [
+ return $this->keyAccess[$key] ??= new ShadowAccess($this->formAccess($key), new KeyAccess($this->value, $key, [
"allow_empty" => $this->allowEmpty,
]));
}
diff --git a/src/schema/input/Input.php b/src/schema/input/Input.php
index 881adb0..1008d87 100644
--- a/src/schema/input/Input.php
+++ b/src/schema/input/Input.php
@@ -13,13 +13,13 @@ use nur\sery\wip\php\access\ValueAccess;
class Input {
const ALLOW_EMPTY = true;
- function __construct(&$dest=null, ?array $params=null) {
- $this->dest =& $dest;
+ function __construct(&$value=null, ?array $params=null) {
+ $this->value =& $value;
$this->allowEmpty = $params["allow_empty"] ?? static::ALLOW_EMPTY;
}
/** @var mixed */
- protected $dest;
+ protected $value;
/**
* @var bool comment considérer une chaine vide: "" si allowEmpty, null sinon
@@ -31,12 +31,12 @@ class Input {
protected function access($key): IAccess {
if ($key === null) {
- return $this->valueAccess ??= new ValueAccess($this->dest, [
+ return $this->valueAccess ??= new ValueAccess($this->value, [
"allow_null" => true,
"allow_empty" => $this->allowEmpty,
]);
} else {
- return $this->keyAccess[$key] ??= new KeyAccess($this->dest, $key, [
+ return $this->keyAccess[$key] ??= new KeyAccess($this->value, $key, [
"allow_empty" => $this->allowEmpty,
]);
}
diff --git a/src/schema/types.php b/src/schema/types.php
index 109e7bf..7e3442a 100644
--- a/src/schema/types.php
+++ b/src/schema/types.php
@@ -6,9 +6,16 @@ use nur\sery\wip\schema\types\Registry;
use nur\sery\wip\schema\types\tarray;
use nur\sery\wip\schema\types\tbool;
use nur\sery\wip\schema\types\tcallable;
+use nur\sery\wip\schema\types\tcontent;
use nur\sery\wip\schema\types\tfloat;
use nur\sery\wip\schema\types\tint;
+use nur\sery\wip\schema\types\tkey;
+use nur\sery\wip\schema\types\tmixed;
+use nur\sery\wip\schema\types\tpkey;
+use nur\sery\wip\schema\types\traw;
+use nur\sery\wip\schema\types\trawstring;
use nur\sery\wip\schema\types\tstring;
+use nur\sery\wip\schema\types\ttext;
/**
* Class types: classe outil pour gérer le registre de types
@@ -24,14 +31,21 @@ class types {
return self::$registry;
}
- static function get(string $name): IType {
- return self::registry()->get($name);
+ static function get(bool $nullable, ?string $name, ?array $args=null, ?array $definition=null): IType {
+ return self::registry()->get($nullable, $name, $args, $definition);
}
- static function string(): tstring { return self::get("string"); }
- static function bool(): tbool { return self::get("bool"); }
- static function int(): tint { return self::get("int"); }
- static function float(): tfloat { return self::get("float"); }
- static function array(): tarray { return self::get("array"); }
- static function callable(): tcallable { return self::get("callable"); }
+ static function rawstring(bool $nullable=true): trawstring { return self::get($nullable, "rawstring"); }
+ static function string(bool $nullable=true): tstring { return self::get($nullable, "string"); }
+ static function text(bool $nullable=true): ttext { return self::get($nullable, "text"); }
+ static function bool(bool $nullable=true): tbool { return self::get($nullable, "bool"); }
+ static function int(bool $nullable=true): tint { return self::get($nullable, "int"); }
+ static function float(bool $nullable=true): tfloat { return self::get($nullable, "float"); }
+ static function array(bool $nullable=true): tarray { return self::get($nullable, "array"); }
+ static function callable(bool $nullable=true): tcallable { return self::get($nullable, "callable"); }
+ static function raw(bool $nullable=true): traw { return self::get($nullable, "raw"); }
+ static function mixed(bool $nullable=true): tmixed { return self::get($nullable, "mixed"); }
+ static function key(bool $nullable=true): tkey { return self::get($nullable, "key"); }
+ static function pkey(bool $nullable=true): tpkey { return self::get($nullable, "pkey"); }
+ static function content(bool $nullable=true): tcontent { return self::get($nullable, "content"); }
}
diff --git a/src/schema/types/IType.php b/src/schema/types/IType.php
index e470811..a245fd7 100644
--- a/src/schema/types/IType.php
+++ b/src/schema/types/IType.php
@@ -1,6 +1,7 @@
trawstring::class,
"string" => tstring::class,
+ "text" => ttext::class,
"bool" => tbool::class, "boolean" => tbool::class,
"int" => tint::class, "integer" => tint::class,
"float" => tfloat::class, "flt" => tfloat::class,
@@ -13,6 +16,8 @@ class Registry {
"array" => tarray::class,
"callable" => tcallable::class,
# types spéciaux
+ "raw" => tmixed::class,
+ "mixed" => tmixed::class,
"key" => tkey::class,
"pkey" => tpkey::class,
"content" => tcontent::class,
@@ -25,12 +30,25 @@ class Registry {
/** @var IType[] */
protected $types;
- function get(string $name): IType {
- $type = cl::get($this->types, $name);
- if ($type === null) {
- $class = self::TYPES[$name];
- $type = $this->types[$name] = new $class();
+ function get(bool $nullable, ?string $name, ?array $args=null, ?array $definition=null): IType {
+ $name ??= "raw";
+ $class = self::TYPES[$name];
+ if (cl::is_list($args)) {
+ $key = array_key_last($args);
+ $params = $args[$key];
+ unset($args[$key]);
+ } else {
+ $params = $args;
+ $args = null;
}
+ $params = cl::merge($class::get_params_from_definition($definition), $params);
+ if ($args || $params !== null) {
+ $args ??= [];
+ return func::with([$class, false, ...$args, $nullable, $params])->invoke();
+ }
+ if ($nullable) $name = "?$name";
+ $type = cl::get($this->types, $name);
+ if ($type === null) $type = $this->types[$name] = new $class($nullable);
return $type;
}
}
diff --git a/src/schema/types/_tformatable.php b/src/schema/types/_tformatable.php
new file mode 100644
index 0000000..b2bf084
--- /dev/null
+++ b/src/schema/types/_tformatable.php
@@ -0,0 +1,19 @@
+params["format"] ?? static::FORMAT;
+ if ($format !== null) return sprintf($format, $value);
+ else return strval($value);
+ }
+}
diff --git a/src/schema/types/_tsimple.php b/src/schema/types/_tsimple.php
index 9614125..072806e 100644
--- a/src/schema/types/_tsimple.php
+++ b/src/schema/types/_tsimple.php
@@ -1,14 +1,99 @@
isAvailable($destKey) && $input->get($destKey) !== false;
+ const NAME = null;
+
+ const ALIASES = [];
+
+ static function get_params_from_definition(?array $definition): ?array {
+ return null;
+ }
+
+ /**
+ * $nullable et $params doivent toujours être les derniers arguments du
+ * constructeur
+ */
+ function __construct(bool $nullable, ?array $params=null) {
+ $this->nullable = $nullable;
+ $this->params = $params;
+ }
+
+ protected bool $nullable;
+
+ protected ?array $params;
+
+ function getName(): string {
+ return static::NAME;
+ }
+
+ function getAliases(): array {
+ return static::ALIASES;
+ }
+
+ function getPhpType(bool $allowNullable=true): ?string {
+ $phpType = $this->getClass();
+ if ($phpType === "mixed") return null;
+ if ($this->nullable && $allowNullable) $phpType = "?$phpType";
+ return $phpType;
+ }
+
+ function is2States(): bool {
+ return false;
+ }
+
+ function get2States(): array {
+ throw StateException::not_implemented();
+ }
+
+ function is3States(): bool {
+ return false;
+ }
+
+ function get3States(): array {
+ throw StateException::not_implemented();
+ }
+
+ function isAvailable(Input $input, $valueKey): bool {
+ return $input->isAvailable($valueKey) && $input->get($valueKey) !== false;
}
function isNull($value): bool {
- return $value === null || (is_string($value) && trim($value) === "");
+ return $value === null || $value === "";
+ }
+
+ function extract(string $value): string {
+ return $value;
+ }
+
+ #############################################################################
+
+ function getGetterName(string $name): string {
+ return prop::get_getter_name($name);
+ }
+
+ function getSetterName(string $name): string {
+ return prop::get_setter_name($name);
+ }
+
+ function getDeleterName(string $name): string {
+ return prop::get_deletter_name($name);
+ }
+
+ function getClassConstName(string $name): string {
+ return strtoupper($name);
+ }
+
+ function getObjectPropertyName(string $name): string {
+ return str::us2camel($name);
+ }
+
+ function getArrayKeyName(string $name): string {
+ return $name;
}
}
diff --git a/src/schema/types/_tstring.php b/src/schema/types/_tstring.php
new file mode 100644
index 0000000..782f2e6
--- /dev/null
+++ b/src/schema/types/_tstring.php
@@ -0,0 +1,26 @@
+params["trim"] ?? static::TRIM) $value = trim($value);
+ if ($this->params["norm_nl"] ?? static::NORM_NL) $value = str::norm_nl($value);
+ return $value;
+ }
+}
diff --git a/src/schema/types/_tunion.php b/src/schema/types/_tunion.php
new file mode 100644
index 0000000..113e02d
--- /dev/null
+++ b/src/schema/types/_tunion.php
@@ -0,0 +1,10 @@
+params["split_pattern"] ?? static::SPLIT_PATTERN;
+ return preg_split($pattern, $value);
+ }
+
+ /**
+ * @var ScalarResult $result
+ * @var ScalarSchema $schema
+ */
+ function verifix(&$value, Result $result, Schema $schema): bool {
+ if (is_array($value)) {
+ $result->setNormalized();
+ return false;
+ } elseif (is_string($value)) {
+ try {
+ $value = $this->parse($value);
+ $result->setValid();
+ return true;
+ } catch (ValueException $e) {
+ }
+ } elseif (is_scalar($value)) {
+ $value = cl::with($value);
+ $result->setValid();
+ return true;
+ }
+ $result->setInvalid($value, $schema);
+ return false;
}
function format($value, $format=null): string {
+ if ($value === null) return "";
+ $format ??= $this->params["format"] ?? static::FORMAT;
+ return implode($format, $value);
}
}
diff --git a/src/schema/types/tbool.php b/src/schema/types/tbool.php
index 4b47586..50fa206 100644
--- a/src/schema/types/tbool.php
+++ b/src/schema/types/tbool.php
@@ -1,25 +1,28 @@
isAvailable($destKey);
+ function getClass(): string {
+ return "bool";
+ }
+
+ function is2States(): bool {
+ return !$this->nullable;
+ }
+
+ function get2States(): array {
+ return [false, true];
+ }
+
+ function is3States(): bool {
+ return $this->nullable;
+ }
+
+ function get3States(): array {
+ return [false, true, null];
+ }
+
+ function isAvailable(Input $input, $valueKey): bool {
+ return $input->isAvailable($valueKey);
}
function isValid($value, ?bool &$normalized=null): bool {
$normalized = is_bool($value);
- if (is_string($value)) {
- $value = trim($value);
- $valid = self::is_yes($value) || self::is_no($value);
- } else {
- $valid = is_scalar($value);
- }
- return $valid;
+ return is_scalar($value);
+ }
+
+ function extract(string $value): string {
+ return trim($value);
+ }
+
+ function parse(string $value) {
+ if (self::is_yes($value)) return true;
+ elseif (self::is_no($value)) return false;
+ throw new ValueException("une valeur booléenne est attendue");
}
/**
* @var ScalarResult $result
* @var ScalarSchema $schema
*/
- function verifix(&$value, Result &$result, Schema $schema): bool {
+ function verifix(&$value, Result $result, Schema $schema): bool {
if (is_bool($value)) {
$result->setNormalized();
return false;
} elseif (is_string($value)) {
- $bool = trim($value);
- if (self::is_yes($bool)) $value = true;
- elseif (self::is_no($bool)) $value = false;
- else return $result->setInvalid($value, $schema);
+ try {
+ $value = $this->parse($value);
+ $result->setValid();
+ return true;
+ } catch (ValueException $e) {
+ }
} elseif (is_scalar($value)) {
$value = boolval($value);
- } else {
- return $result->setInvalid($value, $schema);
+ $result->setValid();
+ return true;
}
- $result->setValid();
- return true;
+ $result->setInvalid($value, $schema);
+ return false;
}
const OUINON_FORMAT = ["Oui", "Non", false];
@@ -105,10 +134,10 @@ class tbool extends _tsimple {
"oz" => self::OZ_FORMAT,
];
- const DEFAULT_FORMAT = self::OUINON_FORMAT;
+ const FORMAT = self::OUINON_FORMAT;
function format($value, $format=null): string {
- if ($format === null) $format = static::DEFAULT_FORMAT;
+ $format ??= $this->params["format"] ?? static::FORMAT;
if (is_string($format)) {
$oformat = $format;
$format = cl::get(self::FORMATS, strtolower($oformat));
@@ -120,4 +149,8 @@ class tbool extends _tsimple {
}
return $value? $format[0]: $format[1];
}
+
+ function getGetterName(string $name): string {
+ return prop::get_getter_name($name, !$this->nullable);
+ }
}
diff --git a/src/schema/types/tcallable.php b/src/schema/types/tcallable.php
index a7280c2..f9e95d6 100644
--- a/src/schema/types/tcallable.php
+++ b/src/schema/types/tcallable.php
@@ -1,27 +1,66 @@
setNormalized();
+ return false;
+ } elseif (is_callable($value)) {
+ $value = func::with($value);
+ $result->setNormalized();
+ return true;
+ } elseif (is_string($value)) {
+ try {
+ $value = $this->parse($value);
+ $result->setValid();
+ return true;
+ } catch (ValueException $e) {
+ }
+ }
+ $result->setInvalid($value, $schema);
+ return false;
}
function format($value, $format=null): string {
diff --git a/src/schema/types/tcontent.php b/src/schema/types/tcontent.php
index f7ade34..1dfe455 100644
--- a/src/schema/types/tcontent.php
+++ b/src/schema/types/tcontent.php
@@ -1,26 +1,56 @@
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 c::to_string($value);
}
}
diff --git a/src/schema/types/tfloat.php b/src/schema/types/tfloat.php
index 4154f2a..db67257 100644
--- a/src/schema/types/tfloat.php
+++ b/src/schema/types/tfloat.php
@@ -1,12 +1,17 @@
setNormalized();
return false;
} elseif (is_string($value)) {
- $float = trim($value);
- if (is_numeric($float)) $value = floatval($float);
- else return $result->setInvalid($value, $schema);
+ try {
+ $value = $this->parse($value);
+ $result->setValid();
+ return true;
+ } catch (ValueException $e) {
+ }
} elseif (is_scalar($value)) {
$value = floatval($value);
- } else {
- return $result->setInvalid($value, $schema);
+ $result->setValid();
+ return true;
}
- $result->setValid();
- return true;
- }
-
- function format($value, $format=null): string {
- if ($format !== null) return sprintf($format, $value);
- else return strval($value);
+ $result->setInvalid($value, $schema);
+ return false;
}
}
diff --git a/src/schema/types/tint.php b/src/schema/types/tint.php
index fb511e7..5673ab5 100644
--- a/src/schema/types/tint.php
+++ b/src/schema/types/tint.php
@@ -1,12 +1,17 @@
setNormalized();
return false;
} elseif (is_string($value)) {
- $int = trim($value);
- if (is_numeric($int)) $value = intval($int);
- else return $result->setInvalid($value, $schema);
+ try {
+ $value = $this->parse($value);
+ $result->setValid();
+ return true;
+ } catch (ValueException $e) {
+ }
} elseif (is_scalar($value)) {
$value = intval($value);
- } else {
- return $result->setInvalid($value, $schema);
+ $result->setValid();
+ return true;
}
- $result->setValid();
- return true;
- }
-
- function format($value, $format=null): string {
- if ($format !== null) return sprintf($format, $value);
- else return strval($value);
+ $result->setInvalid($value, $schema);
+ return false;
}
}
diff --git a/src/schema/types/tkey.php b/src/schema/types/tkey.php
index 63c3f04..0e00cb3 100644
--- a/src/schema/types/tkey.php
+++ b/src/schema/types/tkey.php
@@ -1,26 +1,56 @@
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);
}
}
diff --git a/src/schema/types/tmixed.php b/src/schema/types/tmixed.php
new file mode 100644
index 0000000..5f387c6
--- /dev/null
+++ b/src/schema/types/tmixed.php
@@ -0,0 +1,46 @@
+isAvailable($valueKey);
+ }
+
+ public function isNull($value): bool {
+ return $value === null;
+ }
+
+ function isValid($value, ?bool &$normalized=null): bool {
+ $normalized = true;
+ return true;
+ }
+
+ function parse(string $value) {
+ return $value;
+ }
+
+ /**
+ * @var ScalarResult $result
+ * @var ScalarSchema $schema
+ */
+ function verifix(&$value, Result $result, Schema $schema): bool {
+ $result->setNormalized();
+ return false;
+ }
+
+ function format($value, $format=null): string {
+ return var_export($value, true);
+ }
+}
diff --git a/src/schema/types/tpkey.php b/src/schema/types/tpkey.php
index 32e545c..14f2e01 100644
--- a/src/schema/types/tpkey.php
+++ b/src/schema/types/tpkey.php
@@ -1,17 +1,22 @@
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 {
+ if (is_array($value)) return implode(".", $value);
+ else return strval($value);
}
}
diff --git a/src/schema/types/traw.php b/src/schema/types/traw.php
new file mode 100644
index 0000000..b187b3f
--- /dev/null
+++ b/src/schema/types/traw.php
@@ -0,0 +1,16 @@
+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);
+ }
+}
diff --git a/src/schema/types/tstring.php b/src/schema/types/tstring.php
index 877707c..0e45d99 100644
--- a/src/schema/types/tstring.php
+++ b/src/schema/types/tstring.php
@@ -1,48 +1,8 @@
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);
- }
+ const TRIM = true;
}
diff --git a/src/schema/types/ttext.php b/src/schema/types/ttext.php
new file mode 100644
index 0000000..755d1e6
--- /dev/null
+++ b/src/schema/types/ttext.php
@@ -0,0 +1,9 @@
+ 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/schema/types/boolTest.php b/tests/schema/types/boolTest.php
deleted file mode 100644
index 82dd766..0000000
--- a/tests/schema/types/boolTest.php
+++ /dev/null
@@ -1,111 +0,0 @@
-set(true);
- self::assertSame(true, $destv->get());
- self::assertSame(true, $dest);
- self::assertSame("Oui", $destv->format());
- self::assertSame("Oui", $destv->format("OuiNonNull"));
- self::assertSame("O", $destv->format("ON"));
- self::assertSame("O", $destv->format("ONN"));
-
- $destv->set(false);
- self::assertSame(false, $destv->get());
- self::assertSame(false, $dest);
- self::assertSame("Non", $destv->format());
- self::assertSame("Non", $destv->format("OuiNonNull"));
- self::assertSame("N", $destv->format("ON"));
- self::assertSame("N", $destv->format("ONN"));
-
- $destv->set("yes");
- self::assertSame(true, $destv->get());
-
- $destv->set(" yes ");
- self::assertSame(true, $destv->get());
-
- $destv->set("12");
- self::assertSame(true, $destv->get());
-
- $destv->set(12);
- self::assertSame(true, $destv->get());
-
- $destv->set("no");
- self::assertSame(false, $destv->get());
-
- $destv->set(" no ");
- self::assertSame(false, $destv->get());
-
- $destv->set("0");
- self::assertSame(false, $destv->get());
-
- $destv->set(0);
- self::assertSame(false, $destv->get());
-
- $destv->set(12.34);
- self::assertSame(true, $destv->get());
-
- self::assertException(Exception::class, $destvSetter("a"));
- self::assertException(Exception::class, $destvSetter([]));
- self::assertException(Exception::class, $destvSetter(["a"]));
-
- }
-
- function testBool() {
- /** @var ScalarValue $destv */
- Schema::nv($destv, $dest, null, $schema, "bool");
- $destvSetter = function($value) use($destv) {
- return function() use($destv, $value) {
- $destv->set($value);
- };
- };
-
- self::assertException(Exception::class, $destvSetter(null));
- self::assertException(Exception::class, $destvSetter(""));
- self::assertException(Exception::class, $destvSetter(" "));
-
- $this->commonTests($destv, $dest, $destvSetter);
- }
-
- function testNbool() {
- /** @var ScalarValue $destv */
- Schema::nv($destv, $dest, null, $schema, "?bool");
- $destvSetter = function($value) use($destv) {
- return function() use($destv, $value) {
- $destv->set($value);
- };
- };
-
- $destv->set(null);
- self::assertNull($destv->get());
- self::assertNull($dest);
- self::assertSame("Non", $destv->format());
- self::assertSame("", $destv->format("OuiNonNull"));
- self::assertSame("N", $destv->format("ON"));
- self::assertSame("", $destv->format("ONN"));
-
- $destv->set("");
- self::assertNull($destv->get());
- self::assertNull($dest);
- self::assertSame("Non", $destv->format());
- self::assertSame("", $destv->format("OuiNonNull"));
- self::assertSame("N", $destv->format("ON"));
- self::assertSame("", $destv->format("ONN"));
-
- $destv->set(" ");
- self::assertNull($destv->get());
- self::assertNull($dest);
- self::assertSame("Non", $destv->format());
- self::assertSame("", $destv->format("OuiNonNull"));
- self::assertSame("N", $destv->format("ON"));
- self::assertSame("", $destv->format("ONN"));
-
- $this->commonTests($destv, $dest, $destvSetter);
- }
-}
diff --git a/tests/schema/types/floatTest.php b/tests/schema/types/floatTest.php
deleted file mode 100644
index 225fb08..0000000
--- a/tests/schema/types/floatTest.php
+++ /dev/null
@@ -1,139 +0,0 @@
-set(12);
- self::assertSame(12.0, $destv->get());
- self::assertSame(12.0, $dest);
- self::assertSame("12", $destv->format());
- self::assertSame("0012", $destv->format("%04u"));
-
- $destv->set("12");
- self::assertSame(12.0, $destv->get());
-
- $destv->set(" 12 ");
- self::assertSame(12.0, $destv->get());
-
- $destv->set(12.34);
- self::assertSame(12.34, $destv->get());
-
- $destv->set(true);
- self::assertSame(1.0, $destv->get());
-
- self::assertException(Exception::class, $destvSetter("a"));
- self::assertException(Exception::class, $destvSetter([]));
- self::assertException(Exception::class, $destvSetter(["a"]));
- }
-
- function testFloat() {
- /** @var ScalarValue $destv */
- Schema::nv($destv, $dest, null, $schema, "float");
- $destvSetter = function($value) use($destv) {
- return function() use($destv, $value) {
- $destv->set($value);
- };
- };
-
- self::assertException(Exception::class, $destvSetter(null));
- self::assertException(Exception::class, $destvSetter(""));
- self::assertException(Exception::class, $destvSetter(" "));
-
- // valeur non requise donc retourne null
- $destv->set(false);
- self::assertNull($destv->get());
-
- $this->commonTests($destv, $dest, $destvSetter);
- }
-
- function testRequiredFloat() {
- /** @var ScalarValue $destv */
- Schema::nv($destv, $dest, null, $schema, [
- "float", null,
- "required" => true,
- ]);
- $destvSetter = function($value) use($destv) {
- return function() use($destv, $value) {
- $destv->set($value);
- };
- };
-
- self::assertException(Exception::class, $destvSetter(null));
- self::assertException(Exception::class, $destvSetter(""));
- self::assertException(Exception::class, $destvSetter(" "));
-
- // valeur requise donc lance une exception
- self::assertException(Exception::class, $destvSetter(false));
-
- $this->commonTests($destv, $dest, $destvSetter);
- }
-
- function testNfloat() {
- /** @var ScalarValue $destv */
- Schema::nv($destv, $dest, null, $schema, "?float");
- $destvSetter = function($value) use($destv) {
- return function() use($destv, $value) {
- $destv->set($value);
- };
- };
-
- $destv->set(null);
- self::assertNull($destv->get());
- self::assertNull($dest);
- self::assertSame("", $destv->format());
-
- $destv->set("");
- self::assertNull($destv->get());
- self::assertNull($dest);
- self::assertSame("", $destv->format());
-
- $destv->set(" ");
- self::assertNull($destv->get());
- self::assertNull($dest);
- self::assertSame("", $destv->format());
-
- // valeur non requise donc retourne null
- $destv->set(false);
- self::assertNull($destv->get());
-
- $this->commonTests($destv, $dest, $destvSetter);
- }
-
- function testRequiredNfloat() {
- /** @var ScalarValue $destv */
- Schema::nv($destv, $dest, null, $schema, [
- "?float", null,
- "required" => true,
- ]);
- $destvSetter = function($value) use($destv) {
- return function() use($destv, $value) {
- $destv->set($value);
- };
- };
-
- $destv->set(null);
- self::assertNull($destv->get());
- self::assertNull($dest);
- self::assertSame("", $destv->format());
-
- $destv->set("");
- self::assertNull($destv->get());
- self::assertNull($dest);
- self::assertSame("", $destv->format());
-
- $destv->set(" ");
- self::assertNull($destv->get());
- self::assertNull($dest);
- self::assertSame("", $destv->format());
-
- // valeur requise donc lance une exception
- self::assertException(Exception::class, $destvSetter(false));
-
- $this->commonTests($destv, $dest, $destvSetter);
- }
-}
diff --git a/tests/schema/types/intTest.php b/tests/schema/types/intTest.php
deleted file mode 100644
index 4ca3b5a..0000000
--- a/tests/schema/types/intTest.php
+++ /dev/null
@@ -1,139 +0,0 @@
-set(12);
- self::assertSame(12, $destv->get());
- self::assertSame(12, $dest);
- self::assertSame("12", $destv->format());
- self::assertSame("0012", $destv->format("%04u"));
-
- $destv->set("12");
- self::assertSame(12, $destv->get());
-
- $destv->set(" 12 ");
- self::assertSame(12, $destv->get());
-
- $destv->set(12.34);
- self::assertSame(12, $destv->get());
-
- $destv->set(true);
- self::assertSame(1, $destv->get());
-
- self::assertException(Exception::class, $destvSetter("a"));
- self::assertException(Exception::class, $destvSetter([]));
- self::assertException(Exception::class, $destvSetter(["a"]));
- }
-
- function testInt() {
- /** @var ScalarValue $destv */
- Schema::nv($destv, $dest, null, $schema, "int");
- $destvSetter = function($value) use($destv) {
- return function() use($destv, $value) {
- $destv->set($value);
- };
- };
-
- self::assertException(Exception::class, $destvSetter(null));
- self::assertException(Exception::class, $destvSetter(""));
- self::assertException(Exception::class, $destvSetter(" "));
-
- // valeur non requise donc retourne null
- $destv->set(false);
- self::assertNull($destv->get());
-
- $this->commonTests($destv, $dest, $destvSetter);
- }
-
- function testRequiredInt() {
- /** @var ScalarValue $destv */
- Schema::nv($destv, $dest, null, $schema, [
- "int", null,
- "required" => true,
- ]);
- $destvSetter = function($value) use($destv) {
- return function() use($destv, $value) {
- $destv->set($value);
- };
- };
-
- self::assertException(Exception::class, $destvSetter(null));
- self::assertException(Exception::class, $destvSetter(""));
- self::assertException(Exception::class, $destvSetter(" "));
-
- // valeur requise donc lance une exception
- self::assertException(Exception::class, $destvSetter(false));
-
- $this->commonTests($destv, $dest, $destvSetter);
- }
-
- function testNint() {
- /** @var ScalarValue $destv */
- Schema::nv($destv, $dest, null, $schema, "?int");
- $destvSetter = function($value) use($destv) {
- return function() use($destv, $value) {
- $destv->set($value);
- };
- };
-
- $destv->set(null);
- self::assertNull($destv->get());
- self::assertNull($dest);
- self::assertSame("", $destv->format());
-
- $destv->set("");
- self::assertNull($destv->get());
- self::assertNull($dest);
- self::assertSame("", $destv->format());
-
- $destv->set(" ");
- self::assertNull($destv->get());
- self::assertNull($dest);
- self::assertSame("", $destv->format());
-
- // valeur non requise donc retourne null
- $destv->set(false);
- self::assertNull($destv->get());
-
- $this->commonTests($destv, $dest, $destvSetter);
- }
-
- function testRequiredNint() {
- /** @var ScalarValue $destv */
- Schema::nv($destv, $dest, null, $schema, [
- "?int", null,
- "required" => true,
- ]);
- $destvSetter = function($value) use($destv) {
- return function() use($destv, $value) {
- $destv->set($value);
- };
- };
-
- $destv->set(null);
- self::assertNull($destv->get());
- self::assertNull($dest);
- self::assertSame("", $destv->format());
-
- $destv->set("");
- self::assertNull($destv->get());
- self::assertNull($dest);
- self::assertSame("", $destv->format());
-
- $destv->set(" ");
- self::assertNull($destv->get());
- self::assertNull($dest);
- self::assertSame("", $destv->format());
-
- // valeur requise donc lance une exception
- self::assertException(Exception::class, $destvSetter(false));
-
- $this->commonTests($destv, $dest, $destvSetter);
- }
-}
diff --git a/tests/schema/types/strTest.php b/tests/schema/types/strTest.php
deleted file mode 100644
index 779c52e..0000000
--- a/tests/schema/types/strTest.php
+++ /dev/null
@@ -1,123 +0,0 @@
-set("");
- self::assertSame("", $destv->get());
- self::assertSame("", $dest);
-
- $destv->set(" ");
- self::assertSame(" ", $destv->get());
- self::assertSame(" ", $dest);
-
- $destv->set("a");
- self::assertSame("a", $destv->get());
- self::assertSame("a", $dest);
-
- $destv->set("12");
- self::assertSame("12", $destv->get());
-
- $destv->set(" 12 ");
- self::assertSame(" 12 ", $destv->get());
-
- $destv->set(12);
- self::assertSame("12", $destv->get());
-
- $destv->set(12.34);
- self::assertSame("12.34", $destv->get());
-
- $destv->set(true);
- self::assertSame("1", $destv->get());
-
- self::assertException(Exception::class, $destvSetter([]));
- self::assertException(Exception::class, $destvSetter(["a"]));
- }
-
- function testStr() {
- /** @var ScalarValue $destv */
- Schema::nv($destv, $dest, null, $schema, "string");
- $destvSetter = function($value) use($destv) {
- return function() use($destv, $value) {
- $destv->set($value);
- };
- };
-
- self::assertException(Exception::class, $destvSetter(null));
-
- // valeur non requise donc retourne null
- $destv->set(false);
- self::assertNull($destv->get());
-
- $this->commonTests($destv, $dest, $destvSetter);
- }
-
- function testRequiredStr() {
- /** @var ScalarValue $destv */
- Schema::nv($destv, $dest, null, $schema, [
- "string", null,
- "required" => true,
- ]);
- $destvSetter = function($value) use($destv) {
- return function() use($destv, $value) {
- $destv->set($value);
- };
- };
-
- self::assertException(Exception::class, $destvSetter(null));
-
- // valeur requise donc lance une exception
- self::assertException(Exception::class, $destvSetter(false));
-
- $this->commonTests($destv, $dest, $destvSetter);
- }
-
- function testNstr() {
- /** @var ScalarValue $destv */
- Schema::nv($destv, $dest, null, $schema, "?string");
- $destvSetter = function($value) use($destv) {
- return function() use($destv, $value) {
- $destv->set($value);
- };
- };
-
- $destv->set(null);
- self::assertNull($destv->get());
- self::assertNull($dest);
- self::assertSame("", $destv->format());
-
- // valeur non requise donc retourne null
- $destv->set(false);
- self::assertNull($destv->get());
-
- $this->commonTests($destv, $dest, $destvSetter);
- }
-
- function testRequiredNstr() {
- /** @var ScalarValue $destv */
- Schema::nv($destv, $dest, null, $schema, [
- "?string", null,
- "required" => true,
- ]);
- $destvSetter = function($value) use($destv) {
- return function() use($destv, $value) {
- $destv->set($value);
- };
- };
-
- $destv->set(null);
- self::assertNull($destv->get());
- self::assertNull($dest);
- self::assertSame("", $destv->format());
-
- // valeur requise donc lance une exception
- self::assertException(Exception::class, $destvSetter(false));
-
- $this->commonTests($destv, $dest, $destvSetter);
- }
-}
diff --git a/tests/schema/types/unionTest.php b/tests/schema/types/unionTest.php
deleted file mode 100644
index 048d088..0000000
--- a/tests/schema/types/unionTest.php
+++ /dev/null
@@ -1,29 +0,0 @@
-set("12");
- self::assertSame("12", $si);
- $siv->set(12);
- self::assertSame(12, $si);
-
- # int puis string
- Schema::nv($isv, $is, null, $iss, "int|string");
-
- $isv->set("12");
- self::assertSame("12", $is);
- $isv->set(12);
- self::assertSame(12, $is);
- }
-}
diff --git a/tests/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 @@
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;
diff --git a/tests/php/content/cTest.php b/tests/wip/php/content/cTest.php
similarity index 93%
rename from tests/php/content/cTest.php
rename to tests/wip/php/content/cTest.php
index 7ec292e..e740799 100644
--- a/tests/php/content/cTest.php
+++ b/tests/wip/php/content/cTest.php
@@ -1,7 +1,8 @@
["assoc"],
+ "schema" => null,
+ "type" => [null],
+ "default" => null,
+ "title" => null,
+ "required" => false,
+ "nullable" => true,
+ "desc" => null,
+ "analyzer_func" => null,
+ "extractor_func" => null,
+ "parser_func" => null,
+ "normalizer_func" => null,
+ "messages" => null,
+ "formatter_func" => null,
+ "format" => null,
+ "name" => null,
+ "pkey" => null,
+ "header" => null,
+ "composite" => null,
+ ];
+
+ static function schema(array $definition, array $keyDefinitions): array {
+ $definition = array_merge(self::NULL_SCHEMA, $definition, ["schema" => []]);
+ foreach ($keyDefinitions as $key => $keydef) {
+ $definition["schema"][$key] = array_merge(ScalarSchemaTest::NULL_SCHEMA, $keydef);
+ }; unset($subdef);
+ return $definition;
+ }
+
+ function testNormalize() {
+ self::assertSame(self::schema([
+ "type" => ["array"], "nullable" => true,
+ ], [
+ "a" => [
+ "type" => ["string"], "nullable" => false,
+ "name" => "a", "pkey" => "a", "header" => "a",
+ ],
+ ]), AssocSchema::normalize(["a" => "string"]));
+
+ self::assertSame(self::schema([
+ "type" => ["array"], "nullable" => true,
+ ], [
+ "a" => [
+ "type" => ["string"], "nullable" => false,
+ "name" => "a", "pkey" => "a", "header" => "a",
+ ],
+ "b" => [
+ "type" => ["int"], "nullable" => false,
+ "name" => "b", "pkey" => "b", "header" => "b",
+ ],
+ "c" => [
+ "type" => ["bool"], "nullable" => false,
+ "name" => "c", "pkey" => "c", "header" => "c",
+ ],
+ ]), AssocSchema::normalize([
+ "a" => "string",
+ "b" => "int",
+ "c" => "bool",
+ ]));
+ }
+
+ function testConstructor() {
+ $schema = new AssocSchema([
+ "a" => "string",
+ "b" => "int",
+ "c" => "bool",
+ ]);
+ self::assertSame(self::schema([
+ "type" => ["array"], "nullable" => true,
+ ], [
+ "a" => [
+ "type" => ["string"], "nullable" => false,
+ "name" => "a", "pkey" => "a", "header" => "a",
+ ],
+ "b" => [
+ "type" => ["int"], "nullable" => false,
+ "name" => "b", "pkey" => "b", "header" => "b",
+ ],
+ "c" => [
+ "type" => ["bool"], "nullable" => false,
+ "name" => "c", "pkey" => "c", "header" => "c",
+ ],
+ ]), $schema->getDefinition());
+ yaml::dump($schema->getDefinition());
+ }
+}
diff --git a/tests/schema/_scalar/ScalarSchemaTest.php b/tests/wip/schema/_scalar/ScalarSchemaTest.php
similarity index 96%
rename from tests/schema/_scalar/ScalarSchemaTest.php
rename to tests/wip/schema/_scalar/ScalarSchemaTest.php
index 2c74c68..84fdd35 100644
--- a/tests/schema/_scalar/ScalarSchemaTest.php
+++ b/tests/wip/schema/_scalar/ScalarSchemaTest.php
@@ -1,8 +1,7 @@
null,
"format" => null,
"" => ["scalar"],
+ "schema" => null,
"name" => null,
"pkey" => null,
"header" => null,
diff --git a/tests/wip/schema/_scalar/ScalarWrapperTest.php b/tests/wip/schema/_scalar/ScalarWrapperTest.php
new file mode 100644
index 0000000..6e9326b
--- /dev/null
+++ b/tests/wip/schema/_scalar/ScalarWrapperTest.php
@@ -0,0 +1,294 @@
+get(), "value");
+ self::assertSame($present, $wrapper->isPresent(), "present");
+ self::assertSame($available, $wrapper->isAvailable(), "available");
+ self::assertSame($valid, $wrapper->isValid(), "valid");
+ self::assertSame($normalized, $wrapper->isNormalized(), "normalized");
+ }
+
+ function checkVerifix(ScalarSchema $schema, $orig, bool $verifix, $value, bool $present, bool $available, bool $valid, bool $normalized, ?array $inputParams=null): void {
+ $wrapper = $schema->getWrapper();
+ if ($inputParams !== null) $input = new Input($orig, $inputParams);
+ else $input = $orig;
+ $wrapper->reset($input, null, $verifix);
+ $this->checkValue($wrapper, $value, $present, $available, $valid, $normalized);
+ }
+
+ function checkException(ScalarSchema $schema, $orig, bool $verifix, string $exceptionClass, ?array $inputParams=null) {
+ $wrapper = $schema->getWrapper();
+ if ($inputParams !== null) $orig = new Input($orig, $inputParams);
+ self::assertException($exceptionClass, function() use ($wrapper, &$orig, $verifix) {
+ $wrapper->reset($orig, null, $verifix);
+ });
+ }
+
+ function testRaw() {
+ $schema = new ScalarSchema();
+
+ $this->checkVerifix($schema, false, false, false, true, true, true, true);
+ $this->checkVerifix($schema, false, true, false, true, true, true, true);
+
+ $this->checkVerifix($schema, null, false, null, true, true, true, true);
+ $this->checkVerifix($schema, null, true, null, true, true, true, true);
+
+ $obj = new stdClass();
+ $this->checkVerifix($schema, $obj, false, $obj, true, true, true, true);
+ $this->checkVerifix($schema, $obj, true, $obj, true, true, true, true);
+
+ $schema = new ScalarSchema("raw");
+
+ $this->checkVerifix($schema, false, false, false, true, true, true, true);
+ $this->checkVerifix($schema, false, true, false, true, true, true, true);
+
+ $this->checkVerifix($schema, null, false, null, true, true, true, true);
+ $this->checkVerifix($schema, null, true, null, true, true, true, true);
+
+ $obj = new stdClass();
+ $this->checkVerifix($schema, $obj, false, $obj, true, true, true, true);
+ $this->checkVerifix($schema, $obj, true, $obj, true, true, true, true);
+ }
+
+ function testMixed() {
+ $schema = new ScalarSchema("mixed");
+
+ $this->checkVerifix($schema, false, false, false, true, true, true, true);
+ $this->checkVerifix($schema, false, true, false, true, true, true, true);
+
+ $this->checkVerifix($schema, null, false, null, true, true, false, false);
+ $this->checkException($schema, null, true, ValueException::class);
+
+ $obj = new stdClass();
+ $this->checkVerifix($schema, $obj, false, $obj, true, true, true, true);
+ $this->checkVerifix($schema, $obj, true, $obj, true, true, true, true);
+
+ $schema = new ScalarSchema("?mixed");
+
+ $this->checkVerifix($schema, false, false, false, true, true, true, true);
+ $this->checkVerifix($schema, false, true, false, true, true, true, true);
+
+ $this->checkVerifix($schema, null, false, null, true, true, true, true);
+ $this->checkVerifix($schema, null, true, null, true, true, true, true);
+
+ $obj = new stdClass();
+ $this->checkVerifix($schema, $obj, false, $obj, true, true, true, true);
+ $this->checkVerifix($schema, $obj, true, $obj, true, true, true, true);
+ }
+
+ function testRawstring() {
+ $schema = new ScalarSchema("rawstring");
+
+ $this->checkVerifix($schema, false, false, null, true, false, true, true);
+ $this->checkVerifix($schema, false, true, null, true, false, true, true);
+
+ $this->checkVerifix($schema, null, false, null, true, true, false, false);
+ $this->checkException($schema, null, true, ValueException::class);
+
+ $this->checkVerifix($schema, "", false, "", true, true, true, true);
+ $this->checkVerifix($schema, "", true, "", true, true, true, true);
+
+ $this->checkVerifix($schema, " ", false, " ", true, true, true, true);
+ $this->checkVerifix($schema, " ", true, " ", true, true, true, true);
+
+ $this->checkVerifix($schema, "text", false, "text", true, true, true, true);
+ $this->checkVerifix($schema, "text", true, "text", true, true, true, true);
+
+ $this->checkVerifix($schema, " text ", false, " text ", true, true, true, true);
+ $this->checkVerifix($schema, " text ", true, " text ", true, true, true, true);
+
+ $this->checkVerifix($schema, true, false, true, true, true, true, false);
+ $this->checkVerifix($schema, true, true, "1", true, true, true, false);
+
+ $this->checkVerifix($schema, 42, false, 42, true, true, true, false);
+ $this->checkVerifix($schema, 42, true, "42", true, true, true, false);
+
+ $this->checkVerifix($schema, [], false, [], true, true, false, false);
+ $this->checkException($schema, [], true, ValueException::class);
+
+ ## Tester valeur par défaut
+ $schema = new ScalarSchema(["rawstring", null]);
+
+ $this->checkVerifix($schema, false, false, null, true, false, true, true);
+ $this->checkVerifix($schema, false, true, null, true, false, true, true);
+
+ $this->checkVerifix($schema, null, false, null, true, true, false, false);
+ $this->checkException($schema, null, true, ValueException::class);
+
+ $schema = new ScalarSchema(["rawstring", "default"]);
+
+ $this->checkVerifix($schema, false, false, "default", true, true, true, true);
+ $this->checkVerifix($schema, false, true, "default", true, true, true, true);
+
+ $this->checkVerifix($schema, null, false, null, true, true, false, false);
+ $this->checkException($schema, null, true, ValueException::class);
+
+ ## Tester nullable
+ $schema = new ScalarSchema("?rawstring");
+
+ $this->checkVerifix($schema, null, false, null, true, true, true, true);
+ $this->checkVerifix($schema, null, true, null, true, true, true, true);
+
+ ## Tester required
+ $schema = new ScalarSchema(["rawstring", "required" => true]);
+
+ $this->checkVerifix($schema, false, false, null, true, false, false, false);
+ $this->checkException($schema, false, true, ValueException::class);
+
+ ## Tester allow_empty === false
+ $inputParams = ["allow_empty" => false];
+ $schema = new ScalarSchema("rawstring");
+
+ $this->checkVerifix($schema, null, false, null, true, true, false, false, $inputParams);
+ $this->checkException($schema, null, true, ValueException::class, $inputParams);
+
+ $this->checkVerifix($schema, "", false, null, true, false, true, true, $inputParams);
+ $this->checkVerifix($schema, "", true, null, true, false, true, true, $inputParams);
+
+ $schema = new ScalarSchema("?rawstring");
+
+ $this->checkVerifix($schema, null, false, null, true, true, true, true, $inputParams);
+ $this->checkVerifix($schema, null, true, null, true, true, true, true, $inputParams);
+
+ $this->checkVerifix($schema, "", false, null, true, false, true, true, $inputParams);
+ $this->checkVerifix($schema, "", true, null, true, false, true, true, $inputParams);
+ }
+
+ function testString() {
+ $schema = new ScalarSchema("string");
+
+ $this->checkVerifix($schema, false, false, null, true, false, true, true);
+ $this->checkVerifix($schema, false, true, null, true, false, true, true);
+
+ $this->checkVerifix($schema, null, false, null, true, true, false, false);
+ $this->checkException($schema, null, true, ValueException::class);
+
+ $this->checkVerifix($schema, "", false, "", true, true, true, true);
+ $this->checkVerifix($schema, "", true, "", true, true, true, true);
+
+ $this->checkVerifix($schema, " ", false, "", true, true, true, false);
+ $this->checkVerifix($schema, " ", true, "", true, true, true, false);
+
+ $this->checkVerifix($schema, "text", false, "text", true, true, true, true);
+ $this->checkVerifix($schema, "text", true, "text", true, true, true, true);
+
+ $this->checkVerifix($schema, " text ", false, "text", true, true, true, false);
+ $this->checkVerifix($schema, " text ", true, "text", true, true, true, false);
+
+ $this->checkVerifix($schema, true, false, true, true, true, true, false);
+ $this->checkVerifix($schema, true, true, "1", true, true, true, false);
+
+ $this->checkVerifix($schema, 42, false, 42, true, true, true, false);
+ $this->checkVerifix($schema, 42, true, "42", true, true, true, false);
+
+ $this->checkVerifix($schema, [], false, [], true, true, false, false);
+ $this->checkException($schema, [], true, ValueException::class);
+
+ ## Tester nullable
+ $schema = new ScalarSchema("?string");
+
+ $this->checkVerifix($schema, null, false, null, true, true, true, true);
+ $this->checkVerifix($schema, null, true, null, true, true, true, true);
+
+ ## Tester required
+ $schema = new ScalarSchema(["string", "required" => true]);
+
+ $this->checkVerifix($schema, false, false, null, true, false, false, false);
+ $this->checkException($schema, false, true, ValueException::class);
+
+ ## Tester allow_empty === false
+ $inputParams = ["allow_empty" => false];
+ $schema = new ScalarSchema("string");
+
+ $this->checkVerifix($schema, null, false, null, true, true, false, false, $inputParams);
+ $this->checkException($schema, null, true, ValueException::class, $inputParams);
+
+ $this->checkVerifix($schema, "", false, null, true, false, true, true, $inputParams);
+ $this->checkVerifix($schema, "", true, null, true, false, true, true, $inputParams);
+
+ $schema = new ScalarSchema("?string");
+
+ $this->checkVerifix($schema, null, false, null, true, true, true, true, $inputParams);
+ $this->checkVerifix($schema, null, true, null, true, true, true, true, $inputParams);
+
+ $this->checkVerifix($schema, "", false, null, true, false, true, true, $inputParams);
+ $this->checkVerifix($schema, "", true, null, true, false, true, true, $inputParams);
+ }
+
+ function testInt() {
+ $schema = new ScalarSchema("int");
+
+ $this->checkVerifix($schema, false, false, null, true, false, true, true);
+ $this->checkVerifix($schema, false, true, null, true, false, true, true);
+
+ $this->checkVerifix($schema, null, false, null, true, true, false, false);
+ $this->checkException($schema, null, true, ValueException::class);
+
+ $this->checkVerifix($schema, 42, false, 42, true, true, true, true);
+ $this->checkVerifix($schema, 42, true, 42, true, true, true, true);
+
+ $this->checkVerifix($schema, "42", false, "42", true, true, true, false);
+ $this->checkVerifix($schema, "42", true, 42, true, true, true, false);
+
+ $this->checkVerifix($schema, "42.5", false, "42.5", true, true, true, false);
+ $this->checkVerifix($schema, "42.5", true, 42, true, true, true, false);
+
+ $this->checkVerifix($schema, "42,5", false, "42,5", true, true, true, false);
+ $this->checkVerifix($schema, "42,5", true, 42, true, true, true, false);
+
+ $this->checkVerifix($schema, " 42 ", false, "42", true, true, true, false);
+ $this->checkVerifix($schema, " 42 ", true, 42, true, true, true, false);
+
+ $this->checkVerifix($schema, "", false, "", true, true, false, false);
+ $this->checkException($schema, "", true, ValueException::class);
+
+ $this->checkVerifix($schema, " ", false, " ", true, true, false, false);
+ $this->checkException($schema, " ", true, ValueException::class);
+
+ $this->checkVerifix($schema, "text", false, "text", true, true, false, false);
+ $this->checkException($schema, "text", true, ValueException::class);
+
+ $this->checkVerifix($schema, true, false, true, true, true, true, false);
+ $this->checkVerifix($schema, true, true, 1, true, true, true, false);
+
+ $this->checkVerifix($schema, [], false, [], true, true, false, false);
+ $this->checkException($schema, [], true, ValueException::class);
+
+ ## Tester nullable
+ $schema = new ScalarSchema("?int");
+
+ $this->checkVerifix($schema, null, false, null, true, true, true, true);
+ $this->checkVerifix($schema, null, true, null, true, true, true, true);
+
+ ## Tester required
+ $schema = new ScalarSchema(["int", "required" => true]);
+
+ $this->checkVerifix($schema, false, false, null, true, false, false, false);
+ $this->checkException($schema, false, true, ValueException::class);
+
+ ## Tester allow_empty === false
+ $inputParams = ["allow_empty" => false];
+ $schema = new ScalarSchema("int");
+
+ $this->checkVerifix($schema, null, false, null, true, true, false, false, $inputParams);
+ $this->checkException($schema, null, true, ValueException::class, $inputParams);
+
+ $this->checkVerifix($schema, "", false, null, true, false, true, true, $inputParams);
+ $this->checkVerifix($schema, "", true, null, true, false, true, true, $inputParams);
+
+ $schema = new ScalarSchema("?int");
+
+ $this->checkVerifix($schema, null, false, null, true, true, true, true, $inputParams);
+ $this->checkVerifix($schema, null, true, null, true, true, true, true, $inputParams);
+
+ $this->checkVerifix($schema, "", false, null, true, false, true, true, $inputParams);
+ $this->checkVerifix($schema, "", true, null, true, false, true, true, $inputParams);
+ }
+}
diff --git a/tests/wip/schema/types/boolTest.php b/tests/wip/schema/types/boolTest.php
new file mode 100644
index 0000000..f4db6ce
--- /dev/null
+++ b/tests/wip/schema/types/boolTest.php
@@ -0,0 +1,111 @@
+set(true);
+ self::assertSame(true, $wrapper->get());
+ self::assertSame(true, $value);
+ self::assertSame("Oui", $wrapper->format());
+ self::assertSame("Oui", $wrapper->format("OuiNonNull"));
+ self::assertSame("O", $wrapper->format("ON"));
+ self::assertSame("O", $wrapper->format("ONN"));
+
+ $wrapper->set(false);
+ self::assertSame(false, $wrapper->get());
+ self::assertSame(false, $value);
+ self::assertSame("Non", $wrapper->format());
+ self::assertSame("Non", $wrapper->format("OuiNonNull"));
+ self::assertSame("N", $wrapper->format("ON"));
+ self::assertSame("N", $wrapper->format("ONN"));
+
+ $wrapper->set("yes");
+ self::assertSame(true, $wrapper->get());
+
+ $wrapper->set(" yes ");
+ self::assertSame(true, $wrapper->get());
+
+ $wrapper->set("12");
+ self::assertSame(true, $wrapper->get());
+
+ $wrapper->set(12);
+ self::assertSame(true, $wrapper->get());
+
+ $wrapper->set("no");
+ self::assertSame(false, $wrapper->get());
+
+ $wrapper->set(" no ");
+ self::assertSame(false, $wrapper->get());
+
+ $wrapper->set("0");
+ self::assertSame(false, $wrapper->get());
+
+ $wrapper->set(0);
+ self::assertSame(false, $wrapper->get());
+
+ $wrapper->set(12.34);
+ self::assertSame(true, $wrapper->get());
+
+ self::assertException(Exception::class, $wrapperSetter("a"));
+ self::assertException(Exception::class, $wrapperSetter([]));
+ self::assertException(Exception::class, $wrapperSetter(["a"]));
+
+ }
+
+ function testBool() {
+ /** @var ScalarWrapper $wrapper */
+ Schema::nw($value, null, $schema, "bool", $wrapper);
+ $wrapperSetter = function($value) use($wrapper) {
+ return function() use($wrapper, $value) {
+ $wrapper->set($value);
+ };
+ };
+
+ self::assertException(Exception::class, $wrapperSetter(null));
+ self::assertException(Exception::class, $wrapperSetter(""));
+ self::assertException(Exception::class, $wrapperSetter(" "));
+
+ $this->commonTests($wrapper, $value, $wrapperSetter);
+ }
+
+ function testNbool() {
+ /** @var ScalarWrapper $wrapper */
+ Schema::nw($value, null, $schema, "?bool", $wrapper);
+ $wrapperSetter = function($value) use($wrapper) {
+ return function() use($wrapper, $value) {
+ $wrapper->set($value);
+ };
+ };
+
+ $wrapper->set(null);
+ self::assertNull($wrapper->get());
+ self::assertNull($value);
+ self::assertSame("Non", $wrapper->format());
+ self::assertSame("", $wrapper->format("OuiNonNull"));
+ self::assertSame("N", $wrapper->format("ON"));
+ self::assertSame("", $wrapper->format("ONN"));
+
+ $wrapper->set("");
+ self::assertNull($wrapper->get());
+ self::assertNull($value);
+ self::assertSame("Non", $wrapper->format());
+ self::assertSame("", $wrapper->format("OuiNonNull"));
+ self::assertSame("N", $wrapper->format("ON"));
+ self::assertSame("", $wrapper->format("ONN"));
+
+ $wrapper->set(" ");
+ self::assertNull($wrapper->get());
+ self::assertNull($value);
+ self::assertSame("Non", $wrapper->format());
+ self::assertSame("", $wrapper->format("OuiNonNull"));
+ self::assertSame("N", $wrapper->format("ON"));
+ self::assertSame("", $wrapper->format("ONN"));
+
+ $this->commonTests($wrapper, $value, $wrapperSetter);
+ }
+}
diff --git a/tests/wip/schema/types/floatTest.php b/tests/wip/schema/types/floatTest.php
new file mode 100644
index 0000000..a4679a4
--- /dev/null
+++ b/tests/wip/schema/types/floatTest.php
@@ -0,0 +1,139 @@
+set(12);
+ self::assertSame(12.0, $wrapper->get());
+ self::assertSame(12.0, $value);
+ self::assertSame("12", $wrapper->format());
+ self::assertSame("0012", $wrapper->format("%04u"));
+
+ $wrapper->set("12");
+ self::assertSame(12.0, $wrapper->get());
+
+ $wrapper->set(" 12 ");
+ self::assertSame(12.0, $wrapper->get());
+
+ $wrapper->set(12.34);
+ self::assertSame(12.34, $wrapper->get());
+
+ $wrapper->set(true);
+ self::assertSame(1.0, $wrapper->get());
+
+ self::assertException(Exception::class, $wrapperSetter("a"));
+ self::assertException(Exception::class, $wrapperSetter([]));
+ self::assertException(Exception::class, $wrapperSetter(["a"]));
+ }
+
+ function testFloat() {
+ /** @var ScalarWrapper $wrapper */
+ Schema::nw($value, null, $schema, "float", $wrapper);
+ $wrapperSetter = function($value) use($wrapper) {
+ return function() use($wrapper, $value) {
+ $wrapper->set($value);
+ };
+ };
+
+ self::assertException(Exception::class, $wrapperSetter(null));
+ self::assertException(Exception::class, $wrapperSetter(""));
+ self::assertException(Exception::class, $wrapperSetter(" "));
+
+ // valeur non requise donc retourne null
+ $wrapper->set(false);
+ self::assertNull($wrapper->get());
+
+ $this->commonTests($wrapper, $value, $wrapperSetter);
+ }
+
+ function testRequiredFloat() {
+ /** @var ScalarWrapper $wrapper */
+ Schema::nw($value, null, $schema, [
+ "float", null,
+ "required" => true,
+ ], $wrapper);
+ $wrapperSetter = function($value) use($wrapper) {
+ return function() use($wrapper, $value) {
+ $wrapper->set($value);
+ };
+ };
+
+ self::assertException(Exception::class, $wrapperSetter(null));
+ self::assertException(Exception::class, $wrapperSetter(""));
+ self::assertException(Exception::class, $wrapperSetter(" "));
+
+ // valeur requise donc lance une exception
+ self::assertException(Exception::class, $wrapperSetter(false));
+
+ $this->commonTests($wrapper, $value, $wrapperSetter);
+ }
+
+ function testNfloat() {
+ /** @var ScalarWrapper $wrapper */
+ Schema::nw($value, null, $schema, "?float", $wrapper);
+ $wrapperSetter = function($value) use($wrapper) {
+ return function() use($wrapper, $value) {
+ $wrapper->set($value);
+ };
+ };
+
+ $wrapper->set(null);
+ self::assertNull($wrapper->get());
+ self::assertNull($value);
+ self::assertSame("", $wrapper->format());
+
+ $wrapper->set("");
+ self::assertNull($wrapper->get());
+ self::assertNull($value);
+ self::assertSame("", $wrapper->format());
+
+ $wrapper->set(" ");
+ self::assertNull($wrapper->get());
+ self::assertNull($value);
+ self::assertSame("", $wrapper->format());
+
+ // valeur non requise donc retourne null
+ $wrapper->set(false);
+ self::assertNull($wrapper->get());
+
+ $this->commonTests($wrapper, $value, $wrapperSetter);
+ }
+
+ function testRequiredNfloat() {
+ /** @var ScalarWrapper $wrapper */
+ Schema::nw($value, null, $schema, [
+ "?float", null,
+ "required" => true,
+ ], $wrapper);
+ $wrapperSetter = function($value) use($wrapper) {
+ return function() use($wrapper, $value) {
+ $wrapper->set($value);
+ };
+ };
+
+ $wrapper->set(null);
+ self::assertNull($wrapper->get());
+ self::assertNull($value);
+ self::assertSame("", $wrapper->format());
+
+ $wrapper->set("");
+ self::assertNull($wrapper->get());
+ self::assertNull($value);
+ self::assertSame("", $wrapper->format());
+
+ $wrapper->set(" ");
+ self::assertNull($wrapper->get());
+ self::assertNull($value);
+ self::assertSame("", $wrapper->format());
+
+ // valeur requise donc lance une exception
+ self::assertException(Exception::class, $wrapperSetter(false));
+
+ $this->commonTests($wrapper, $value, $wrapperSetter);
+ }
+}
diff --git a/tests/wip/schema/types/intTest.php b/tests/wip/schema/types/intTest.php
new file mode 100644
index 0000000..c9cccbf
--- /dev/null
+++ b/tests/wip/schema/types/intTest.php
@@ -0,0 +1,139 @@
+set(12);
+ self::assertSame(12, $wrapper->get());
+ self::assertSame(12, $value);
+ self::assertSame("12", $wrapper->format());
+ self::assertSame("0012", $wrapper->format("%04u"));
+
+ $wrapper->set("12");
+ self::assertSame(12, $wrapper->get());
+
+ $wrapper->set(" 12 ");
+ self::assertSame(12, $wrapper->get());
+
+ $wrapper->set(12.34);
+ self::assertSame(12, $wrapper->get());
+
+ $wrapper->set(true);
+ self::assertSame(1, $wrapper->get());
+
+ self::assertException(Exception::class, $wrapperSetter("a"));
+ self::assertException(Exception::class, $wrapperSetter([]));
+ self::assertException(Exception::class, $wrapperSetter(["a"]));
+ }
+
+ function testInt() {
+ /** @var ScalarWrapper $wrapper */
+ Schema::nw($value, null, $schema, "int", $wrapper);
+ $wrapperSetter = function($value) use($wrapper) {
+ return function() use($wrapper, $value) {
+ $wrapper->set($value);
+ };
+ };
+
+ self::assertException(Exception::class, $wrapperSetter(null));
+ self::assertException(Exception::class, $wrapperSetter(""));
+ self::assertException(Exception::class, $wrapperSetter(" "));
+
+ // valeur non requise donc retourne null
+ $wrapper->set(false);
+ self::assertNull($wrapper->get());
+
+ $this->commonTests($wrapper, $value, $wrapperSetter);
+ }
+
+ function testRequiredInt() {
+ /** @var ScalarWrapper $wrapper */
+ Schema::nw($value, null, $schema, [
+ "int", null,
+ "required" => true,
+ ], $wrapper);
+ $wrapperSetter = function($value) use($wrapper) {
+ return function() use($wrapper, $value) {
+ $wrapper->set($value);
+ };
+ };
+
+ self::assertException(Exception::class, $wrapperSetter(null));
+ self::assertException(Exception::class, $wrapperSetter(""));
+ self::assertException(Exception::class, $wrapperSetter(" "));
+
+ // valeur requise donc lance une exception
+ self::assertException(Exception::class, $wrapperSetter(false));
+
+ $this->commonTests($wrapper, $value, $wrapperSetter);
+ }
+
+ function testNint() {
+ /** @var ScalarWrapper $wrapper */
+ Schema::nw($value, null, $schema, "?int", $wrapper);
+ $wrapperSetter = function($value) use($wrapper) {
+ return function() use($wrapper, $value) {
+ $wrapper->set($value);
+ };
+ };
+
+ $wrapper->set(null);
+ self::assertNull($wrapper->get());
+ self::assertNull($value);
+ self::assertSame("", $wrapper->format());
+
+ $wrapper->set("");
+ self::assertNull($wrapper->get());
+ self::assertNull($value);
+ self::assertSame("", $wrapper->format());
+
+ $wrapper->set(" ");
+ self::assertNull($wrapper->get());
+ self::assertNull($value);
+ self::assertSame("", $wrapper->format());
+
+ // valeur non requise donc retourne null
+ $wrapper->set(false);
+ self::assertNull($wrapper->get());
+
+ $this->commonTests($wrapper, $value, $wrapperSetter);
+ }
+
+ function testRequiredNint() {
+ /** @var ScalarWrapper $wrapper */
+ Schema::nw($value, null, $schema, [
+ "?int", null,
+ "required" => true,
+ ], $wrapper);
+ $wrapperSetter = function($value) use($wrapper) {
+ return function() use($wrapper, $value) {
+ $wrapper->set($value);
+ };
+ };
+
+ $wrapper->set(null);
+ self::assertNull($wrapper->get());
+ self::assertNull($value);
+ self::assertSame("", $wrapper->format());
+
+ $wrapper->set("");
+ self::assertNull($wrapper->get());
+ self::assertNull($value);
+ self::assertSame("", $wrapper->format());
+
+ $wrapper->set(" ");
+ self::assertNull($wrapper->get());
+ self::assertNull($value);
+ self::assertSame("", $wrapper->format());
+
+ // valeur requise donc lance une exception
+ self::assertException(Exception::class, $wrapperSetter(false));
+
+ $this->commonTests($wrapper, $value, $wrapperSetter);
+ }
+}
diff --git a/tests/wip/schema/types/strTest.php b/tests/wip/schema/types/strTest.php
new file mode 100644
index 0000000..184d99c
--- /dev/null
+++ b/tests/wip/schema/types/strTest.php
@@ -0,0 +1,123 @@
+set("");
+ self::assertSame("", $wrapper->get());
+ self::assertSame("", $value);
+
+ $wrapper->set(" ");
+ self::assertSame("", $wrapper->get());
+ self::assertSame("", $value);
+
+ $wrapper->set("a");
+ self::assertSame("a", $wrapper->get());
+ self::assertSame("a", $value);
+
+ $wrapper->set("12");
+ self::assertSame("12", $wrapper->get());
+
+ $wrapper->set(" 12 ");
+ self::assertSame("12", $wrapper->get());
+
+ $wrapper->set(12);
+ self::assertSame("12", $wrapper->get());
+
+ $wrapper->set(12.34);
+ self::assertSame("12.34", $wrapper->get());
+
+ $wrapper->set(true);
+ self::assertSame("1", $wrapper->get());
+
+ self::assertException(Exception::class, $wrapperSetter([]));
+ self::assertException(Exception::class, $wrapperSetter(["a"]));
+ }
+
+ function testStr() {
+ /** @var ScalarWrapper $wrapper */
+ Schema::nw($value, null, $schema, "string", $wrapper);
+ $wrapperSetter = function($value) use($wrapper) {
+ return function() use($wrapper, $value) {
+ $wrapper->set($value);
+ };
+ };
+
+ self::assertException(Exception::class, $wrapperSetter(null));
+
+ // valeur non requise donc retourne null
+ $wrapper->set(false);
+ self::assertNull($wrapper->get());
+
+ $this->commonTests($wrapper, $value, $wrapperSetter);
+ }
+
+ function testRequiredStr() {
+ /** @var ScalarWrapper $wrapper */
+ Schema::nw($value, null, $schema, [
+ "string", null,
+ "required" => true,
+ ], $wrapper);
+ $wrapperSetter = function($value) use($wrapper) {
+ return function() use($wrapper, $value) {
+ $wrapper->set($value);
+ };
+ };
+
+ self::assertException(Exception::class, $wrapperSetter(null));
+
+ // valeur requise donc lance une exception
+ self::assertException(Exception::class, $wrapperSetter(false));
+
+ $this->commonTests($wrapper, $value, $wrapperSetter);
+ }
+
+ function testNstr() {
+ /** @var ScalarWrapper $wrapper */
+ Schema::nw($value, null, $schema, "?string", $wrapper);
+ $wrapperSetter = function($value) use($wrapper) {
+ return function() use($wrapper, $value) {
+ $wrapper->set($value);
+ };
+ };
+
+ $wrapper->set(null);
+ self::assertNull($wrapper->get());
+ self::assertNull($value);
+ self::assertSame("", $wrapper->format());
+
+ // valeur non requise donc retourne null
+ $wrapper->set(false);
+ self::assertNull($wrapper->get());
+
+ $this->commonTests($wrapper, $value, $wrapperSetter);
+ }
+
+ function testRequiredNstr() {
+ /** @var ScalarWrapper $wrapper */
+ Schema::nw($value, null, $schema, [
+ "?string", null,
+ "required" => true,
+ ], $wrapper);
+ $wrapperSetter = function($value) use($wrapper) {
+ return function() use($wrapper, $value) {
+ $wrapper->set($value);
+ };
+ };
+
+ $wrapper->set(null);
+ self::assertNull($wrapper->get());
+ self::assertNull($value);
+ self::assertSame("", $wrapper->format());
+
+ // valeur requise donc lance une exception
+ self::assertException(Exception::class, $wrapperSetter(false));
+
+ $this->commonTests($wrapper, $value, $wrapperSetter);
+ }
+}
diff --git a/tests/wip/schema/types/unionTest.php b/tests/wip/schema/types/unionTest.php
new file mode 100644
index 0000000..312d3d4
--- /dev/null
+++ b/tests/wip/schema/types/unionTest.php
@@ -0,0 +1,30 @@
+set("12");
+ self::assertSame("12", $si);
+ $siw->set(12);
+ self::assertSame(12, $si);
+
+ # int puis string
+ /** @var ScalarWrapper $isw */
+ Schema::nw($is, null, $iss, "int|string", $isw);
+
+ $isw->set("12");
+ self::assertSame("12", $is);
+ $isw->set(12);
+ self::assertSame(12, $is);
+ }
+}