Compare commits
	
		
			No commits in common. "c51809e47670505d28b0a759ff95d1e79b8fadee" and "fc795bbfcb11d34271d3dc15a6517a83270d9735" have entirely different histories.
		
	
	
		
			c51809e476
			...
			fc795bbfcb
		
	
		
@ -15,9 +15,10 @@ use Throwable;
 | 
				
			|||||||
 *   profil par défaut est dépendant de l'implémentation de IConfigManager
 | 
					 *   profil par défaut est dépendant de l'implémentation de IConfigManager
 | 
				
			||||||
 *   utilisée. Dans l'implémentation actuelle, 'ALL' est le profil par défaut.
 | 
					 *   utilisée. Dans l'implémentation actuelle, 'ALL' est le profil par défaut.
 | 
				
			||||||
 * - PKEY est le chemin de clé dans lequel les caractères '.' sont remplacés
 | 
					 * - PKEY est le chemin de clé dans lequel les caractères '.' sont remplacés
 | 
				
			||||||
 *   par '__'
 | 
					 *   par '__' et '-' par '_' (celà signifie qu'il n'est pas possible de définir
 | 
				
			||||||
 | 
					 *   un chemin de clé qui contient le caractère '_')
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * par exemple, la valeur dbs.my_auth.type du profil par défaut est pris dans
 | 
					 * par exemple, la valeur dbs.my-auth.type du profil par défaut est pris dans
 | 
				
			||||||
 * la variable 'CONFIG_ALL_dbs__my_auth__type'. pour le profil prod c'est la
 | 
					 * la variable 'CONFIG_ALL_dbs__my_auth__type'. pour le profil prod c'est la
 | 
				
			||||||
 * variable 'CONFIG_prod_dbs__my_auth__type'
 | 
					 * variable 'CONFIG_prod_dbs__my_auth__type'
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@ -50,9 +51,7 @@ class EnvConfig extends DynConfig {
 | 
				
			|||||||
    $profile = substr($name, 0, $i);
 | 
					    $profile = substr($name, 0, $i);
 | 
				
			||||||
    $name = substr($name, $i + 1);
 | 
					    $name = substr($name, $i + 1);
 | 
				
			||||||
    $pkey = str_replace("__", ".", $name);
 | 
					    $pkey = str_replace("__", ".", $name);
 | 
				
			||||||
    #XXX désactiver parce que les configurations sont plus généralement avec
 | 
					    $pkey = str_replace("_", "-", $pkey);
 | 
				
			||||||
    # le caractères '_', par le caractères '-'
 | 
					 | 
				
			||||||
    //$pkey = str_replace("_", "-", $pkey);
 | 
					 | 
				
			||||||
    return [$pkey, $profile];
 | 
					    return [$pkey, $profile];
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@ namespace nur\sery\wip\schema;
 | 
				
			|||||||
use nur\sery\wip\schema\input\Input;
 | 
					use nur\sery\wip\schema\input\Input;
 | 
				
			||||||
use nur\sery\wip\schema\types\IType;
 | 
					use nur\sery\wip\schema\types\IType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class WrapperContext {
 | 
					class AnalyzerContext {
 | 
				
			||||||
  function __construct(Schema $schema, Wrapper $wrapper, Input $input, $valueKey, Result $result) {
 | 
					  function __construct(Schema $schema, Wrapper $wrapper, Input $input, $valueKey, Result $result) {
 | 
				
			||||||
    $this->schema = $schema;
 | 
					    $this->schema = $schema;
 | 
				
			||||||
    $this->wrapper = $wrapper;
 | 
					    $this->wrapper = $wrapper;
 | 
				
			||||||
@ -164,7 +164,7 @@ abstract class Schema implements ArrayAccess {
 | 
				
			|||||||
    tcallable::ensure_ncallable($definition["normalizer_func"]);
 | 
					    tcallable::ensure_ncallable($definition["normalizer_func"]);
 | 
				
			||||||
    tarray::ensure_narray($definition["messages"]);
 | 
					    tarray::ensure_narray($definition["messages"]);
 | 
				
			||||||
    tcallable::ensure_ncallable($definition["formatter_func"]);
 | 
					    tcallable::ensure_ncallable($definition["formatter_func"]);
 | 
				
			||||||
    tbool::ensure_nbool($definition["computed"]);
 | 
					    tbool::ensure_nbool($definition["composite"]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch ($nature[0] ?? null) {
 | 
					    switch ($nature[0] ?? null) {
 | 
				
			||||||
    case "assoc":
 | 
					    case "assoc":
 | 
				
			||||||
 | 
				
			|||||||
@ -1,19 +1,23 @@
 | 
				
			|||||||
# nulib\schema
 | 
					# nulib\schema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* instance de WrapperContext directement dans le schéma 
 | 
					 | 
				
			||||||
* plus de {key} ni {orig} dans messages
 | 
					 | 
				
			||||||
  * les messages standard ne sont utilisés que s'il n'y a pas de message dans
 | 
					 | 
				
			||||||
    l'exception
 | 
					 | 
				
			||||||
  * si instance de UserException, prendre le message "non technique" pour
 | 
					 | 
				
			||||||
    résultat
 | 
					 | 
				
			||||||
* valeurs composite/computed
 | 
					 | 
				
			||||||
  * analyse / vérification de la valeur complète après calcul du résultat, si
 | 
					 | 
				
			||||||
    tous les résultats sont bons
 | 
					 | 
				
			||||||
  * calcul des valeurs composites/computed par une fonction avant/après l'analyse
 | 
					 | 
				
			||||||
    globale si résultat ok
 | 
					 | 
				
			||||||
* tdate et tdatetime. qu'en est-il des autres classes (delay, etc.)
 | 
					* tdate et tdatetime. qu'en est-il des autres classes (delay, etc.)
 | 
				
			||||||
  * possibilité de spécifier le format de la date à analyser 
 | 
					  * possibilité de spécifier le format de la date à analyser 
 | 
				
			||||||
* ScalarSchema::from_property()
 | 
					* 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)`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* dans AssocSchema, support `[key_prefix]` qui permet de spécifier un préfixe
 | 
					* dans AssocSchema, support `[key_prefix]` qui permet de spécifier un préfixe
 | 
				
			||||||
  commun aux champs dans le tableau destination, e.g
 | 
					  commun aux champs dans le tableau destination, e.g
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
namespace nur\sery\wip\schema\_scalar;
 | 
					namespace nur\sery\wip\schema\_scalar;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Exception;
 | 
				
			||||||
use nulib\cl;
 | 
					use nulib\cl;
 | 
				
			||||||
use nulib\ref\schema\ref_analyze;
 | 
					use nulib\ref\schema\ref_analyze;
 | 
				
			||||||
use nulib\ref\schema\ref_schema;
 | 
					use nulib\ref\schema\ref_schema;
 | 
				
			||||||
 | 
				
			|||||||
@ -91,11 +91,8 @@ class ScalarSchema extends Schema {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function getWrapper(&$value=null, $valueKey=null, ?Wrapper &$wrapper=null): ScalarWrapper {
 | 
					  function getWrapper(&$value=null, $valueKey=null, ?Wrapper &$wrapper=null): ScalarWrapper {
 | 
				
			||||||
    # si pas de valeur ni de wrapper, pas de vérification et donc pas d'exception
 | 
					 | 
				
			||||||
    # cf le code similaire dans ScalarWrapper::__construct()
 | 
					 | 
				
			||||||
    $verifix = $value !== null || $wrapper !== null;
 | 
					 | 
				
			||||||
    if (!($wrapper instanceof ScalarWrapper)) $wrapper = $this->newWrapper();
 | 
					    if (!($wrapper instanceof ScalarWrapper)) $wrapper = $this->newWrapper();
 | 
				
			||||||
    return $wrapper->reset($value, $valueKey, $verifix);
 | 
					    return $wrapper->reset($value, $valueKey);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #############################################################################
 | 
					  #############################################################################
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@ namespace nur\sery\wip\schema\_scalar;
 | 
				
			|||||||
use nulib\php\func;
 | 
					use nulib\php\func;
 | 
				
			||||||
use nulib\ref\schema\ref_analyze;
 | 
					use nulib\ref\schema\ref_analyze;
 | 
				
			||||||
use nulib\ValueException;
 | 
					use nulib\ValueException;
 | 
				
			||||||
use nur\sery\wip\schema\WrapperContext;
 | 
					use nur\sery\wip\schema\AnalyzerContext;
 | 
				
			||||||
use nur\sery\wip\schema\input\Input;
 | 
					use nur\sery\wip\schema\input\Input;
 | 
				
			||||||
use nur\sery\wip\schema\types;
 | 
					use nur\sery\wip\schema\types;
 | 
				
			||||||
use nur\sery\wip\schema\types\IType;
 | 
					use nur\sery\wip\schema\types\IType;
 | 
				
			||||||
@ -74,7 +74,7 @@ class ScalarWrapper extends Wrapper {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** analyser la valeur et résoudre son type */
 | 
					  /** analyser la valeur et résoudre son type */
 | 
				
			||||||
  protected function analyze0(WrapperContext $context): int {
 | 
					  protected function analyze0(AnalyzerContext $context): int {
 | 
				
			||||||
    /** @var ScalarSchema $schema */
 | 
					    /** @var ScalarSchema $schema */
 | 
				
			||||||
    $schema = $context->schema;
 | 
					    $schema = $context->schema;
 | 
				
			||||||
    $input = $context->input;
 | 
					    $input = $context->input;
 | 
				
			||||||
@ -171,7 +171,7 @@ class ScalarWrapper extends Wrapper {
 | 
				
			|||||||
    $valueKey = $this->valueKey;
 | 
					    $valueKey = $this->valueKey;
 | 
				
			||||||
    $result = $this->result;
 | 
					    $result = $this->result;
 | 
				
			||||||
    $result->reset();
 | 
					    $result->reset();
 | 
				
			||||||
    $context = new WrapperContext($schema, $this, $input, $valueKey, $result);
 | 
					    $context = new AnalyzerContext($schema, $this, $input, $valueKey, $result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** @var func $analyzerFunc */
 | 
					    /** @var func $analyzerFunc */
 | 
				
			||||||
    $analyzerFunc = $schema->analyzerFunc;
 | 
					    $analyzerFunc = $schema->analyzerFunc;
 | 
				
			||||||
@ -243,7 +243,7 @@ class ScalarWrapper extends Wrapper {
 | 
				
			|||||||
      /** @var func $normalizerFunc */
 | 
					      /** @var func $normalizerFunc */
 | 
				
			||||||
      $normalizerFunc = $schema->normalizerFunc;
 | 
					      $normalizerFunc = $schema->normalizerFunc;
 | 
				
			||||||
      if ($normalizerFunc !== null) {
 | 
					      if ($normalizerFunc !== null) {
 | 
				
			||||||
        $context = new WrapperContext($schema, $this, $this->input, $valueKey, $result);
 | 
					        $context = new AnalyzerContext($schema, $this, $this->input, $valueKey, $result);
 | 
				
			||||||
        $orig = $value;
 | 
					        $orig = $value;
 | 
				
			||||||
        $value = $normalizerFunc->invoke([$orig, $context]);
 | 
					        $value = $normalizerFunc->invoke([$orig, $context]);
 | 
				
			||||||
        $modified = $value !== $orig;
 | 
					        $modified = $value !== $orig;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,6 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
namespace nur\sery\wip\schema;
 | 
					namespace nur\sery\wip\schema;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use nulib\ValueException;
 | 
					 | 
				
			||||||
use nur\sery\wip\schema\types\IType;
 | 
					use nur\sery\wip\schema\types\IType;
 | 
				
			||||||
use nur\sery\wip\schema\types\Registry;
 | 
					use nur\sery\wip\schema\types\Registry;
 | 
				
			||||||
use nur\sery\wip\schema\types\tarray;
 | 
					use nur\sery\wip\schema\types\tarray;
 | 
				
			||||||
@ -32,11 +31,7 @@ class types {
 | 
				
			|||||||
    return self::$registry;
 | 
					    return self::$registry;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static function get(bool $nullable, $name, ?array $args=null, ?array $definition=null): IType {
 | 
					  static function get(bool $nullable, ?string $name, ?array $args=null, ?array $definition=null): IType {
 | 
				
			||||||
    if ($name instanceof IType) return $name;
 | 
					 | 
				
			||||||
    if ($name !== null && !is_string($name)) {
 | 
					 | 
				
			||||||
      throw ValueException::invalid_type($name, "string");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return self::registry()->get($nullable, $name, $args, $definition);
 | 
					    return self::registry()->get($nullable, $name, $args, $definition);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -10,8 +10,6 @@ use nur\sery\wip\schema\Schema;
 | 
				
			|||||||
 * Interface IType: un type de données
 | 
					 * Interface IType: un type de données
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
interface IType {
 | 
					interface IType {
 | 
				
			||||||
  static function get_params_from_definition(?array $definition): ?array;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * obtenir, pour information, le nom officiel de ce type, utilisable dans une
 | 
					   * obtenir, pour information, le nom officiel de ce type, utilisable dans une
 | 
				
			||||||
   * définition de schéma
 | 
					   * définition de schéma
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,6 @@ namespace nur\sery\wip\schema\types;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use nulib\cl;
 | 
					use nulib\cl;
 | 
				
			||||||
use nulib\php\func;
 | 
					use nulib\php\func;
 | 
				
			||||||
use nulib\ValueException;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Registry {
 | 
					class Registry {
 | 
				
			||||||
  const TYPES = [
 | 
					  const TYPES = [
 | 
				
			||||||
@ -17,7 +16,7 @@ class Registry {
 | 
				
			|||||||
    "array" => tarray::class,
 | 
					    "array" => tarray::class,
 | 
				
			||||||
    "callable" => tcallable::class,
 | 
					    "callable" => tcallable::class,
 | 
				
			||||||
    # types spéciaux
 | 
					    # types spéciaux
 | 
				
			||||||
    "raw" => traw::class,
 | 
					    "raw" => tmixed::class,
 | 
				
			||||||
    "mixed" => tmixed::class,
 | 
					    "mixed" => tmixed::class,
 | 
				
			||||||
    "key" => tkey::class,
 | 
					    "key" => tkey::class,
 | 
				
			||||||
    "pkey" => tpkey::class,
 | 
					    "pkey" => tpkey::class,
 | 
				
			||||||
@ -32,6 +31,8 @@ class Registry {
 | 
				
			|||||||
  protected $types;
 | 
					  protected $types;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function get(bool $nullable, ?string $name, ?array $args=null, ?array $definition=null): IType {
 | 
					  function get(bool $nullable, ?string $name, ?array $args=null, ?array $definition=null): IType {
 | 
				
			||||||
 | 
					    $name ??= "raw";
 | 
				
			||||||
 | 
					    $class = self::TYPES[$name];
 | 
				
			||||||
    if (cl::is_list($args)) {
 | 
					    if (cl::is_list($args)) {
 | 
				
			||||||
      $key = array_key_last($args);
 | 
					      $key = array_key_last($args);
 | 
				
			||||||
      $params = $args[$key];
 | 
					      $params = $args[$key];
 | 
				
			||||||
@ -40,16 +41,6 @@ class Registry {
 | 
				
			|||||||
      $params = $args;
 | 
					      $params = $args;
 | 
				
			||||||
      $args = null;
 | 
					      $args = null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    $name ??= "raw";
 | 
					 | 
				
			||||||
    $class = cl::get(self::TYPES, $name);
 | 
					 | 
				
			||||||
    if ($class === null) {
 | 
					 | 
				
			||||||
      $class = $name;
 | 
					 | 
				
			||||||
      if (!class_exists($class)) {
 | 
					 | 
				
			||||||
        throw ValueException::invalid_type($class, IType::class);
 | 
					 | 
				
			||||||
      } elseif (!is_subclass_of($class, IType::class)) {
 | 
					 | 
				
			||||||
        return new tgeneric($class, $nullable, $params);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    $params = cl::merge($class::get_params_from_definition($definition), $params);
 | 
					    $params = cl::merge($class::get_params_from_definition($definition), $params);
 | 
				
			||||||
    if ($args || $params !== null) {
 | 
					    if ($args || $params !== null) {
 | 
				
			||||||
      $args ??= [];
 | 
					      $args ??= [];
 | 
				
			||||||
 | 
				
			|||||||
@ -1,52 +0,0 @@
 | 
				
			|||||||
<?php
 | 
					 | 
				
			||||||
namespace nur\sery\wip\schema\types;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use nulib\ValueException;
 | 
					 | 
				
			||||||
use nur\sery\wip\schema\_scalar\ScalarResult;
 | 
					 | 
				
			||||||
use nur\sery\wip\schema\_scalar\ScalarSchema;
 | 
					 | 
				
			||||||
use nur\sery\wip\schema\input\Input;
 | 
					 | 
				
			||||||
use nur\sery\wip\schema\Result;
 | 
					 | 
				
			||||||
use nur\sery\wip\schema\Schema;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class tgeneric extends _tsimple {
 | 
					 | 
				
			||||||
  function __construct(string $class, bool $nullable, ?array $params=null) {
 | 
					 | 
				
			||||||
    $this->class = $class;
 | 
					 | 
				
			||||||
    parent::__construct($nullable, $params);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  protected string $class;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  function getClass(): string {
 | 
					 | 
				
			||||||
    return $this->class;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  function isAvailable(Input $input, $valueKey): bool {
 | 
					 | 
				
			||||||
    return $input->isAvailable($valueKey);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  public function isNull($value): bool {
 | 
					 | 
				
			||||||
    return $value === null;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  function isValid($value, ?bool &$normalized=null): bool {
 | 
					 | 
				
			||||||
    $normalized = true;
 | 
					 | 
				
			||||||
    return $value instanceof $this->class;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  function parse(string $value) {
 | 
					 | 
				
			||||||
    throw ValueException::invalid_type($value, $this->class);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * @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 strval($value);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -41,6 +41,6 @@ class tmixed extends _tsimple {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function format($value, $format=null): string {
 | 
					  function format($value, $format=null): string {
 | 
				
			||||||
    return strval($value);
 | 
					    return var_export($value, true);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -25,7 +25,7 @@ class AssocSchemaTest extends TestCase {
 | 
				
			|||||||
    "name" => null,
 | 
					    "name" => null,
 | 
				
			||||||
    "pkey" => null,
 | 
					    "pkey" => null,
 | 
				
			||||||
    "header" => null,
 | 
					    "header" => null,
 | 
				
			||||||
    "computed" => null,
 | 
					    "composite" => null,
 | 
				
			||||||
  ];
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static function schema(array $definition, array $keyDefinitions): array {
 | 
					  static function schema(array $definition, array $keyDefinitions): array {
 | 
				
			||||||
 | 
				
			|||||||
@ -24,7 +24,7 @@ class ScalarSchemaTest extends TestCase {
 | 
				
			|||||||
    "name" => null,
 | 
					    "name" => null,
 | 
				
			||||||
    "pkey" => null,
 | 
					    "pkey" => null,
 | 
				
			||||||
    "header" => null,
 | 
					    "header" => null,
 | 
				
			||||||
    "computed" => null,
 | 
					    "composite" => null,
 | 
				
			||||||
  ];
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static function schema(array $schema): array {
 | 
					  static function schema(array $schema): array {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user