modifs.mineures sans commentaires

This commit is contained in:
Jephté Clain 2025-03-05 07:50:38 +04:00
parent 68023b72ee
commit 74487a0ab9
21 changed files with 432 additions and 170 deletions

View File

@ -2,5 +2,12 @@
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GrazieInspection" enabled="false" level="GRAMMAR_ERROR" enabled_by_default="false" />
<inspection_tool class="LanguageDetectionInspection" 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>

15
.idea/php.xml generated
View File

@ -10,6 +10,11 @@
<option name="highlightLevel" value="WARNING" />
<option name="transferred" value="true" />
</component>
<component name="PhpCodeSniffer">
<phpcs_settings>
<phpcs_by_interpreter asDefaultInterpreter="true" interpreter_id="846389f7-9fb5-4173-a868-1dc6b8fbb3fa" timeout="30000" />
</phpcs_settings>
</component>
<component name="PhpIncludePathManager">
<include_path>
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
@ -64,6 +69,11 @@
</include_path>
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="7.4" />
<component name="PhpStan">
<PhpStan_settings>
<phpstan_by_interpreter asDefaultInterpreter="true" interpreter_id="846389f7-9fb5-4173-a868-1dc6b8fbb3fa" timeout="60000" />
</PhpStan_settings>
</component>
<component name="PhpStanOptionsConfiguration">
<option name="transferred" value="true" />
</component>
@ -72,6 +82,11 @@
<PhpUnitSettings custom_loader_path="$PROJECT_DIR$/vendor/autoload.php" />
</phpunit_settings>
</component>
<component name="Psalm">
<Psalm_settings>
<psalm_fixer_by_interpreter asDefaultInterpreter="true" interpreter_id="846389f7-9fb5-4173-a868-1dc6b8fbb3fa" timeout="60000" />
</Psalm_settings>
</component>
<component name="PsalmOptionsConfiguration">
<option name="transferred" value="true" />
</component>

View File

@ -11,6 +11,7 @@ class AnalyzerContext {
$this->destKey = $destKey;
$this->result = $result;
$this->type = null;
$this->orig = null;
$this->value = null;
}
@ -21,5 +22,7 @@ class AnalyzerContext {
public Result $result;
public ?IType $type;
/** @var mixed */
public $orig;
/** @var mixed */
public $value;
}

View File

