diff --git a/src/schema/Schema.php b/src/schema/Schema.php index 113a857..30ad9cb 100644 --- a/src/schema/Schema.php +++ b/src/schema/Schema.php @@ -152,10 +152,9 @@ abstract class Schema implements ArrayAccess { switch ($nature[0] ?? null) { case "assoc": - foreach ($definition["schema"] as $definitionKey => &$definitionValue) { - self::_normalize($definitionValue, $definitionKey); - }; - unset($definitionValue); + foreach ($definition["schema"] as $definitionKey => &$subdef) { + $subdef = self::_normalize($subdef, $definitionKey); + }; unset($subdef); break; case "list": self::_normalize($definition["schema"]); @@ -206,6 +205,37 @@ abstract class Schema implements ArrayAccess { } } + protected static function _ensure_schema_instances(array $definition): array { + switch ($definition[""][0]) { + case "assoc": + foreach ($definition["schema"] as &$subdef) { + self::_ensure_schema_instances($subdef); + Schema::ns($subdef); + }; unset($subdef); + break; + case "list": + Schema::ns($definition["schema"]); + 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; + } + /** * @var array définition du schéma, à redéfinir le cas échéant dans une classe * dérivée @@ -215,15 +245,15 @@ abstract class Schema implements ArrayAccess { protected array $definition; function getDefinition(): array { - return $this->definition; + return self::_ensure_schema_array($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 getWrapper(&$value=null, $valueKey=null, ?Wrapper &$wrapper=null): Wrapper; diff --git a/src/schema/Wrapper.php b/src/schema/Wrapper.php index 20194dd..f373213 100644 --- a/src/schema/Wrapper.php +++ b/src/schema/Wrapper.php @@ -9,9 +9,9 @@ use nur\sery\wip\schema\_scalar\ScalarWrapper; use nur\sery\wip\schema\types\IType; abstract class Wrapper implements ArrayAccess, IteratorAggregate { - function isAssoc(?AssocWrapper &$assoc=null): bool { return false; } - function isList(?ListWrapper &$list=null): bool { return false; } - function isScalar(?ScalarWrapper &$scalar=null): bool { return false; } + 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(&$value, $valueKey=null, ?bool $verifix=null): self; diff --git a/src/schema/_assoc/AssocResult.php b/src/schema/_assoc/AssocResult.php index 99dbc41..d55f723 100644 --- a/src/schema/_assoc/AssocResult.php +++ b/src/schema/_assoc/AssocResult.php @@ -3,6 +3,6 @@ namespace nur\sery\wip\schema\_assoc; use nur\sery\wip\schema\Result; -abstract/*XXX*/ class AssocResult extends Result { +class AssocResult extends Result { function isAssoc(?AssocResult &$assoc=null): bool { $assoc = $this; return true;} } diff --git a/src/schema/_assoc/AssocSchema.php b/src/schema/_assoc/AssocSchema.php index 310f408..7966a1c 100644 --- a/src/schema/_assoc/AssocSchema.php +++ b/src/schema/_assoc/AssocSchema.php @@ -3,11 +3,7 @@ namespace nur\sery\wip\schema\_assoc; use nulib\cl; use nulib\ref\schema\ref_schema; -use nulib\ValueException; -use nur\sery\wip\schema\_scalar\ScalarSchema; use nur\sery\wip\schema\Schema; -use nur\sery\wip\schema\SchemaException; -use nur\sery\wip\schema\types; use nur\sery\wip\schema\Wrapper; /** @@ -59,13 +55,17 @@ class AssocSchema extends Schema { $this->definition = $definition; } - function isAssoc(?AssocSchema &$assoc=null): bool { - $assoc = $this; + function isAssoc(?AssocSchema &$schema=null): bool { + $schema = $this; return true; } - function getWrapper(&$value=null, $valueKey=null, ?Wrapper &$wrapper=null): AssocWrapper { - if ($wrapper instanceof AssocWrapper) return $wrapper->reset($value, $valueKey); - else return ($wrapper = new AssocWrapper($this, $value, $valueKey)); + 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/AssocWrapper.php b/src/schema/_assoc/AssocWrapper.php index 2a8b8d6..a120ef3 100644 --- a/src/schema/_assoc/AssocWrapper.php +++ b/src/schema/_assoc/AssocWrapper.php @@ -1,18 +1,135 @@ schema = $schema; + $this->verifix = $verifix; + $this->throw = $throw ?? false; + $this->result = new ScalarResult(); + $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 $type; + + protected ScalarResult $result; + + protected ?array $keys; + + protected ?array $wrappers; + + /** résultat de l'analyse de la valeur */ + protected ?array $results; + + 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 getWrapper($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(): 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->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 { } - - /** @param Result[] $results */ - function verifix(bool $throw=true, ?array &$results=null): bool { - } } diff --git a/src/schema/_list/ListSchema.php b/src/schema/_list/ListSchema.php index 66fee9c..4fb158d 100644 --- a/src/schema/_list/ListSchema.php +++ b/src/schema/_list/ListSchema.php @@ -2,10 +2,7 @@ namespace nur\sery\wip\schema\_list; use nulib\ref\schema\ref_schema; -use nulib\ValueException; -use nur\sery\wip\schema\_scalar\ScalarSchema; use nur\sery\wip\schema\Schema; -use nur\sery\wip\schema\SchemaException; use nur\sery\wip\schema\Wrapper; class ListSchema extends Schema { @@ -58,13 +55,17 @@ class ListSchema extends Schema { $this->definition = $definition; } - function isList(?ListSchema &$list=null): bool { - $list = $this; + function isList(?ListSchema &$schema=null): bool { + $schema = $this; return true; } + protected function newWrapper(): ListWrapper { + return new ListWrapper($this); + } + function getWrapper(&$value=null, $valueKey=null, ?Wrapper &$wrapper=null): ListWrapper { - if ($wrapper instanceof ListWrapper) return $wrapper->reset($value, $valueKey); - else return ($wrapper = new ListWrapper($this, $value, $valueKey)); + if (!($wrapper instanceof ListWrapper)) $wrapper = $this->newWrapper(); + return $wrapper->reset($value, $valueKey); } } diff --git a/src/schema/_list/ListWrapper.php b/src/schema/_list/ListWrapper.php index efe0754..cae167b 100644 --- a/src/schema/_list/ListWrapper.php +++ b/src/schema/_list/ListWrapper.php @@ -5,7 +5,7 @@ use nur\sery\wip\schema\Result; use nur\sery\wip\schema\Wrapper; abstract/*XXX*/ class ListWrapper extends Wrapper { - function isList(?ListWrapper &$list=null): bool { $list = $this; return true; } + function isList(?ListWrapper &$wrapper=null): bool { $wrapper = $this; return true; } function ensureKeys(): bool { } diff --git a/src/schema/_scalar/ScalarSchema.php b/src/schema/_scalar/ScalarSchema.php index a723c6a..5d2476b 100644 --- a/src/schema/_scalar/ScalarSchema.php +++ b/src/schema/_scalar/ScalarSchema.php @@ -75,8 +75,8 @@ class ScalarSchema extends Schema { } static function normalize($definition, $definitionKey=null): array { - self::_normalize($definition, $definitionKey); - self::_ensure_nature($definition, "scalar", null); + $definition = self::_normalize($definition, $definitionKey); + self::_ensure_nature($definition, "scalar"); return $definition; } @@ -87,14 +87,18 @@ class ScalarSchema extends Schema { $this->definition = $definition; } - function isScalar(?ScalarSchema &$scalar=null): bool { - $scalar = $this; + function isScalar(?ScalarSchema &$schema=null): bool { + $schema = $this; return true; } + protected function newWrapper(): ScalarWrapper { + return new ScalarWrapper($this); + } + function getWrapper(&$value=null, $valueKey=null, ?Wrapper &$wrapper=null): ScalarWrapper { - if ($wrapper instanceof ScalarWrapper) return $wrapper->reset($value, $valueKey); - else return ($wrapper = new ScalarWrapper($this, $value, $valueKey)); + if (!($wrapper instanceof ScalarWrapper)) $wrapper = $this->newWrapper(); + return $wrapper->reset($value, $valueKey); } ############################################################################# diff --git a/src/schema/_scalar/ScalarWrapper.php b/src/schema/_scalar/ScalarWrapper.php index 110c6f8..b90da28 100644 --- a/src/schema/_scalar/ScalarWrapper.php +++ b/src/schema/_scalar/ScalarWrapper.php @@ -27,7 +27,7 @@ class ScalarWrapper extends Wrapper { $this->throw = $throw ?? true; } - function isScalar(?ScalarWrapper &$scalar=null): bool { $scalar = $this; return true; } + function isScalar(?ScalarWrapper &$wrapper=null): bool { $wrapper = $this; return true; } /** schéma de cette valeur */ protected ScalarSchema $schema; diff --git a/tests/wip/schema/_assoc/AssocSchemaTest.php b/tests/wip/schema/_assoc/AssocSchemaTest.php new file mode 100644 index 0000000..ceb6728 --- /dev/null +++ b/tests/wip/schema/_assoc/AssocSchemaTest.php @@ -0,0 +1,70 @@ + ["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", + ])); + } +} diff --git a/tests/wip/schema/_scalar/ScalarSchemaTest.php b/tests/wip/schema/_scalar/ScalarSchemaTest.php index 0a2e071..84fdd35 100644 --- a/tests/wip/schema/_scalar/ScalarSchemaTest.php +++ b/tests/wip/schema/_scalar/ScalarSchemaTest.php @@ -3,7 +3,6 @@ namespace nur\sery\wip\schema\_scalar; use nulib\tests\TestCase; use nur\sery\wip\schema\SchemaException; -use nur\sery\wip\schema\types\IType; class ScalarSchemaTest extends TestCase { const NULL_SCHEMA = [ @@ -32,13 +31,6 @@ class ScalarSchemaTest extends TestCase { return array_merge(self::NULL_SCHEMA, $schema); } - static function sanitize(array $schema): array { - if ($schema["type"] instanceof IType) { - $schema["type"] = [$schema["type"]->getClass()]; - } - return $schema; - } - function testNormalize() { self::assertSame(self::NULL_SCHEMA, ScalarSchema::normalize(null)); self::assertSame(self::NULL_SCHEMA, ScalarSchema::normalize([])); @@ -51,22 +43,22 @@ class ScalarSchemaTest extends TestCase { }); $string = self::schema(["type" => ["string"], "nullable" => false]); - self::assertSame($string, self::sanitize(ScalarSchema::normalize("string"))); - self::assertSame($string, self::sanitize(ScalarSchema::normalize(["string"]))); + self::assertSame($string, ScalarSchema::normalize("string")); + self::assertSame($string, ScalarSchema::normalize(["string"])); $nstring = self::schema(["type" => ["string"]]); - self::assertSame($nstring, self::sanitize(ScalarSchema::normalize(["?string"]))); - self::assertSame($nstring, self::sanitize(ScalarSchema::normalize(["?string|null"]))); - self::assertSame($nstring, self::sanitize(ScalarSchema::normalize(["string|null"]))); - self::assertSame($nstring, self::sanitize(ScalarSchema::normalize([["?string", "null"]]))); - self::assertSame($nstring, self::sanitize(ScalarSchema::normalize([["string", "null"]]))); - self::assertSame($nstring, self::sanitize(ScalarSchema::normalize([["string", null]]))); + self::assertSame($nstring, ScalarSchema::normalize(["?string"])); + self::assertSame($nstring, ScalarSchema::normalize(["?string|null"])); + self::assertSame($nstring, ScalarSchema::normalize(["string|null"])); + self::assertSame($nstring, ScalarSchema::normalize([["?string", "null"]])); + self::assertSame($nstring, ScalarSchema::normalize([["string", "null"]])); + self::assertSame($nstring, ScalarSchema::normalize([["string", null]])); $key = self::schema(["type" => ["string", "int"], "nullable" => false]); - self::assertSame($key, self::sanitize(ScalarSchema::normalize("string|int"))); + self::assertSame($key, ScalarSchema::normalize("string|int")); $nkey = self::schema(["type" => ["string", "int"], "nullable" => true]); - self::assertSame($nkey, self::sanitize(ScalarSchema::normalize("?string|int"))); - self::assertSame($nkey, self::sanitize(ScalarSchema::normalize("string|?int"))); + self::assertSame($nkey, ScalarSchema::normalize("?string|int")); + self::assertSame($nkey, ScalarSchema::normalize("string|?int")); } } diff --git a/tests/wip/schema/_scalar/ScalarValueTest.php b/tests/wip/schema/_scalar/ScalarWrapperTest.php similarity index 92% rename from tests/wip/schema/_scalar/ScalarValueTest.php rename to tests/wip/schema/_scalar/ScalarWrapperTest.php index 7a5a43b..6e9326b 100644 --- a/tests/wip/schema/_scalar/ScalarValueTest.php +++ b/tests/wip/schema/_scalar/ScalarWrapperTest.php @@ -6,28 +6,28 @@ use nulib\ValueException; use nur\sery\wip\schema\input\Input; use stdClass; -class ScalarValueTest extends TestCase { - function checkValue(ScalarWrapper $wrapper, $dest, bool $present, bool $available, bool $valid, bool $normalized): void { - self::assertSame($dest, $wrapper->get(), "value"); +class ScalarWrapperTest extends TestCase { + function checkValue(ScalarWrapper $wrapper, $value, bool $present, bool $available, bool $valid, bool $normalized): void { + self::assertSame($value, $wrapper->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, $src, bool $verifix, $dest, bool $present, bool $available, bool $valid, bool $normalized, ?array $inputParams=null): void { - $value = $schema->getWrapper(); - if ($inputParams !== null) $input = new Input($src, $inputParams); - else $input = $src; - $value->reset($input, null, $verifix); - $this->checkValue($value, $dest, $present, $available, $valid, $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, $src, bool $verifix, string $exceptionClass, ?array $inputParams=null) { - $value = $schema->getWrapper(); - if ($inputParams !== null) $src = new Input($src, $inputParams); - self::assertException($exceptionClass, function() use ($value, &$src, $verifix) { - $value->reset($src, null, $verifix); + 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); }); }