modifs.mineures sans commentaires

This commit is contained in:
Jephté Clain 2023-11-24 16:50:05 +04:00
parent 916aa54fc0
commit c1cdfdb855
18 changed files with 341 additions and 150 deletions

View File

@ -1,8 +1,8 @@
# -*- coding: utf-8 mode: yaml -*- vim:sw=2:sts=2:et:ai:si:sta:fenc=utf-8 # -*- coding: utf-8 mode: yaml -*- vim:sw=2:sts=2:et:ai:si:sta:fenc=utf-8
composer_php_min: '7.4' composer_php_min: '7.3'
composer_php_max: '8.0' composer_php_max: '8.0'
composer_registry: pubdocker.univ-reunion.fr composer_registry: pubdocker.univ-reunion.fr
composer_image: image/phpbuilder:d11 composer_image: image/phpbuilder:d10
defaults: defaults:
master: master:
allow_link: true allow_link: true

View File

@ -3,7 +3,6 @@
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="nur\sery\" /> <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="nur\sery\" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="nur\sery\" /> <sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="nur\sery\" />
<excludeFolder url="file://$MODULE_DIR$/vendor" /> <excludeFolder url="file://$MODULE_DIR$/vendor" />
</content> </content>

View File

@ -45,7 +45,7 @@
<path value="$PROJECT_DIR$/vendor/phpunit/phpunit" /> <path value="$PROJECT_DIR$/vendor/phpunit/phpunit" />
</include_path> </include_path>
</component> </component>
<component name="PhpProjectSharedConfiguration" php_language_level="7.4" /> <component name="PhpProjectSharedConfiguration" php_language_level="7.3" />
<component name="PhpStanOptionsConfiguration"> <component name="PhpStanOptionsConfiguration">
<option name="transferred" value="true" /> <option name="transferred" value="true" />
</component> </component>

View File

