modifs.mineures sans commentaires
This commit is contained in:
parent
02e49afb65
commit
6037b3e7ca
|
@ -0,0 +1,8 @@
|
||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
|
@ -0,0 +1,14 @@
|
||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="PhpAbstractStaticMethodInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PhpDocMissingReturnTagInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PhpDocSignatureInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="PhpSignatureMismatchDuringInheritanceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||||
|
<option name="processCode" value="true" />
|
||||||
|
<option name="processLiterals" value="true" />
|
||||||
|
<option name="processComments" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/nur-sery.iml" filepath="$PROJECT_DIR$/.idea/nur-sery.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="nur\sery\" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="PhpDockerContainerSettings">
|
||||||
|
<list>
|
||||||
|
<map>
|
||||||
|
<entry key="125ffb9d-fd5f-4e71-8182-94191665795a">
|
||||||
|
<value>
|
||||||
|
<DockerContainerSettings>
|
||||||
|
<option name="version" value="1" />
|
||||||
|
<option name="volumeBindings">
|
||||||
|
<list>
|
||||||
|
<DockerVolumeBindingImpl>
|
||||||
|
<option name="containerPath" value="/opt/project" />
|
||||||
|
</DockerVolumeBindingImpl>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</DockerContainerSettings>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</list>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="MessDetectorOptionsConfiguration">
|
||||||
|
<option name="transferred" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="PHPCSFixerOptionsConfiguration">
|
||||||
|
<option name="transferred" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="PHPCodeSnifferOptionsConfiguration">
|
||||||
|
<option name="highlightLevel" value="WARNING" />
|
||||||
|
<option name="transferred" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="PhpIncludePathManager">
|
||||||
|
<include_path>
|
||||||
|
<path value="$PROJECT_DIR$/vendor/phar-io/manifest" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/phar-io/version" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/nulib/tests" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/nulib/php" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/composer" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/exporter" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/resource-operations" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/theseer/tokenizer" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/global-state" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/complexity" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/recursion-context" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/object-enumerator" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/object-reflector" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/cli-parser" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/diff" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/lines-of-code" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/nikic/php-parser" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/type" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/version" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/comparator" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/environment" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/doctrine/instantiator" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/myclabs/deep-copy" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/phpunit/php-timer" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/phpunit/php-file-iterator" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/phpunit/php-text-template" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/phpunit/php-invoker" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/phpunit/php-code-coverage" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/phpunit/phpunit" />
|
||||||
|
</include_path>
|
||||||
|
</component>
|
||||||
|
<component name="PhpProjectSharedConfiguration" php_language_level="7.4" />
|
||||||
|
<component name="PhpStanOptionsConfiguration">
|
||||||
|
<option name="transferred" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="PhpUnit">
|
||||||
|
<phpunit_settings>
|
||||||
|
<PhpUnitSettings custom_loader_path="$PROJECT_DIR$/vendor/autoload.php" />
|
||||||
|
</phpunit_settings>
|
||||||
|
</component>
|
||||||
|
<component name="PsalmOptionsConfiguration">
|
||||||
|
<option name="transferred" value="true" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="PHPUnit">
|
||||||
|
<option name="directories">
|
||||||
|
<list>
|
||||||
|
<option value="$PROJECT_DIR$/tests" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery\output;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Output: une destination pour écrire du contenu
|
||||||
|
*/
|
||||||
|
abstract class Output {
|
||||||
|
abstract function print($value): void;
|
||||||
|
|
||||||
|
/** afficher un tag, dont la fonction n'est pas d'être affiché à l'utilisateur, mais de structuer l'information affichée à l'utilisateur */
|
||||||
|
function printTag(?array $tag): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** afficher un contenu destiné à être affiché à l'utilisateur */
|
||||||
|
function printContent(?array $content): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** afficher une ligne de donnée au format CSV */
|
||||||
|
abstract function printCsv(?array $row): void;
|
||||||
|
|
||||||
|
abstract function printObject($object): void;
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery\output;
|
||||||
|
|
||||||
|
trait TOutputObjectAsCsv {
|
||||||
|
function printObject($object): void {
|
||||||
|
if ($object === null) return;
|
||||||
|
if (is_object($object)) $object = (array)$object;
|
||||||
|
if (is_array($object)) $this->printCsv($object);
|
||||||
|
else $this->printContent([$object]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery\output;
|
||||||
|
|
||||||
|
class TtyOutput extends Output {
|
||||||
|
use TOutputObjectAsCsv;
|
||||||
|
|
||||||
|
function print($value): void {
|
||||||
|
echo $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function printTag(?array $tag): void {
|
||||||
|
# Ne pas écrire les tags
|
||||||
|
#XXX convertir certains tags en couleurs?
|
||||||
|
}
|
||||||
|
|
||||||
|
function printCsv(?array $row): void {
|
||||||
|
#XXX rendre paramétrable les options de sortie
|
||||||
|
fputcsv(STDOUT, $row);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery\output;
|
||||||
|
|
||||||
|
class WebOutput extends Output {
|
||||||
|
use TOutputObjectAsCsv;
|
||||||
|
|
||||||
|
function print($value): void {
|
||||||
|
echo $value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery\schema;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class FormInput: accès à des paramètres de formulaire (POST ou GET, dans cet
|
||||||
|
* ordre)
|
||||||
|
*
|
||||||
|
* cette implémentation lit depuis les paramètres de formulaire et écrit dans
|
||||||
|
* une référence
|
||||||
|
*/
|
||||||
|
class FormInput extends Input {
|
||||||
|
function exists($key=null): bool {
|
||||||
|
if ($key === null) return false;
|
||||||
|
return array_key_exists($key, $_POST) || array_key_exists($key, $_GET);
|
||||||
|
}
|
||||||
|
|
||||||
|
function get($key=null) {
|
||||||
|
if ($key === null) return null;
|
||||||
|
if (array_key_exists($key, $_POST)) return $_POST[$key];
|
||||||
|
elseif (array_key_exists($key, $_GET)) return $_GET[$key];
|
||||||
|
else return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery\schema;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class GetInput: accès à des paramètres de formulaire de type GET uniquement
|
||||||
|
*
|
||||||
|
* cette implémentation lit depuis les paramètres de formulaire et écrit dans
|
||||||
|
* une référence
|
||||||
|
*/
|
||||||
|
class GetInput extends Input {
|
||||||
|
function exists($key=null): bool {
|
||||||
|
if ($key === null) return false;
|
||||||
|
return array_key_exists($key, $_GET);
|
||||||
|
}
|
||||||
|
|
||||||
|
function get($key=null) {
|
||||||
|
if ($key === null) return null;
|
||||||
|
if (array_key_exists($key, $_GET)) return $_GET[$key];
|
||||||
|
else return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery\schema;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Input: accès à une valeur
|
||||||
|
*
|
||||||
|
* cette implémentation lit depuis et écrit dans une référence
|
||||||
|
*/
|
||||||
|
class Input {
|
||||||
|
function __construct(&$value=null) {
|
||||||
|
$this->value =& $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected $value;
|
||||||
|
|
||||||
|
function exists($key=null): bool {
|
||||||
|
if ($key === null) return true;
|
||||||
|
return $this->value !== null && array_key_exists($key, $this->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function get($key=null) {
|
||||||
|
if ($key === null) return $this->value;
|
||||||
|
elseif ($this->value === null) return null;
|
||||||
|
elseif (!array_key_exists($key, $this->value)) return null;
|
||||||
|
else return $this->value[$key];
|
||||||
|
}
|
||||||
|
|
||||||
|
function set($value, $key=null): void {
|
||||||
|
if ($key === null) $this->value = $value;
|
||||||
|
else $this->value[$key] = $value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery\schema;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class PostInput: accès à des paramètres de formulaire de type POST uniquement
|
||||||
|
*
|
||||||
|
* cette implémentation lit depuis les paramètres de formulaire et écrit dans
|
||||||
|
* une référence
|
||||||
|
*/
|
||||||
|
class PostInput extends Input {
|
||||||
|
function exists($key=null): bool {
|
||||||
|
if ($key === null) return false;
|
||||||
|
return array_key_exists($key, $_POST);
|
||||||
|
}
|
||||||
|
|
||||||
|
function get($key=null) {
|
||||||
|
if ($key === null) return null;
|
||||||
|
if (array_key_exists($key, $_POST)) return $_POST[$key];
|
||||||
|
else return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery\schema;
|
||||||
|
|
||||||
|
use nur\sery\StateException;
|
||||||
|
use nur\sery\schema\values\AssocValue;
|
||||||
|
use nur\sery\schema\values\IValue;
|
||||||
|
use nur\sery\schema\values\ScalarValue;
|
||||||
|
use nur\sery\schema\values\SeqValue;
|
||||||
|
|
||||||
|
class Schema {
|
||||||
|
/**
|
||||||
|
* créer une nouvelle instance de cette classe à partir d'un schéma non
|
||||||
|
* normalisé
|
||||||
|
*/
|
||||||
|
static function new(&$md, $schema): self {
|
||||||
|
if ($md === null) $md = new static($schema);
|
||||||
|
return $md;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** obtenir une instance de cette classe à partir d'un schéma normalisé */
|
||||||
|
static function with(array $schema): self {
|
||||||
|
return new static($schema, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery\schema;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class SchemaException extends Exception {
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery\schema;
|
||||||
|
|
||||||
|
class ref_schema {
|
||||||
|
const SCHEMA_SCHEMA = [
|
||||||
|
"type" => ["string", null, "" => 0,
|
||||||
|
"required" => true,
|
||||||
|
"desc" => "type de la valeur",
|
||||||
|
],
|
||||||
|
"default" => [null, null, "" => 1,
|
||||||
|
"desc" => "valeur par défaut",
|
||||||
|
],
|
||||||
|
"key" => ["?key", null, "" => "",
|
||||||
|
"desc" => "clé de la valeur si elle est dans un tableau",
|
||||||
|
],
|
||||||
|
"required" => ["bool", false,
|
||||||
|
"desc" => "cette valeur est-elle requise?",
|
||||||
|
],
|
||||||
|
"formatter" => ["?callable", null,
|
||||||
|
"desc" => "signature de la fonction: (value, format, type) => string",
|
||||||
|
],
|
||||||
|
"parser" => ["?callable", null,
|
||||||
|
"desc" => "signature de la fonction: (value, type) => [value, result]",
|
||||||
|
],
|
||||||
|
"messages" => ["?array", null,
|
||||||
|
"desc" => "message à afficher en cas d'erreur d'analyse",
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
const MESSAGES = [
|
||||||
|
"absent" => "{key}: Vous devez spécifier cette valeur",
|
||||||
|
"null" => "{key}: Cette valeur ne doit pas être nulle",
|
||||||
|
"invalid" => "{key}: {orig}: cette valeur est invalide",
|
||||||
|
];
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery\schema\types;
|
||||||
|
|
||||||
|
use nur\sery\schema\values\Result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface IType: un type de données
|
||||||
|
*/
|
||||||
|
interface IType {
|
||||||
|
/**
|
||||||
|
* indiquer si la valeur a été fournie par l'utilisateur (elle doit exister
|
||||||
|
* et être non vide)
|
||||||
|
*/
|
||||||
|
function available($value, $key=null): bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* indiquer si la valeur spécifiée existe. cette méthode permet de distinguer
|
||||||
|
* les cas "fourni par l'utilisateur mais vide" et "non fourni par l'utilisateur"
|
||||||
|
*/
|
||||||
|
function exists($value, $key=null): bool;
|
||||||
|
|
||||||
|
function verifix(&$value, bool $throw, ?Result &$result);
|
||||||
|
|
||||||
|
function format($value, ?string $format);
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery\schema\values;
|
||||||
|
|
||||||
|
class AssocValue implements IValue {
|
||||||
|
use TValue;
|
||||||
|
|
||||||
|
function isScalar(?ScalarValue &$scalar=null): bool { return false; }
|
||||||
|
function isSeq(?SeqValue &$seq=null): bool { return false; }
|
||||||
|
function isAssoc(?AssocValue &$assoc=null): bool { $assoc = $this; return true; }
|
||||||
|
|
||||||
|
function ensureKeys(): bool {
|
||||||
|
}
|
||||||
|
function orderKeys(): bool {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param Result[] $results */
|
||||||
|
function verifix(bool $throw=true, ?array &$results=null): bool {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery\schema\values;
|
||||||
|
|
||||||
|
use nur\sery\schema\types\IType;
|
||||||
|
|
||||||
|
interface IValue {
|
||||||
|
/** retourner true si cette valeur est scalaire */
|
||||||
|
function isScalar(?ScalarValue &$scalar=null): bool;
|
||||||
|
|
||||||
|
/** retourner true cette valeur est un tableau séquentiel */
|
||||||
|
function isSeq(?SeqValue &$seq=null): bool;
|
||||||
|
|
||||||
|
/** retourner true cette valeur est un tableau associatif */
|
||||||
|
function isAssoc(?AssocValue &$assoc=null): bool;
|
||||||
|
|
||||||
|
function reset(&$value, $key=null, bool $verifix=true): void;
|
||||||
|
|
||||||
|
/** retourner true si la valeur existe */
|
||||||
|
function exists(): bool;
|
||||||
|
|
||||||
|
/** retourner true si la valeur est valide */
|
||||||
|
function isValid(): bool;
|
||||||
|
|
||||||
|
/** retourner true si la valeur est dans sa forme normalisée */
|
||||||
|
function isNormalized();
|
||||||
|
|
||||||
|
/** retourner le type associé à cette valeur */
|
||||||
|
function getType(): IType;
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery\schema\values;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Result: résultat de l'analyse ou de la normalisation d'une valeur
|
||||||
|
*
|
||||||
|
* @property-read bool $valid
|
||||||
|
* @property-read string|int|null $key si la valeur est dans un tableau, clé de
|
||||||
|
* la valeur dans le tableau
|
||||||
|
* @property-read string|null $orig valeur originale avant analyse
|
||||||
|
* @property-read string|null $message message d'erreur si la valeur n'est pas
|
||||||
|
* valide
|
||||||
|
*/
|
||||||
|
class Result {
|
||||||
|
const KEYS = ["valid", "key", "orig", "message"];
|
||||||
|
|
||||||
|
function __construct(?array $result=null) {
|
||||||
|
if ($result === null) $result = ["valid" => false];
|
||||||
|
foreach (static::KEYS as $key) {
|
||||||
|
if (!array_key_exists($key, $result)) $result[$key] = null;
|
||||||
|
}
|
||||||
|
#XXX interpoler [message] avec les clés de $result
|
||||||
|
$this->result = $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected $result;
|
||||||
|
|
||||||
|
function __get($name) {
|
||||||
|
return $this->result[$name];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery\schema\values;
|
||||||
|
|
||||||
|
use nur\sery\schema\types\IType;
|
||||||
|
|
||||||
|
class ScalarValue implements IValue {
|
||||||
|
use TValue;
|
||||||
|
|
||||||
|
function __construct(&$value, array $schema, $key=null, bool $verifix=true) {
|
||||||
|
$this->schema = $schema;
|
||||||
|
$this->reset($value, $key, $verifix);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isScalar(?ScalarValue &$scalar=null): bool { $scalar = $this; return true; }
|
||||||
|
function isSeq(?SeqValue &$seq=null): bool { return false; }
|
||||||
|
function isAssoc(?AssocValue &$assoc=null): bool { return false; }
|
||||||
|
|
||||||
|
function get($default=null) {
|
||||||
|
$key = $this->key;
|
||||||
|
if ($key === null) return $this->value;
|
||||||
|
elseif (array_key_exists($key, $this->value)) return $this->value[$key];
|
||||||
|
else return $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
function set($value): self {
|
||||||
|
$key = $this->key;
|
||||||
|
if ($key === null) $this->value = $value;
|
||||||
|
else $this->value[$key] = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var IType */
|
||||||
|
protected $type;
|
||||||
|
|
||||||
|
function type(): IType {
|
||||||
|
if ($this->type === null) $this->type = $this->md()->getType($this->key);
|
||||||
|
return $this->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var ?Result résultat de l'analyse de la valeur */
|
||||||
|
protected $result;
|
||||||
|
|
||||||
|
function exists(): bool {
|
||||||
|
return $this->type()->exists($this->value, $this->key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* analyser, corriger éventuellement et normaliser la valeur
|
||||||
|
*
|
||||||
|
* si la valeur était déjà normalisée, retourner false.
|
||||||
|
*/
|
||||||
|
function verifix(bool $throw=true, ?Result &$result=null): bool {
|
||||||
|
$type = $this->type();
|
||||||
|
$key = $this->key;
|
||||||
|
if ($key === null) $modified = $type->verifix($this->value, $throw, $result);
|
||||||
|
else $modified = $type->verifix($this->value[$key], $throw, $result);
|
||||||
|
$this->result = $result;
|
||||||
|
return $modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse($value, bool $throw=true, ?Result &$result=null) {
|
||||||
|
$this->type()->verifix($value, $throw, $result);
|
||||||
|
$this->set($value);
|
||||||
|
$this->result = $result;
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function format(?string $format=null): string {
|
||||||
|
$type = $this->type();
|
||||||
|
$key = $this->key;
|
||||||
|
if ($key === null) return $type->format($this->value, $format);
|
||||||
|
else return $type->format($this->value[$key], $format);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery\schema\values;
|
||||||
|
|
||||||
|
class SeqValue implements IValue {
|
||||||
|
use TValue;
|
||||||
|
|
||||||
|
function isScalar(?ScalarValue &$scalar=null): bool { return false; }
|
||||||
|
function isSeq(?SeqValue &$seq=null): bool { $seq = $this; return true; }
|
||||||
|
function isAssoc(?AssocValue &$assoc=null): bool { return false; }
|
||||||
|
|
||||||
|
function ensureKeys(): bool {
|
||||||
|
}
|
||||||
|
|
||||||
|
function orderKeys(): bool {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param Result[] $results */
|
||||||
|
function verifix(bool $throw=true, ?array &$results=null): bool {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery\schema\values;
|
||||||
|
|
||||||
|
use nur\sery\schema\Schema;
|
||||||
|
|
||||||
|
trait TValue {
|
||||||
|
/** @var array schéma normalisé de cette valeur */
|
||||||
|
protected $schema;
|
||||||
|
|
||||||
|
/** @var Schema */
|
||||||
|
protected $md;
|
||||||
|
|
||||||
|
function md(): Schema {
|
||||||
|
if ($this->md === null) $this->md = Schema::with($this->schema);
|
||||||
|
return $this->md;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var mixed valeur ou référence d'un tableau contenant la valeur */
|
||||||
|
protected $value;
|
||||||
|
|
||||||
|
/** @var string|int clé de la valeur dans le tableau destination */
|
||||||
|
protected $key;
|
||||||
|
|
||||||
|
function reset(&$value, $key=null, bool $verifix=true): void {
|
||||||
|
$this->value =& $value;
|
||||||
|
$this->key = $key;
|
||||||
|
$this->result = null;
|
||||||
|
if ($verifix) $this->verifix();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue