nur-sery/src/schema/Schema.php

130 lines
4.3 KiB
PHP
Raw Normal View History

2023-11-09 10:03:35 +04:00
<?php
namespace nur\sery\schema;
2023-11-09 10:34:36 +04:00
use nur\sery\schema\input\Input;
2023-11-09 10:03:35 +04:00
use nur\sery\schema\values\AssocValue;
use nur\sery\schema\values\IValue;
use nur\sery\schema\values\ScalarValue;
use nur\sery\schema\values\SeqValue;
2023-11-09 10:34:36 +04:00
use nulib\StateException;
#XXX
# analyze() et [analyzer_func] --> indique ce qu'est la valeur qu'on vérifixe
# retourne MISSING (la valeur n'existe pas)
# NULL (la valeur existe mais est nulle)
# STRING (la valeur est une chaine qu'il faut parser)
# INVALID (la valeur n'est pas du bon type et il n'est pas possible de la convertir)
# VALID (la valeur est dans le bon type)
# extract() et [extractor_func] --> si analyze() retourne STRING, extraire la
# chaine à parser
# parse() et [parser_func] --> parser la chaine et retourner la valeur
# format() et [formatter_func] --> formatter la valeur et retourner une chaine
2023-11-09 10:03:35 +04:00
class Schema {
/**
2023-11-09 10:34:36 +04:00
* créer une nouvelle instance de cette classe à partir d'un schéma
*
* @param bool $normalized indique si le schéma est normalisé
2023-11-09 10:03:35 +04:00
* normalisé
*/
2023-11-09 10:34:36 +04:00
static function new(&$md, $schema, bool $normalized=false): self {
if ($md === null) $md = new static($schema, !$normalized);
2023-11-09 10:03:35 +04:00
return $md;
}
static function normalize($schema): array {
if ($schema === null) throw new SchemaException("schema is required");
elseif (!is_array($schema)) $schema = [$schema];
#XXX
return $schema;
}
const SCHEMA = null;
function __construct($schema=null, bool $normalize=true) {
if ($schema === null) $schema = static::SCHEMA;
if ($normalize) $schema = self::normalize($schema);
$this->schema = $schema;
}
/**
* @var array schéma normalisé
*
* il y a 3 formes pour un schéma:
* - schéma valeur scalaire [0 => type, 1 => default, ...]
* - schéma tableau séquentiel [schema]
* - schéma tableau associatif [key => schema, ...]
*/
protected $schema;
/**
* retourner true si le schéma est pour une valeur scalaire, false s'il s'agit
* du schéma d'un tableau (séquentiel ou associatif)
*/
function isScalar(): bool {
return array_key_exists(0, $this->schema) && array_key_exists(1, $this->schema);
}
/** retourner true si le schéma est pour un tableau séquentiel */
function isSeq(): bool {
return array_key_exists(0, $this->schema) && !array_key_exists(1, $this->schema);
}
/** retourner true si le schéma est pour un tableau associatif */
function isAssoc(): bool {
return !array_key_exists(0, $this->schema) && !array_key_exists(1, $this->schema);
}
/**
* @var bool true si toutes les clés du schéma doivent exister, avec leur
* valeur par défaut le cas échéant
*/
protected $ppEnsureKeys;
/** @var bool true si les clés doivent être dans l'ordre du schéma */
protected $ppOrderKeys;
/**
* @var bool true si les valeurs doivent être automatiquement vérifiées et
* corrigées
*/
protected $ppVerifix;
function ensureSchema(&$value, $key=null, ?array $params=null): void {
}
/** retourner true si la valeur est scalaire */
function getScalar(&$value, $key=null, ?ScalarValue &$scalar=null): bool {
if (!$this->isScalar()) return false;
if ($value instanceof Input) $input = $value;
else $input = new Input($value);
$scalar = new ScalarValue($input, $this->schema, $key);
return true;
}
/** retourner true la valeur est un tableau séquentiel */
function getSeq(&$value, $key=null, ?SeqValue &$seq=null): bool {
if (!$this->isSeq()) return false;
if ($value instanceof Input) $input = $value;
else $input = new Input($value);
$seq = new SeqValue($input, $this->schema, $key);
return true;
}
/** retourner true la valeur est un tableau associatif */
function getAssoc(&$value, $key=null, ?AssocValue &$assoc=null): bool {
if (!$this->isAssoc()) return false;
if ($value instanceof Input) $input = $value;
else $input = new Input($value);
$assoc = new AssocValue($input, $this->schema, $key);
return true;
}
function getValue(&$value, $key=null): IValue {
if ($this->getScalar($input, $key, $scalar)) return $scalar;
elseif ($this->getSeq($input, $key, $seq)) return $seq;
elseif ($this->getAssoc($input, $key, $assoc)) return $assoc;
else throw StateException::unexpected_state();
}
}