@ -14,10 +14,10 @@
], ],
"require": { "require": {
"nulib/php": "dev-wip", "nulib/php": "dev-wip",
"php": ">=7.4" "php": ">=7.3"
}, },
"require-dev": { "require-dev": {
"nulib/tests": "9", "nulib/tests": "7.3",
"phpunit/phpunit": "^9" "phpunit/phpunit": "^9"
}, },
"autoload": { "autoload": {

20
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "35175827c89c36554dda904ee7e0658d", "content-hash": "3255ed049bfe20f7ca8dfc802bcf506e",
"packages": [ "packages": [
{ {
"name": "nulib/php", "name": "nulib/php",
@ -12,7 +12,7 @@
"dist": { "dist": {
"type": "path", "type": "path",
"url": "../nulib", "url": "../nulib",
"reference": "7cac433cbc8890b4aa6787a12da3a87cc0bb6c3d" "reference": "ae65a36505313c06f822797f4dca58476af065eb"
}, },
"require": { "require": {
"php": ">=7.3" "php": ">=7.3"
@ -231,7 +231,7 @@
}, },
{ {
"name": "nulib/tests", "name": "nulib/tests",
"version": "9", "version": "7.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://git.univ-reunion.fr/sda-php/nulib-tests.git", "url": "https://git.univ-reunion.fr/sda-php/nulib-tests.git",
@ -1760,16 +1760,16 @@
}, },
{ {
"name": "theseer/tokenizer", "name": "theseer/tokenizer",
"version": "1.2.1", "version": "1.2.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/theseer/tokenizer.git", "url": "https://github.com/theseer/tokenizer.git",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1798,7 +1798,7 @@
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"support": { "support": {
"issues": "https://github.com/theseer/tokenizer/issues", "issues": "https://github.com/theseer/tokenizer/issues",
"source": "https://github.com/theseer/tokenizer/tree/1.2.1" "source": "https://github.com/theseer/tokenizer/tree/1.2.2"
}, },
"funding": [ "funding": [
{ {
@ -1806,7 +1806,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2021-07-28T10:34:58+00:00" "time": "2023-11-20T00:12:19+00:00"
} }
], ],
"aliases": [], "aliases": [],
@ -1817,7 +1817,7 @@
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,
"platform": { "platform": {
"php": ">=7.4" "php": ">=7.3"
}, },
"platform-dev": [], "platform-dev": [],
"plugin-api-version": "2.2.0" "plugin-api-version": "2.2.0"

View File

@ -39,30 +39,26 @@ La nature indique le type de données représenté par le schéma.
"title" => "libellé de la valeur", "title" => "libellé de la valeur",
"required" => false, "required" => false,
"nullable" => true, "nullable" => true,
"desc" => description de la valeur, "desc" => "description de la valeur",
"name" => "identifiant de la valeur", "name" => "identifiant de la valeur",
], ],
ITEM_SCHEMA, ITEM_SCHEMA,
]; ];
~~~ ~~~
les champs required, nullable, title et desc ne sont considérés que s'ils ne
sont pas déjà définis dans un schéma parent.
* nature tableau associatif: modélise un tableau associatif * nature tableau associatif: modélise un tableau associatif
~~~php ~~~php
const ASSOC_SCHEMA = [ const ASSOC_SCHEMA = [
"" => [assoc", "" => ["assoc",
"title" => "libellé de la valeur", "title" => "libellé de la valeur",
"required" => false, "required" => false,
"nullable" => true, "nullable" => true,
"desc" => description de la valeur, "desc" => "description de la valeur",
"name" => "identifiant de la valeur", "name" => "identifiant de la valeur",
], ],
KEY => VALUE_SCHEMA, KEY => VALUE_SCHEMA,
... ...
]; ];
~~~ ~~~
les champs required, nullable, title et desc ne sont considérés que s'ils ne
sont pas déjà définis dans un schéma parent.
## Schéma d'une valeur scalaire ## Schéma d'une valeur scalaire

View File

@ -0,0 +1,40 @@
<?php
namespace nur\sery\schema;
use nulib\cl;
class AssocSchema extends Schema {
/** @var array meta-schema d'un schéma de nature tableau associatif */
const METASCHEMA = [];
/**
* 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
if (array_key_exists("", $definition)) {
$nature = $definition[""];
if ($nature === "assoc") return true;
if (is_array($nature)
&& array_key_exists(0, $nature)
&& $nature[0] === "assoc") {
return true;
}
return false;
}
# un tableau associatif
return !cl::have_num_keys($definition);
}
static function normalize($definition): array {
}
function __construct($definition=null, bool $normalize=true) {
if ($definition === null) $definition = static::SCHEMA;
if ($normalize) $definition = self::normalize($definition);
$this->definition = $definition;
}
}

40
src/schema/ListSchema.php Normal file
View File

@ -0,0 +1,40 @@
<?php
namespace nur\sery\schema;
class ListSchema extends Schema {
/** @var array meta-schema d'un schéma de nature liste */
const METASCHEMA = [];
/**
* indiquer si $definition est une définition de schéma de nature liste que
* {@link normalize()} pourrait normaliser
*/
static function isa_definition($definition): bool {
if (!is_array($definition)) return false;
# nature explicitement spécifiée
if (array_key_exists("", $definition)) {
$nature = $definition[""];
if ($nature === "list") return true;
if (is_array($nature)
&& array_key_exists(0, $nature)
&& $nature[0] === "list") {
return true;
}
return false;
}
# un unique élément tableau à l'index 0
$count = count($definition);
$haveIndex0 = array_key_exists(0, $definition);
return $count == 1 && $haveIndex0 && is_array($definition[0]);
}
static function normalize($definition): array {
}
function __construct($definition=null, bool $normalize=true) {
if ($definition === null) $definition = static::SCHEMA;
if ($normalize) $definition = self::normalize($definition);
$this->definition = $definition;
}
}

129
src/schema/OldSchema.php Normal file
View File

@ -0,0 +1,129 @@
<?php
namespace nur\sery\schema;
use nur\sery\schema\input\Input;
use nur\sery\schema\values\AssocValue;
use nur\sery\schema\values\IValue;
use nur\sery\schema\values\ScalarValue;
use nur\sery\schema\values\SeqValue;
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
class OldSchema {
/**
* créer une nouvelle instance de cette classe à partir d'un schéma
*
* @param bool $normalized indique si le schéma est normalisé
* normalisé
*/
static function new(&$md, $schema, bool $normalized=false): self {
if ($md === null) $md = new static($schema, !$normalized);
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();
}
}

View File

@ -0,0 +1,48 @@
<?php
namespace nur\sery\schema;
class ScalarSchema extends Schema {
/** @var array meta-schema d'un schéma de nature scalaire */
const METASCHEMA = ref_schema::SCALAR_METASCHEMA;
/**
* indiquer si $definition est une définition de schéma scalaire que
* {@link normalize()} pourrait normaliser
*/
static function isa_definition($definition): bool {
# chaine ou null
if ($definition === null) return true;
if (is_string($definition)) return true;
if (!is_array($definition)) return false;
# nature explicitement spécifiée
if (array_key_exists("", $definition)) {
$nature = $definition[""];
if ($nature === "scalar") return true;
if (is_array($nature)
&& array_key_exists(0, $nature)
&& $nature[0] === "scalar") {
return true;
}
return false;
}
# un unique élément chaine à l'index 0
$count = count($definition);
$haveIndex0 = array_key_exists(0, $definition);
if ($count == 1 && $haveIndex0
&& ($definition[0] === null || is_string($definition[0]))) {
return true;
}
# un élément à l'index 0, et d'autres éléments
return $haveIndex0 && $count > 1;
}
static function normalize($definition): array {
}
function __construct($definition=null, bool $normalize=true) {
if ($definition === null) $definition = static::SCHEMA;
if ($normalize) $definition = self::normalize($definition);
$this->definition = $definition;
}
}

View File

@ -1,129 +1,31 @@
<?php <?php
namespace nur\sery\schema; namespace nur\sery\schema;
use nur\sery\schema\input\Input; abstract class Schema {
use nur\sery\schema\values\AssocValue;
use nur\sery\schema\values\IValue;
use nur\sery\schema\values\ScalarValue;
use nur\sery\schema\values\SeqValue;
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
class Schema {
/** /**
* créer une nouvelle instance de cette classe à partir d'un schéma * créer si besoin une nouvelle instance à partir d'une définition de schéma
*
* @param bool $normalized indique si le schéma est normalisé
* normalisé
*/ */
static function new(&$md, $schema, bool $normalized=false): self { static function new(&$md, $definition): self {
if ($md === null) $md = new static($schema, !$normalized); if ($md === null) {
if (AssocSchema::isa_definition($definition)) {
$md = new AssocSchema($definition);
} elseif (ListSchema::isa_definition($definition)) {
$md = new ListSchema($definition);
} elseif (ScalarSchema::isa_definition($definition)) {
$md = new ScalarSchema($definition);
} else {
throw SchemaException::invalid_schema();
}
}
return $md; return $md;
} }
static function normalize($schema): array { /**
if ($schema === null) throw new SchemaException("schema is required"); * @var array définition du schéma, à redéfinir le cas échéant dans une classe
elseif (!is_array($schema)) $schema = [$schema]; * dérivée
#XXX */
return $schema;
}
const SCHEMA = null; const SCHEMA = null;
function __construct($schema=null, bool $normalize=true) { /** @var array */
if ($schema === null) $schema = static::SCHEMA; protected $definition;
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();
}
} }

View File

@ -4,4 +4,7 @@ namespace nur\sery\schema;
use Exception; use Exception;
class SchemaException extends Exception { class SchemaException extends Exception {
static final function invalid_schema(): self {
return new static("invalid schema");
}
} }

View File

@ -30,6 +30,40 @@ class ref_schema {
const MESSAGES = [ const MESSAGES = [
"absent" => "{key}: Vous devez spécifier cette valeur", "absent" => "{key}: Vous devez spécifier cette valeur",
"null" => "{key}: Cette valeur ne doit pas être nulle", "null" => "{key}: Cette valeur ne doit pas être nulle",
"empty" => "{key}: Cette valeur ne doit pas être vide",
"invalid" => "{key}: {orig}: cette valeur est invalide", "invalid" => "{key}: {orig}: cette valeur est invalide",
]; ];
/** @var array schéma des natures de schéma */
public const NATURE_METASCHEMA = [
"nature" => ["string", null, "nature du schéma",
"key" => 0,
"allowed_values" => ["assoc", "list", "scalar"],
],
"title" => ["?string", null, "libellé de la valeur"],
"required" => ["bool", false, "la valeur est-elle requise?"],
"nullable" => ["?bool", null, "la valeur peut-elle être nulle?"],
"desc" => ["?content", null, "description de la valeur"],
"name" => ["?key", null, "identifiant de la valeur"],
"schema" => ["?array", null, "définition du schéma"],
];
/** @var array meta-schema d'un schéma de nature scalaire */
public const SCALAR_METASCHEMA = [
"type" => ["array", null, "types possibles de la valeur", "required" => true],
"default" => [null, null, "valeur par défaut si la valeur n'existe pas"],
"title" => ["?string", null, "libellé de la valeur"],
"required" => ["bool", false, "la valeur est-elle requise?"],
"nullable" => ["?bool", null, "la valeur peut-elle être nulle?"],
"desc" => ["?content", null, "description de la valeur"],
"analyzer_func" => ["?callable", null, "fonction qui analyse une valeur entrante et indique comment la traiter"],
"extractor_func" => ["?callable", null, "fonction qui extrait la valeur à analyser dans une chaine de caractère"],
"parser_func" => ["?callable", null, "fonction qui analyse une chaine de caractères pour produire la valeur"],
"normalizer_func" => ["?callable", null, "fonction qui normalise la valeur"],
"messages" => ["?array", null, "messages à afficher en cas d'erreur d'analyse"],
"formatter_func" => ["?callable", null, "fonction qui formatte la valeur pour affichage"],
"format" => [null, null, "format à utiliser pour l'affichage"],
"" => ["" => ["assoc", "schema" => self::NATURE_METASCHEMA]],
"name" => ["?key", null, "identifiant de la valeur"],
];
} }

View File

@ -1,17 +1,17 @@
<?php <?php
namespace nur\sery\schema\values; namespace nur\sery\schema\values;
use nur\sery\schema\Schema; use nur\sery\schema\OldSchema;
trait TValue { trait TValue {
/** @var array schéma normalisé de cette valeur */ /** @var array schéma normalisé de cette valeur */
protected array $schema; protected array $schema;
/** @var Schema */ /** @var OldSchema */
protected Schema $md; protected OldSchema $md;
function md(): Schema { function md(): OldSchema {
return Schema::new($this->md, $this->schema, true); return OldSchema::new($this->md, $this->schema, true);
} }
/** @var mixed valeur ou référence d'un tableau contenant la valeur */ /** @var mixed valeur ou référence d'un tableau contenant la valeur */

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\params; namespace nur\sery\web\params;
use nulib\str; use nulib\str;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\params; namespace nur\sery\web\params;
use nulib\cl; use nulib\cl;
use nulib\str; use nulib\str;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\params; namespace nur\sery\web\params;
use nulib\cl; use nulib\cl;
use nulib\str; use nulib\str;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\params; namespace nur\sery\web\params;
use nulib\cl; use nulib\cl;
use nulib\str; use nulib\str;