diff --git a/src/schema/Result.php b/src/schema/Result.php index e3d696b..2a63685 100644 --- a/src/schema/Result.php +++ b/src/schema/Result.php @@ -13,9 +13,9 @@ abstract class Result { $this->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 diff --git a/src/schema/Schema.php b/src/schema/Schema.php index 30ad9cb..0bbd86e 100644 --- a/src/schema/Schema.php +++ b/src/schema/Schema.php @@ -9,6 +9,7 @@ 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; @@ -26,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(); } @@ -59,7 +60,22 @@ abstract class Schema implements ArrayAccess { return self::ns($schema, $definition)->getWrapper($value, $valueKey, $wrapper); } - protected static function _normalize($definition, $definitionKey=null): array { + 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; @@ -152,16 +168,14 @@ abstract class Schema implements ArrayAccess { switch ($nature[0] ?? null) { case "assoc": - foreach ($definition["schema"] as $definitionKey => &$subdef) { - $subdef = self::_normalize($subdef, $definitionKey); - }; unset($subdef); + foreach ($definition["schema"] as $key => &$keydef) { + self::_normalize($keydef, $key); + }; unset($keydef); break; case "list": self::_normalize($definition["schema"]); break; } - - return $definition; } protected static function _ensure_nature(array $definition, string $expectedNature, ?string $expectedType=null): void { @@ -181,7 +195,7 @@ abstract class Schema implements ArrayAccess { $types = $definition["type"]; $nullable = $definition["nullable"]; # s'il n'y a qu'une seul type, l'instancier tout de suite - if (count($types) == 1 && $types[0] !== null) { + if (is_array($types) && count($types) == 1 && $types[0] !== null) { foreach ($types as $key => $name) { if ($key === 0) { $args = null; @@ -194,10 +208,9 @@ abstract class Schema implements ArrayAccess { } switch ($definition[""][0]) { case "assoc": - foreach ($definition["schema"] as &$definitionValue) { - self::_ensure_type($definitionValue); - }; - unset($definitionValue); + foreach ($definition["schema"] as &$keydef) { + self::_ensure_type($keydef); + }; unset($keydef); break; case "list": self::_ensure_type($definition["schema"]); @@ -205,35 +218,18 @@ abstract class Schema implements ArrayAccess { } } - protected static function _ensure_schema_instances(array $definition): array { + protected static function _ensure_schema_instances(array &$definition): void { switch ($definition[""][0]) { case "assoc": - foreach ($definition["schema"] as &$subdef) { - self::_ensure_schema_instances($subdef); - Schema::ns($subdef); - }; unset($subdef); + 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"]); + Schema::ns($definition["schema"], null, null, false); break; } - return $definition; - } - - protected static function _ensure_schema_array(array $definition): array { - switch ($definition[""][0]) { - case "assoc": - foreach ($definition["schema"] as &$subdef) { - if ($subdef instanceof Schema) $subdef = $subdef->getDefinition(); - }; unset($subdef); - break; - case "list": - $subdef = $definition["schema"]; - if ($subdef instanceof Schema) $subdef = $subdef->getDefinition(); - $definition["schema"] = $subdef; - break; - } - return $definition; } /** @@ -242,10 +238,12 @@ abstract class Schema implements ArrayAccess { */ const SCHEMA = null; + protected array $_definition; + protected array $definition; function getDefinition(): array { - return self::_ensure_schema_array($this->definition); + return $this->_definition; } /** retourner true si le schéma est de nature tableau associatif */ diff --git a/src/schema/TODO.md b/src/schema/TODO.md index 92fcbc0..a7a5233 100644 --- a/src/schema/TODO.md +++ b/src/schema/TODO.md @@ -1,5 +1,7 @@ # 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 diff --git a/src/schema/_assoc/AssocResult.php b/src/schema/_assoc/AssocResult.php index d55f723..acada76 100644 --- a/src/schema/_assoc/AssocResult.php +++ b/src/schema/_assoc/AssocResult.php @@ -4,5 +4,5 @@ namespace nur\sery\wip\schema\_assoc; use nur\sery\wip\schema\Result; class AssocResult extends Result { - function isAssoc(?AssocResult &$assoc=null): bool { $assoc = $this; return true;} + function isAssoc(?AssocResult &$result=null): bool { $result = $this; return true;} } diff --git a/src/schema/_assoc/AssocSchema.php b/src/schema/_assoc/AssocSchema.php index 7966a1c..cabcc38 100644 --- a/src/schema/_assoc/AssocSchema.php +++ b/src/schema/_assoc/AssocSchema.php @@ -13,25 +13,18 @@ class AssocSchema extends Schema { /** @var array meta-schema d'un schéma de nature tableau associatif */ const METASCHEMA = ref_schema::ASSOC_METASCHEMA; - private static function have_nature(array $definition): bool { - $nature = $definition[""] ?? null; - if ($nature === "assoc") return true; - if (is_array($nature) - && array_key_exists(0, $nature) - && $nature[0] === "assoc") { - return true; - } - return false; - } - /** * indiquer si $definition est une définition de schéma de nature tableau * associatif que {@link normalize()} pourrait normaliser */ static function isa_definition($definition): bool { if (!is_array($definition)) return false; - # nature explicitement spécifiée ou tableau associatif - return self::have_nature($definition) || !cl::have_num_keys($definition); + # nature explicitement spécifiée + if (self::have_nature($definition, $nature)) { + return $nature === "assoc"; + } + # tableau associatif + return !cl::have_num_keys($definition); } static function normalize($definition, $definitionKey=null): array { @@ -43,15 +36,19 @@ class AssocSchema extends Schema { "schema" => $definition, ]; } - $definition = self::_normalize($definition, $definitionKey); + 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); - self::_ensure_type($definition); + if ($normalize) { + $definition = self::normalize($definition, $definitionKey); + $this->_definition = $definition; + self::_ensure_type($definition); + self::_ensure_schema_instances($definition); + } $this->definition = $definition; } diff --git a/src/schema/_list/ListResult.php b/src/schema/_list/ListResult.php index dc33239..5aeb5ac 100644 --- a/src/schema/_list/ListResult.php +++ b/src/schema/_list/ListResult.php @@ -4,5 +4,5 @@ namespace nur\sery\wip\schema\_list; use nur\sery\wip\schema\Result; abstract/*XXX*/ class ListResult extends Result { - function isList(?ListResult &$list=null): bool { $list = $this; return true;} + function isList(?ListResult &$result=null): bool { $result = $this; return true;} } diff --git a/src/schema/_list/ListSchema.php b/src/schema/_list/ListSchema.php index 4fb158d..f75b759 100644 --- a/src/schema/_list/ListSchema.php +++ b/src/schema/_list/ListSchema.php @@ -9,17 +9,6 @@ class ListSchema extends Schema { /** @var array meta-schema d'un schéma de nature liste */ const METASCHEMA = ref_schema::LIST_METASCHEMA; - private static function have_nature(array $definition): bool { - $nature = $definition[""] ?? null; - if ($nature === "list") return true; - if (is_array($nature) - && array_key_exists(0, $nature) - && $nature[0] === "list") { - return true; - } - return false; - } - /** * indiquer si $definition est une définition de schéma de nature liste que * {@link normalize()} pourrait normaliser @@ -27,7 +16,9 @@ class ListSchema extends Schema { static function isa_definition($definition): bool { if (!is_array($definition)) return false; # nature explicitement spécifiée - if (self::have_nature($definition)) return true; + if (self::have_nature($definition, $nature)) { + return $nature === "list"; + } # un unique élément tableau à l'index 0 $count = count($definition); $haveIndex0 = array_key_exists(0, $definition); @@ -43,15 +34,19 @@ class ListSchema extends Schema { "schema" => $definition[0], ]; } - $definition = self::_normalize($definition, $definitionKey); + 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); - self::_ensure_type($definition); + if ($normalize) { + $definition = self::normalize($definition, $definitionKey); + $this->_definition = $definition; + self::_ensure_type($definition); + self::_ensure_schema_instances($definition); + } $this->definition = $definition; } diff --git a/src/schema/_scalar/ScalarResult.php b/src/schema/_scalar/ScalarResult.php index b247aba..09be6be 100644 --- a/src/schema/_scalar/ScalarResult.php +++ b/src/schema/_scalar/ScalarResult.php @@ -33,7 +33,7 @@ class ScalarResult extends Result { "origValue", "normalizedValue", ]; - function isScalar(?ScalarResult &$scalar=null): bool { $scalar = $this; return true; } + function isScalar(?ScalarResult &$result=null): bool { $result = $this; return true; } function getKeys(): array { return [null]; diff --git a/src/schema/_scalar/ScalarSchema.php b/src/schema/_scalar/ScalarSchema.php index 5d2476b..95e07ed 100644 --- a/src/schema/_scalar/ScalarSchema.php +++ b/src/schema/_scalar/ScalarSchema.php @@ -1,19 +1,9 @@ _definition = $definition; + self::_ensure_type($definition); + self::_ensure_schema_instances($definition); + } $this->definition = $definition; } diff --git a/tests/wip/schema/_assoc/AssocSchemaTest.php b/tests/wip/schema/_assoc/AssocSchemaTest.php index ceb6728..25ebc31 100644 --- a/tests/wip/schema/_assoc/AssocSchemaTest.php +++ b/tests/wip/schema/_assoc/AssocSchemaTest.php @@ -1,9 +1,9 @@ "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()); + } }