@ -6,8 +6,6 @@ use nulib\ref\schema\ref_analyze;
use nulib\ValueException;
use nur\sery\wip\schema\AnalyzerContext;
use nur\sery\wip\schema\input\Input;
use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Schema;
use nur\sery\wip\schema\types;
use nur\sery\wip\schema\types\IType;
use nur\sery\wip\schema\Value;
@ -57,8 +55,7 @@ class ScalarValue extends Value {
$this->destKey = $destKey;
$this->type = null;
$this->analyzeExtractParse();
if ($verifix === null) $verifix = $this->defaultVerifix;
if ($verifix) $this->verifix();
if ($verifix ?? $this->defaultVerifix) $this->verifix();
return $this;
}
@ -123,32 +120,37 @@ class ScalarValue extends Value {
# sinon prendre le premier type
if (!$haveType) $type = $this->type = $firstType;
$context->type = $type;
if (!$type->isAvailable($input, $destKey)) return $result->setUnavailable($schema);
$value = $context->value = $input->get($destKey);
if ($type->isNull($value)) return $result->setNull($schema);
if ($type->isValid($value, $normalized)) {
$value = $input->get($destKey);
$context->orig = $context->value = $value;
if ($type->isNull($value)) {
return $result->setNull($schema);
} elseif (is_string($value)) {
return ref_analyze::STRING;
} elseif ($type->isValid($value, $normalized)) {
if ($normalized) return $result->setNormalized();
else return $result->setValid();
} else {
return $result->setInvalid($value, $schema);
}
if (is_string($value)) return ref_analyze::STRING;
else return $result->setInvalid($value, $schema);
}
function _extract(AnalyzerContext $context): void {
$value = $context->value;
$value = $context->type->extract($value);
$context->value = $value;
function _extract(AnalyzerContext $context): bool {
return $context->type->extract($context->value);
}
function _parse(AnalyzerContext $context): void {
$value = $context->value;
$value = $context->type->parse($value);
$context->value = $value;
function _parse(AnalyzerContext $context): bool {
try {
$context->value = $context->type->parse($context->value);
return true;
} catch (ValueException $e) {
return false;
}
}
function analyzeExtractParse(): void {
function analyzeExtractParse(): int {
$schema = $this->schema;
$input = $this->input;
$destKey = $this->destKey;
@ -160,18 +162,31 @@ class ScalarValue extends Value {
$analyzerFunc = $schema->analyzerFunc;
if ($analyzerFunc !== null) $what = $analyzerFunc->invoke([$context]);
else $what = $this->_analyze($context);
if ($what !== ref_analyze::STRING) return $what;
if ($what === ref_analyze::STRING) {
/** @var func $extractorFunc */
$extractorFunc = $schema->extractorFunc;
if ($extractorFunc !== null) $extractorFunc->invoke([$context]);
else $this->_extract($context);
/** @var func $extractorFunc */
$extractorFunc = $schema->extractorFunc;
if ($extractorFunc !== null) $valid = $extractorFunc->invoke([$context]);
else $valid = $this->_extract($context);
if (!$valid) return $result->setInvalid($context->orig, $schema);
if ($context->type->isNull($context->value)) return $result->setNull($schema);
$extracted = $context->value;
/** @var func $parserFunc */
$parserFunc = $schema->parserFunc;
if ($parserFunc !== null) $parserFunc->invoke([$context]);
else $this->_parse($context);
/** @var func $parserFunc */
$parserFunc = $schema->parserFunc;
if ($parserFunc !== null) $valid = $parserFunc->invoke([$context]);
else $valid = $this->_parse($context);
if ($valid) {
$normalized = $context->value === $context->orig;
if ($normalized) {
$input->set($context->value, $destKey);
return $result->setNormalized();
} else {
$input->set($extracted, $destKey);
return $result->setValid();
}
}
return $result->setInvalid($context->orig, $schema);
}
function verifix(?bool $throw=null): bool {
@ -247,6 +262,18 @@ class ScalarValue extends Value {
}
function format($format=null): string {
return $this->type->format($this->input->get($this->destKey), $format);
$value = $this->input->get($this->destKey);
/** @var func $formatterFunc */
$formatterFunc = $this->schema->formatterFunc;
if ($formatterFunc !== null) {
# la fonction formatter n'a pas forcément accès au format de la définition
# le lui fournir ici
$format ??= $this->schema->format;
return $formatterFunc->invoke([$value, $format]);
} else {
# on assume que le type a été initialisé avec le format de la définition
# le cas échéant
return $this->type->format($value, $format);
}
}
}

View File

@ -9,6 +9,7 @@ use nur\sery\wip\schema\types\tcallable;
use nur\sery\wip\schema\types\tfloat;
use nur\sery\wip\schema\types\tint;
use nur\sery\wip\schema\types\trawstring;
use nur\sery\wip\schema\types\ttext;
/**
* Class types: classe outil pour gérer le registre de types
@ -30,6 +31,7 @@ class types {
static function rawstring(): trawstring { return self::get("rawstring"); }
static function string(): tstring { return self::get("string"); }
static function text(): ttext { return self::get("text"); }
static function bool(): tbool { return self::get("bool"); }
static function int(): tint { return self::get("int"); }
static function float(): tfloat { return self::get("float"); }

View File

@ -1,6 +1,7 @@
<?php
namespace nur\sery\wip\schema\types;
use nulib\ValueException;
use nur\sery\wip\schema\input\Input;
use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Schema;
@ -15,25 +16,38 @@ interface IType {
/** la valeur $value est-elle nulle? */
function isNull($value): bool;
/** la valeur $value est-elle valide et normalisée le cas échéant? */
/**
* la valeur $value est-elle valide et normalisée le cas échéant?
*
* NB: si $value est un string. elle doit avoir déjà été traitée au préalable
* par extract() et parse()
*/
function isValid($value, ?bool &$normalized=null): bool;
/** extraire de la chaine la valeur à analyser */
function extract(string $value): string;
function extract(string &$value): bool;
/** analyser la chaine et retourner la valeur "convertie" */
/**
* analyser la chaine et retourner la valeur "convertie"
*
* @throws ValueException en cas d'erreur d'analyse
*/
function parse(string $value);
/**
* analyser, corriger éventuellement et normaliser la valeur
*
* NB: si $value est un string. elle doit avoir déjà été traitée au préalable
* par extract() et parse()
*
* si la valeur était déjà normalisée, ou si une erreur s'est produite,
* retourner false.
*/
function verifix(&$value, Result &$result, Schema $schema): bool;
function verifix(&$value, Result $result, Schema $schema): bool;
/**
* formatter la valeur pour affichage. $value est garanti d'être du bon type
* formatter la valeur pour affichage. si $value n'est pas null, elle est
* garantie d'être du bon type
*/
function format($value, $format=null): string;
}

View File

@ -8,6 +8,7 @@ class Registry {
const TYPES = [
"rawstring" => trawstring::class,
"string" => tstring::class,
"text" => ttext::class,
"bool" => tbool::class, "boolean" => tbool::class,
"int" => tint::class, "integer" => tint::class,
"float" => tfloat::class, "flt" => tfloat::class,
@ -29,7 +30,7 @@ class Registry {
function get(string $name, ?array $params=null, ?array $definition=null): IType {
$class = self::TYPES[$name];
$params = cl::merge($class::get_params($definition), $params);
$params = cl::merge($class::get_params_from_definition($definition), $params);
if ($params !== null) {
return func::with([$class, false, $params])->invoke();
}

View File

@ -0,0 +1,19 @@
<?php
namespace nur\sery\wip\schema\types;
abstract class _tformatable extends _tsimple {
const FORMAT = null;
static function get_params_from_definition(?array $definition): ?array {
$params = null;
$format = $definition["format"] ?? null;
if ($format !== null) $params["format"] = $format;
return $params;
}
function format($value, $format=null): string {
$format ??= $this->params["format"] ?? static::FORMAT;
if ($format !== null) return sprintf($format, $value);
else return strval($value);
}
}

View File

@ -4,7 +4,7 @@ namespace nur\sery\wip\schema\types;
use nur\sery\wip\schema\input\Input;
abstract class _tsimple implements IType {
static function get_params(?array $definition): ?array {
static function get_params_from_definition(?array $definition): ?array {
return null;
}
@ -19,14 +19,10 @@ abstract class _tsimple implements IType {
}
function isNull($value): bool {
return $value === null || (is_string($value) && trim($value) === "");
return $value === null || $value === "";
}
function extract(string $value): string {
return $value;
}
function parse(string $value) {
return $value;
function extract(string &$value): bool {
return true;
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace nur\sery\wip\schema\types;
use nulib\str;
abstract class _tstring extends _tsimple {
/** @var bool faut-il trimmer la valeur */
const TRIM = false;
/** @var bool faut-il normaliser les caractères fin de ligne */
const NORM_NL = false;
static function get_params_from_definition(?array $definition): ?array {
$params = null;
$trim = $definition["trim"] ?? null;
if ($trim !== null) $params["trim"] = $trim;
$normNl = $definition["norm_nl"] ?? null;
if ($normNl !== null) $params["norm_nl"] = $normNl;
return $params;
}
function extract(string &$value): bool {
if ($this->params["trim"] ?? static::TRIM) $value = trim($value);
if ($this->params["norm_nl"] ?? static::NORM_NL) $value = str::norm_nl($value);
return true;
}
}

View File

@ -2,10 +2,24 @@
namespace nur\sery\wip\schema\types;
use nulib\cl;
use nur\sery\wip\schema\_scalar\ScalarResult;
use nur\sery\wip\schema\_scalar\ScalarSchema;
use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Schema;
class tarray extends _tsimple {
class tarray extends _tstring {
const SPLIT_PATTERN = '/\s+/';
const FORMAT = " ";
public static function get_params_from_definition(?array $definition): ?array {
$params = parent::get_params_from_definition($definition);
$splitPattern = $definition["split_pattern"] ?? null;
if ($splitPattern !== null) $params["split_pattern"] = $splitPattern;
$format = $definition["format"] ?? null;
if ($format !== null) $params["format"] = $format;
return $params;
}
static function ensure_array(&$array): void {
if (!is_array($array)) $array = cl::with($array);
}
@ -19,9 +33,32 @@ class tarray extends _tsimple {
return is_scalar($value) || is_array($value);
}
function verifix(&$value, Result &$result, Schema $schema): bool {
function parse(string $value) {
$pattern = $this->params["split_pattern"] ?? static::SPLIT_PATTERN;
return preg_split($pattern, $value);
}
/**
* @var ScalarResult $result
* @var ScalarSchema $schema
*/
function verifix(&$value, Result $result, Schema $schema): bool {
if (is_array($value)) {
$result->setNormalized();
return false;
} elseif (is_scalar($value)) {
$value = cl::with($value);
$result->setValid();
return true;
} else {
$result->setInvalid($value, $schema);
return false;
}
}
function format($value, $format=null): string {
if ($value === null) return "";
$format ??= $this->params["format"] ?? static::FORMAT;
return implode($format, $value);
}
}

View File

@ -9,17 +9,15 @@ use nur\sery\wip\schema\input\Input;
use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Schema;
class tbool extends _tsimple {
class tbool extends _tformatable {
/** liste de valeurs chaines à considérer comme 'OUI' */
const YES_VALUES = [
# IMPORTANT: ordonner par taille décroissante pour compatibilité avec parse()
"true", "vrai", "yes", "oui",
"t", "v", "y", "o", "1",
];
/** liste de valeurs chaines à considérer comme 'NON' */
const NO_VALUES = [
# IMPORTANT: ordonner par taille décroissante pour compatibilité avec parse()
"false", "faux", "non", "no",
"f", "n", "0",
];
@ -59,35 +57,36 @@ class tbool extends _tsimple {
function isValid($value, ?bool &$normalized=null): bool {
$normalized = is_bool($value);
if (is_string($value)) {
$value = trim($value);
$valid = self::is_yes($value) || self::is_no($value);
} else {
$valid = is_scalar($value);
}
return $valid;
return is_scalar($value);
}
function extract(string &$value): bool {
$value = trim($value);
return true;
}
function parse(string $value) {
if (self::is_yes($value)) return true;
elseif (self::is_no($value)) return false;
throw new ValueException("une valeur booléenne est attendue");
}
/**
* @var ScalarResult $result
* @var ScalarSchema $schema
*/
function verifix(&$value, Result &$result, Schema $schema): bool {
function verifix(&$value, Result $result, Schema $schema): bool {
if (is_bool($value)) {
$result->setNormalized();
return false;
} elseif (is_string($value)) {
$bool = trim($value);
if (self::is_yes($bool)) $value = true;
elseif (self::is_no($bool)) $value = false;
else return $result->setInvalid($value, $schema);
} elseif (is_scalar($value)) {
$value = boolval($value);
$result->setValid();
return true;
} else {
return $result->setInvalid($value, $schema);
$result->setInvalid($value, $schema);
return false;
}
$result->setValid();
return true;
}
const OUINON_FORMAT = ["Oui", "Non", false];
@ -105,10 +104,10 @@ class tbool extends _tsimple {
"oz" => self::OZ_FORMAT,
];
const DEFAULT_FORMAT = self::OUINON_FORMAT;
const FORMAT = self::OUINON_FORMAT;
function format($value, $format=null): string {
if ($format === null) $format = static::DEFAULT_FORMAT;
$format ??= $this->params["format"] ?? static::FORMAT;
if (is_string($format)) {
$oformat = $format;
$format = cl::get(self::FORMATS, strtolower($oformat));

View File

@ -1,13 +1,17 @@
<?php
namespace nur\sery\wip\schema\types;
use Exception;
use nulib\php\func;
use nulib\ValueException;
use nur\sery\wip\schema\_scalar\ScalarResult;
use nur\sery\wip\schema\_scalar\ScalarSchema;
use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Schema;
class tcallable extends _tsimple {
static function ensure_callable(&$callable): void {
func::ensure($callable);
$callable = func::ensure($callable);
}
static function ensure_ncallable(&$callable): void {
@ -19,7 +23,30 @@ class tcallable extends _tsimple {
return func::check($value);
}
function verifix(&$value, Result &$result, Schema $schema): bool {
function parse(string $value) {
try {
return func::ensure($value);
} catch (Exception $e) {
throw new ValueException(null, null, 0, $e);
}
}
/**
* @var ScalarResult $result
* @var ScalarSchema $schema
*/
function verifix(&$value, Result $result, Schema $schema): bool {
if ($value instanceof func) {
$result->setNormalized();
return false;
} elseif (is_callable($value)) {
$value = func::with($value);
$result->setNormalized();
return true;
} else {
$result->setInvalid($value, $schema);
return false;
}
}
function format($value, $format=null): string {

View File

@ -1,6 +1,9 @@
<?php
namespace nur\sery\wip\schema\types;
use nulib\php\content\c;
use nur\sery\wip\schema\_scalar\ScalarResult;
use nur\sery\wip\schema\_scalar\ScalarSchema;
use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Schema;
@ -19,9 +22,29 @@ abstract class tcontent extends _tsimple {
return is_scalar($value) || is_array($value);
}
function verifix(&$value, Result &$result, Schema $schema): bool {
function parse(string $value) {
return $value;
}
/**
* @var ScalarResult $result
* @var ScalarSchema $schema
*/
function verifix(&$value, Result $result, Schema $schema): bool {
if (is_string($value) || is_array($value)) {
$result->setNormalized();
return false;
} elseif (is_scalar($value)) {
$value = strval($value);
$result->setValid();
return true;
} else {
$result->setInvalid($value, $schema);
return false;
}
}
function format($value, $format=null): string {
return c::to_string($value);
}
}

View File

@ -1,12 +1,13 @@
<?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\Result;
use nur\sery\wip\schema\Schema;
class tfloat extends _tsimple {
class tfloat extends _tformatable {
static function ensure_float(&$float): void {
if (!is_float($float)) $float = floatval($float);
}
@ -17,34 +18,35 @@ class tfloat extends _tsimple {
function isValid($value, ?bool &$normalized=null): bool {
$normalized = is_float($value);
if (is_string($value)) $valid = is_numeric(trim($value));
else $valid = is_scalar($value);
return $valid;
return is_scalar($value);
}
function extract(string &$value): bool {
$value = trim($value);
return true;
}
function parse(string $value) {
$value = str_replace(",", ".", trim($value));
if (is_numeric($value)) return floatval($value);
throw new ValueException("une valeur numérique flottante est attendue");
}
/**
* @var ScalarResult $result
* @var ScalarSchema $schema
*/
function verifix(&$value, Result &$result, Schema $schema): bool {
function verifix(&$value, Result $result, Schema $schema): bool {
if (is_float($value)) {
$result->setNormalized();
return false;
} elseif (is_string($value)) {
$float = trim($value);
if (is_numeric($float)) $value = floatval($float);
else return $result->setInvalid($value, $schema);
} elseif (is_scalar($value)) {
$value = floatval($value);
$result->setValid();
return true;
} else {
return $result->setInvalid($value, $schema);
$result->setInvalid($value, $schema);
return false;
}
$result->setValid();
return true;
}
function format($value, $format=null): string {
if ($format !== null) return sprintf($format, $value);
else return strval($value);
}
}

View File

@ -1,19 +1,13 @@
<?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\Result;
use nur\sery\wip\schema\Schema;
class tint extends _tsimple {
static function get_params(?array $definition): ?array {
if ($definition === null) return null;
$format = $definition["format"] ?? null;
if ($format === null) return null;
return ["format" => $format];
}
class tint extends _tformatable {
static function ensure_int(&$int): void {
if (!is_int($int)) $int = intval($int);
}
@ -23,42 +17,38 @@ class tint extends _tsimple {
}
//const INT_PATTERN = '/^[-+]?[0-9]+(?:\.[0-9]*)?$/';
function isValid($value, ?bool &$normalized=null): bool {
$normalized = is_int($value);
if (is_string($value)) {
$value = str_replace(",", ".", trim($value));
$valid = is_numeric($value);
} else {
$valid = is_scalar($value);
}
return $valid;
return is_scalar($value);
}
function extract(string &$value): bool {
$value = trim($value);
return true;
}
function parse(string $value) {
$value = str_replace(",", ".", trim($value));
if (is_numeric($value)) return intval($value);
throw new ValueException("une valeur numérique entière est attendue");
}
/**
* @var ScalarResult $result
* @var ScalarSchema $schema
*/
function verifix(&$value, Result &$result, Schema $schema): bool {
function verifix(&$value, Result $result, Schema $schema): bool {
if (is_int($value)) {
$result->setNormalized();
return false;
} elseif (is_string($value)) {
$int = str_replace(",", ".", trim($value));
if (is_numeric($int)) $value = intval($int);
else return $result->setInvalid($value, $schema);
} elseif (is_scalar($value)) {
$value = intval($value);
$result->setValid();
return true;
} else {
return $result->setInvalid($value, $schema);
$result->setInvalid($value, $schema);
return false;
}
$result->setNormalized();
return true;
}
function format($value, $format=null): string {
$format ??= $this->params["format"] ?? null;
if ($format !== null) return sprintf($format, $value);
else return strval($value);
}
}

View File

@ -1,12 +1,16 @@
<?php
namespace nur\sery\wip\schema\types;
use nur\sery\wip\schema\_scalar\ScalarResult;
use nur\sery\wip\schema\_scalar\ScalarSchema;
use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Schema;
class tkey extends _tsimple {
static function ensure_key(&$key): void {
if (!is_string($key) && !is_int($key)) $key = strval($key);
if ($key === null) $key = "";
elseif ($key === false) $key = 0;
elseif (!is_string($key) && !is_int($key)) $key = strval($key);
}
static function ensure_nkey(&$key): void {
@ -18,9 +22,29 @@ class tkey extends _tsimple {
return is_scalar($value);
}
function verifix(&$value, Result &$result, Schema $schema): bool {
function parse(string $value) {
return $value;
}
/**
* @var ScalarResult $result
* @var ScalarSchema $schema
*/
function verifix(&$value, Result $result, Schema $schema): bool {
if (is_string($value) || is_int($value)) {
$result->setNormalized();
return false;
} elseif (is_scalar($value)) {
$value = strval($value);
$result->setValid();
return true;
} else {
$result->setInvalid($value, $schema);
return false;
}
}
function format($value, $format=null): string {
return strval($value);
}
}

View File

@ -1,17 +1,20 @@
<?php
namespace nur\sery\wip\schema\types;
use nur\sery\wip\schema\_scalar\ScalarResult;
use nur\sery\wip\schema\_scalar\ScalarSchema;
use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Schema;
class tpkey extends _tsimple {
static function ensure_pkey(&$pkey): void {
if (!is_string($pkey) && !is_int($pkey) && !is_array($pkey)) $pkey = strval($pkey);
if ($pkey === null) $pkey = "";
elseif ($pkey === false) $pkey = 0;
elseif (!is_string($pkey) && !is_int($pkey) && !is_array($pkey)) $pkey = strval($pkey);
if (is_array($pkey)) {
foreach ($pkey as &$key) {
tkey::ensure_key($key);
};
unset($key);
}; unset($key);
}
}
@ -24,9 +27,30 @@ class tpkey extends _tsimple {
return is_scalar($value) || is_array($value);
}
function verifix(&$value, Result &$result, Schema $schema): bool {
function parse(string $value) {
return $value;
}
/**
* @var ScalarResult $result
* @var ScalarSchema $schema
*/
function verifix(&$value, Result $result, Schema $schema): bool {
if (is_string($value) || is_int($value) || is_array($value)) {
$result->setNormalized();
return false;
} elseif (is_scalar($value)) {
$value = strval($value);
$result->setValid();
return true;
} else {
$result->setInvalid($value, $schema);
return false;
}
}
function format($value, $format=null): string {
if (is_array($value)) return implode(".", $value);
else return strval($value);
}
}

View File

@ -1,71 +1,50 @@
<?php
namespace nur\sery\wip\schema\types;
use nulib\str;
use nur\sery\wip\schema\_scalar\ScalarResult;
use nur\sery\wip\schema\_scalar\ScalarSchema;
use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Schema;
class trawstring extends _tsimple {
const TRIM = false;
class trawstring extends _tstring {
static function ensure_string(&$string): void {
if (!is_string($string)) $string = strval($string);
if (static::TRIM) $string = trim($string);
if (static::NORM_NL) $string = str::norm_nl($string);
}
static function ensure_nstring(&$string): void {
if ($string !== null) self::ensure_string($string);
}
function __construct(?array $params=null) {
parent::__construct($params);
$this->trim = boolval($this->params["trim"] ?? static::TRIM);
}
protected bool $trim;
function isNull($value): bool {
return $value === null;
}
protected function check_normalized(string $value, bool $trim): bool {
if ($trim && $value !== "") {
if (preg_match('/^\s+/', $value)) {
return false;
} elseif (preg_match('/\s+$/', $value)) {
return false;
}
}
return true;
}
function isValid($value, ?bool &$normalized=null): bool {
if (is_string($value)) {
$normalized = self::check_normalized($value, $this->trim);
$normalized = true;
return true;
}
return is_scalar($value);
}
function parse(string $value) {
return $value;
}
/**
* @var ScalarResult $result
* @var ScalarSchema $schema
*/
function verifix(&$value, Result &$result, Schema $schema): bool {
function verifix(&$value, Result $result, Schema $schema): bool {
if (is_string($value)) {
$normalized = false;
if ($this->trim) {
$orig = $value;
$value = trim($value);
$normalized = $value !== $orig;
}
$result->setNormalized();
return $normalized;
return false;
} elseif (is_scalar($value)) {
$value = strval($value);
if ($this->trim) $value = trim($value);
$result->setNormalized();
$result->setValid();
return true;
} else {
$result->setInvalid($value, $schema);

View File

@ -0,0 +1,7 @@
<?php
namespace nur\sery\wip\schema\types;
class ttext extends trawstring {
const TRIM = true;
const NORM_NL = true;
}

View File

@ -3,6 +3,7 @@ namespace nur\sery\wip\schema\_scalar;
use nulib\tests\TestCase;
use nulib\ValueException;
use nur\sery\wip\schema\input\Input;
class ScalarValueTest extends TestCase {
function checkValue(ScalarValue $value, $dest, bool $present, bool $available, bool $valid, bool $normalized): void {
@ -17,12 +18,10 @@ class ScalarValueTest extends TestCase {
$schema = new ScalarSchema("rawstring");
$value = $schema->newValue();
$string = null;
$value->reset($string, null, false);
$string = null; $value->reset($string, null, false);
$this->checkValue($value, null, true, true, false, false);
self::assertException(ValueException::class, function() use (&$value) {
$string = null;
$value->reset($string);
$string = null; $value->reset($string);
});
$string = ""; $value->reset($string, null, false);
@ -53,12 +52,12 @@ class ScalarValueTest extends TestCase {
$string = true; $value->reset($string, null, false);
$this->checkValue($value, true, true, true, true, false);
$string = true; $value->reset($string);
$this->checkValue($value, "1", true, true, true, true);
$this->checkValue($value, "1", true, true, true, false);
$string = 42; $value->reset($string, null, false);
$this->checkValue($value, 42, true, true, true, false);
$string = 42; $value->reset($string);
$this->checkValue($value, "42", true, true, true, true);
$this->checkValue($value, "42", true, true, true, false);
$string = []; $value->reset($string, null, false);
$this->checkValue($value, [], true, true, false, false);
@ -85,6 +84,42 @@ class ScalarValueTest extends TestCase {
self::assertException(ValueException::class, function() use (&$value) {
$string = false; $value->reset($string);
});
## Tester allow_empty === false
$schema = new ScalarSchema("rawstring");
$value = $schema->newValue();
$string = null; $input = new Input($string, ["allow_empty" => false]);
$value->reset($input, null, false);
$this->checkValue($value, null, true, true, false, false);
self::assertException(ValueException::class, function() use (&$value) {
$string = null; $input = new Input($string, ["allow_empty" => false]);
$value->reset($input);
});
$string = ""; $input = new Input($string, ["allow_empty" => false]);
$value->reset($input, null, false);
$this->checkValue($value, null, true, false, true, true);
$string = ""; $input = new Input($string, ["allow_empty" => false]);
$value->reset($input);
$this->checkValue($value, null, true, false, true, true);
$schema = new ScalarSchema("?rawstring");
$value = $schema->newValue();
$string = null; $input = new Input($string, ["allow_empty" => false]);
$value->reset($input, null, false);
$this->checkValue($value, null, true, true, true, true);
$string = null; $input = new Input($string, ["allow_empty" => false]);
$value->reset($input);
$this->checkValue($value, null, true, true, true, true);
$string = ""; $input = new Input($string, ["allow_empty" => false]);
$value->reset($input, null, false);
$this->checkValue($value, null, true, false, true, true);
$string = ""; $input = new Input($string, ["allow_empty" => false]);
$value->reset($input);
$this->checkValue($value, null, true, false, true, true);
}
function testString() {
@ -104,7 +139,7 @@ class ScalarValueTest extends TestCase {
$this->checkValue($value, "", true, true, true, true);
$string = " "; $value->reset($string, null, false);
$this->checkValue($value, " ", true, true, true, false);
$this->checkValue($value, "", true, true, true, false);
$string = " "; $value->reset($string);
$this->checkValue($value, "", true, true, true, true);
@ -114,7 +149,7 @@ class ScalarValueTest extends TestCase {
$this->checkValue($value, "text", true, true, true, true);
$string = " text "; $value->reset($string, null, false);
$this->checkValue($value, " text ", true, true, true, false);
$this->checkValue($value, "text", true, true, true, false);
$string = " text "; $value->reset($string);
$this->checkValue($value, "text", true, true, true, true);
@ -126,12 +161,12 @@ class ScalarValueTest extends TestCase {
$string = true; $value->reset($string, null, false);
$this->checkValue($value, true, true, true, true, false);
$string = true; $value->reset($string);
$this->checkValue($value, "1", true, true, true, true);
$this->checkValue($value, "1", true, true, true, false);
$string = 42; $value->reset($string, null, false);
$this->checkValue($value, 42, true, true, true, false);
$string = 42; $value->reset($string);
$this->checkValue($value, "42", true, true, true, true);
$this->checkValue($value, "42", true, true, true, false);
$string = []; $value->reset($string, null, false);
$this->checkValue($value, [], true, true, false, false);
@ -179,17 +214,22 @@ class ScalarValueTest extends TestCase {
$int = "42"; $value->reset($int, null, false);
$this->checkValue($value, "42", true, true, true, false);
$int = "42"; $value->reset($int);
$this->checkValue($value, 42, true, true, true, true);
$this->checkValue($value, 42, true, true, true, false);
$int = "42.5"; $value->reset($int, null, false);
$this->checkValue($value, "42.5", true, true, true, false);
$int = "42.5"; $value->reset($int);
$this->checkValue($value, 42, true, true, true, true);
$this->checkValue($value, 42, true, true, true, false);
$int = "42,5"; $value->reset($int, null, false);
$this->checkValue($value, "42,5", true, true, true, false);
$int = "42,5"; $value->reset($int);
$this->checkValue($value, 42, true, true, true, true);
$this->checkValue($value, 42, true, true, true, false);
$int = " 42 "; $value->reset($int, null, false);
$this->checkValue($value, "42", true, true, true, false);
$int = " 42 "; $value->reset($int);
$this->checkValue($value, 42, true, true, true, false);
$int = ""; $value->reset($int, null, false);
$this->checkValue($value, "", true, true, false, false);
@ -206,7 +246,7 @@ class ScalarValueTest extends TestCase {
});
$int = "text"; $value->reset($int, null, false);
$this->checkValue($value, "text", true, true, false, true);
$this->checkValue($value, "text", true, true, false, false);
self::assertException(ValueException::class, function() use (&$value) {
$int = "text";
$value->reset($int);
@ -220,7 +260,7 @@ class ScalarValueTest extends TestCase {
$int = true; $value->reset($int, null, false);
$this->checkValue($value, true, true, true, true, false);
$int = true; $value->reset($int);
$this->checkValue($value, 1, true, true, true, true);
$this->checkValue($value, 1, true, true, true, false);
$int = []; $value->reset($int, null, false);
$this->checkValue($value, [], true, true, false, false);