<?php namespace nur\sery\wip\schema; use ArrayAccess; use nur\sery\AccessException; use nur\sery\cl; use nur\sery\wip\schema\_assoc\AssocSchema; use nur\sery\wip\schema\_list\ListSchema; use nur\sery\wip\schema\_scalar\ScalarSchema; abstract class Schema implements ArrayAccess { /** * créer si besoin une nouvelle instance de {@link Schema} à partir d'une * définition de schéma * * - si $schema est une instance de schéma, la retourner * - si $schema est un array, c'est une définition, et elle est remplacée par * l'instance de Schema nouvelle créée * - sinon, prendre $definition comme définition */ static function ns(&$schema, $definition=null, $definitionKey=null): self { if (is_array($schema)) { $definition = $schema; $schema = null; } if ($schema === null) { if (AssocSchema::isa_definition($definition)) { $schema = new AssocSchema($definition, $definitionKey); } elseif (ListSchema::isa_definition($definition)) { $schema = new ListSchema($definition, $definitionKey); } elseif (ScalarSchema::isa_definition($definition)) { $schema = new ScalarSchema($definition, $definitionKey); } else { throw SchemaException::invalid_schema(); } } return $schema; } /** * 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 */ static function nv(?Value &$destv=null, &$dest=null, $destKey=null, &$schema=null, $definition=null): Value { 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); } /** * @var array définition du schéma, à redéfinir le cas échéant dans une classe * dérivée */ const SCHEMA = null; /** @var array */ protected $definition; /** retourner true si le schéma est de nature tableau associatif */ function isAssoc(?AssocSchema &$assoc=null): bool { return false; } /** retourner true si le schéma est de nature liste */ function isList(?ListSchema &$list=null): bool { return false; } /** retourner true si le schéma est de nature scalaire */ function isScalar(?ScalarSchema &$scalar=null): bool { return false; } abstract function newValue(?Value &$destv=null, &$dest=null, $destKey=null): Value; ############################################################################# # key & properties function offsetExists($offset): bool { return array_key_exists($offset, $this->definition); } function offsetGet($offset) { if (!array_key_exists($offset, $this->definition)) return null; else return $this->definition[$offset]; } function offsetSet($offset, $value): void { throw AccessException::read_only(null, $offset); } function offsetUnset($offset): void { throw AccessException::read_only(null, $offset); } const _PROPERTY_PKEYS = []; function __get($name) { $pkey = cl::get(static::_PROPERTY_PKEYS, $name, $name); return cl::pget($this->definition, $pkey); } }