Compare commits

...

38 Commits

Author SHA1 Message Date
a045296629 modifs.mineures sans commentaires 2025-04-15 12:28:07 +04:00
68f5dc5209 modifs.mineures sans commentaires 2025-04-10 00:27:05 +04:00
f005692cd8 déplacer nur/sery/wip et nur/sery dans nulib 2025-04-04 06:35:07 +04:00
d844bd03ad modifs.mineures sans commentaires 2025-04-02 22:21:16 +04:00
c4e02d5bcf afficher la version de l'application 2025-04-02 18:06:51 +04:00
2a92a9a07e modifs.mineures sans commentaires 2025-03-28 16:17:12 +04:00
c274adb6e6 modifs.mineures sans commentaires 2025-03-28 15:38:57 +04:00
ff02ffdf4f modifs.mineures sans commentaires 2025-03-27 15:58:47 +04:00
9109e0fe39 modifs.mineures sans commentaires 2025-03-24 13:46:51 +04:00
fd1ebaf611 modifs.mineures sans commentaires 2025-03-23 08:19:20 +04:00
26817d2826 modifs.mineures sans commentaires 2025-03-23 08:06:40 +04:00
7257654753 modifs.mineures sans commentaires 2025-03-22 16:42:42 +04:00
e2bec38540 modifs.mineures sans commentaires 2025-03-21 07:45:22 +04:00
c2ec23be30 modifs.mineures sans commentaires 2025-03-20 09:57:07 +04:00
741a807420 modifs.mineures sans commentaires 2025-03-20 09:38:01 +04:00
e9f4826a94 modifs.mineures sans commentaires 2025-03-20 09:36:01 +04:00
fd9b3b29bc modifs.mineures sans commentaires 2025-03-20 08:41:31 +04:00
f37a53cfbd modifs.mineures sans commentaires 2025-03-20 08:01:50 +04:00
6e8245dbcb modifs.mineures sans commentaires 2025-03-19 20:34:46 +04:00
f4e252a6e0 modifs.mineures sans commentaires 2025-03-19 19:32:27 +04:00
19f6f9c9e1 modifs.mineures sans commentaires 2025-03-19 18:31:49 +04:00
baa770d969 modifs.mineures sans commentaires 2025-03-19 17:05:26 +04:00
c5bfa3940c modifs.mineures sans commentaires 2025-03-19 17:03:12 +04:00
39af99ffa4 modifs.mineures sans commentaires 2025-03-19 16:56:36 +04:00
1fc4e7637b modifs.mineures sans commentaires 2025-03-19 16:10:26 +04:00
ef7e8551aa modifs.mineures sans commentaires 2025-03-19 13:49:36 +04:00
9328aac9e9 modifs.mineures sans commentaires 2025-03-19 10:06:53 +04:00
62fc315b9e modifs.mineures sans commentaires 2025-03-19 08:37:17 +04:00
b9e91bd917 modifs.mineures sans commentaires 2025-03-19 07:18:41 +04:00
3608b02749 modifs.mineures sans commentaires 2025-03-19 06:38:19 +04:00
d148850c12 modifs.mineures sans commentaires 2025-03-18 17:37:55 +04:00
189c7aba68 modifs.mineures sans commentaires 2025-03-18 13:30:02 +04:00
91e6c0dcd2 modifs.mineures sans commentaires 2025-03-18 10:48:50 +04:00
bb311708d7 modifs.mineures sans commentaires 2025-03-18 10:43:43 +04:00
1feffb6c0f modifs.mineures sans commentaires 2025-03-18 10:35:28 +04:00
62987d576e <pman>Init changelog & version 0.4.1p82 2025-03-17 17:24:49 +04:00
5decd631e2 <pman>deps de dev 2025-03-17 17:20:12 +04:00
c98afaa98c <pman>Intégration de la branche rel74-0.4.1 2025-03-17 17:20:07 +04:00
100 changed files with 2874 additions and 1689 deletions

6
.idea/nur-ture.iml generated
View File

@ -4,10 +4,8 @@
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/nur_src" isTestSource="false" packagePrefix="nur\" /> <sourceFolder url="file://$MODULE_DIR$/nur_src" isTestSource="false" packagePrefix="nur\" />
<sourceFolder url="file://$MODULE_DIR$/nur_tests" isTestSource="true" packagePrefix="nur\" /> <sourceFolder url="file://$MODULE_DIR$/nur_tests" isTestSource="true" packagePrefix="nur\" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="nur\sery\wip\" /> <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="nulib\" />
<sourceFolder url="file://$MODULE_DIR$/src_app" isTestSource="false" packagePrefix="nur\sery\" /> <sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="nulib\" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="nur\sery\" />
<sourceFolder url="file://$MODULE_DIR$/src_glue" isTestSource="false" packagePrefix="nulib\" />
<excludeFolder url="file://$MODULE_DIR$/vendor" /> <excludeFolder url="file://$MODULE_DIR$/vendor" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />

View File

@ -1,3 +1,5 @@
## Release 0.4.1p82 du 17/03/2025-17:23
## Release 0.4.1p74 du 17/03/2025-17:19 ## Release 0.4.1p74 du 17/03/2025-17:19
* `56fda96` changer le type de variables gérées par EnvConfig * `56fda96` changer le type de variables gérées par EnvConfig

View File

@ -3,6 +3,18 @@
"type": "library", "type": "library",
"description": "espace de maturation pour les librairies", "description": "espace de maturation pour les librairies",
"repositories": [ "repositories": [
{
"type": "path",
"url": "../nulib"
},
{
"type": "path",
"url": "../nulib-spout"
},
{
"type": "path",
"url": "../nulib-phpss"
},
{ {
"type": "composer", "type": "composer",
"url": "https://repos.univ-reunion.fr/composer" "url": "https://repos.univ-reunion.fr/composer"
@ -18,9 +30,9 @@
"php": "^7.4" "php": "^7.4"
}, },
"require-dev": { "require-dev": {
"nulib/php": "^0.4.0p74", "nulib/php": "^7.4-dev",
"nulib/spout": "^0.4.0p74", "nulib/spout": "^7.4-dev",
"nulib/phpss": "^0.4.0p74", "nulib/phpss": "^7.4-dev",
"nulib/tests": "^7.4", "nulib/tests": "^7.4",
"ext-posix": "*", "ext-posix": "*",
"ext-pcntl": "*", "ext-pcntl": "*",
@ -52,9 +64,7 @@
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"nulib\\": "src_glue", "nulib\\": "src",
"nur\\sery\\wip\\": "src",
"nur\\sery\\": "src_app",
"nur\\": "nur_src" "nur\\": "nur_src"
}, },
"files": [ "files": [
@ -63,7 +73,7 @@
}, },
"autoload-dev": { "autoload-dev": {
"psr-4": { "psr-4": {
"nur\\sery\\": "tests", "nulib\\": "tests",
"nur\\": "nur_tests" "nur\\": "nur_tests"
} }
}, },

56
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": "85c16d446d9a6899358782f7520bf3f6", "content-hash": "0b1e015d12aecf1cdfbdc6a702d83d25",
"packages": [], "packages": [],
"packages-dev": [ "packages-dev": [
{ {
@ -585,11 +585,11 @@
}, },
{ {
"name": "nulib/php", "name": "nulib/php",
"version": "0.4.0p74", "version": "dev-dev74",
"source": { "dist": {
"type": "git", "type": "path",
"url": "https://git.univ-reunion.fr/sda-php/nulib.git", "url": "../nulib",
"reference": "559feda663fc99f8baee2ba32f164b19bdd01927" "reference": "2a50167241fe6b6d84d793aad748eb74c631eae9"
}, },
"require": { "require": {
"ext-json": "*", "ext-json": "*",
@ -599,6 +599,8 @@
"require-dev": { "require-dev": {
"ext-curl": "*", "ext-curl": "*",
"ext-pcntl": "*", "ext-pcntl": "*",
"ext-pdo": "*",
"ext-pgsql": "*",
"ext-posix": "*", "ext-posix": "*",
"ext-sqlite3": "*", "ext-sqlite3": "*",
"nulib/tests": "^7.4" "nulib/tests": "^7.4"
@ -627,18 +629,20 @@
} }
], ],
"description": "fonctions et classes essentielles", "description": "fonctions et classes essentielles",
"time": "2025-03-14T11:23:41+00:00" "transport-options": {
"relative": true
}
}, },
{ {
"name": "nulib/phpss", "name": "nulib/phpss",
"version": "0.4.0p74", "version": "dev-dev74",
"source": { "dist": {
"type": "git", "type": "path",
"url": "https://git.univ-reunion.fr/sda-php/nulib-phpss.git", "url": "../nulib-phpss",
"reference": "1d8a88039f17242c72ff20cd01538b3fce8f8692" "reference": "e902acb4461a9358de8cce0a534bfe0e63e8b100"
}, },
"require": { "require": {
"nulib/php": "^0.4.0p74", "nulib/php": "^7.4-dev",
"php": "^7.4", "php": "^7.4",
"phpoffice/phpspreadsheet": "^1.0" "phpoffice/phpspreadsheet": "^1.0"
}, },
@ -669,15 +673,17 @@
} }
], ],
"description": "wrapper pour phpoffice/phpspreadsheet", "description": "wrapper pour phpoffice/phpspreadsheet",
"time": "2025-03-14T11:28:01+00:00" "transport-options": {
"relative": true
}
}, },
{ {
"name": "nulib/spout", "name": "nulib/spout",
"version": "0.4.0p74", "version": "dev-dev74",
"source": { "dist": {
"type": "git", "type": "path",
"url": "https://git.univ-reunion.fr/sda-php/nulib-spout.git", "url": "../nulib-spout",
"reference": "b5836e61961838c7f6d6735cdb671d47e05315e0" "reference": "8d7512e2bff3dc333bb58130ac5500017db700ca"
}, },
"require": { "require": {
"ext-dom": "*", "ext-dom": "*",
@ -685,7 +691,7 @@
"ext-libxml": "*", "ext-libxml": "*",
"ext-xmlreader": "*", "ext-xmlreader": "*",
"ext-zip": "*", "ext-zip": "*",
"nulib/php": "^0.4.0p74", "nulib/php": "^7.4-dev",
"php": "^7.4" "php": "^7.4"
}, },
"replace": { "replace": {
@ -723,7 +729,9 @@
} }
], ],
"description": "wrapper pour openspout/openspout", "description": "wrapper pour openspout/openspout",
"time": "2025-03-14T11:36:53+00:00" "transport-options": {
"relative": true
}
}, },
{ {
"name": "nulib/tests", "name": "nulib/tests",
@ -2937,7 +2945,11 @@
], ],
"aliases": [], "aliases": [],
"minimum-stability": "stable", "minimum-stability": "stable",
"stability-flags": [], "stability-flags": {
"nulib/php": 20,
"nulib/spout": 20,
"nulib/phpss": 20
},
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,
"platform": { "platform": {

View File

@ -2,6 +2,6 @@
<?php <?php
require $_composer_autoload_path?? __DIR__.'/../vendor/autoload.php'; require $_composer_autoload_path?? __DIR__.'/../vendor/autoload.php';
use nur\sery\tools\SteamTrainApp; use nulib\tools\SteamTrainApp;
SteamTrainApp::run(); SteamTrainApp::run();

View File

@ -2,6 +2,7 @@
namespace nur\cli; namespace nur\cli;
use Exception; use Exception;
use nulib\app;
use nulib\app\RunFile; use nulib\app\RunFile;
use nulib\ExitError; use nulib\ExitError;
use nulib\ext\yaml; use nulib\ext\yaml;
@ -16,7 +17,6 @@ use nur\config\ArrayConfig;
use nur\msg; use nur\msg;
use nur\os; use nur\os;
use nur\path; use nur\path;
use nur\sery\app;
/** /**
* Class Application: application de base * Class Application: application de base

View File

@ -105,7 +105,7 @@ class ref_type {
/** comme {@link c} mais nullable */ /** comme {@link c} mais nullable */
const NCONTENT = "?".self::CONTENT; const NCONTENT = "?".self::CONTENT;
/** comme {@link \nur\sery\FILE} mais nullable */ /** comme {@link FILE} mais nullable */
const NFILE = "?".self::FILE; const NFILE = "?".self::FILE;
/** comme {@link DATETIME} mais nullable */ /** comme {@link DATETIME} mais nullable */

View File

@ -32,6 +32,7 @@ class nb {
} }
static final function menu($text, ?array $links=null, ?array $options=null): array { static final function menu($text, ?array $links=null, ?array $options=null): array {
$links = array_filter($links, function($link) { return $link !== null; });
$item = ["item" => "menu", "links" => $links, "value" => $text]; $item = ["item" => "menu", "links" => $links, "value" => $text];
if ($options !== null) $item = array_merge($item, $options); if ($options !== null) $item = array_merge($item, $options);
return $item; return $item;

View File

@ -1,6 +1,7 @@
<?php <?php
namespace nur\v\vp; namespace nur\v\vp;
use nulib\app;
use nur\authz; use nur\authz;
use nur\b\authnz\IAuthzUser; use nur\b\authnz\IAuthzUser;
use nur\config; use nur\config;
@ -46,6 +47,21 @@ class NavigablePage extends AInitAuthzPage implements INavigablePage {
const MENU_SULOGIN = true; const MENU_SULOGIN = true;
protected function getAppVersionNbtext(): ?array {
$app = app::get();
$projdir = $app->getProjdir();
$versionfile = "$projdir/VERSION.txt";
if (file_exists($versionfile)) {
$name = $app->getName();
$version = file_get_contents($versionfile);
return nb::text([
"style" => "margin: 0 15px",
"$name v$version"
]);
}
return null;
}
protected function getAuthzNbtext(IAuthzUser $user): array { protected function getAuthzNbtext(IAuthzUser $user): array {
$username = $user->getUsername(); $username = $user->getUsername();
$role = $user->getRole(); $role = $user->getRole();
@ -95,6 +111,7 @@ class NavigablePage extends AInitAuthzPage implements INavigablePage {
$user = authz::get(); $user = authz::get();
navbar::nav(["align" => "right"], [ navbar::nav(["align" => "right"], [
nb::menu(icon::user($user->getShortName()), [ nb::menu(icon::user($user->getShortName()), [
$this->getAppVersionNbtext(),
$this->getAuthzNbtext($user), $this->getAuthzNbtext($user),
$this->getLogoutNblink(), $this->getLogoutNblink(),
]), ]),

View File

@ -2,7 +2,7 @@
require(__DIR__.'/../../vendor/autoload.php'); require(__DIR__.'/../../vendor/autoload.php');
use nur\cli\Application; use nur\cli\Application;
use nur\sery\output\msg; use nulib\output\msg;
class TestArgs4 extends Application { class TestArgs4 extends Application {
protected $query; protected $query;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery; namespace nulib;
use nulib\A; use nulib\A;
use nulib\app\LockFile; use nulib\app\LockFile;
@ -12,7 +12,7 @@ use nulib\php\func;
use nulib\str; use nulib\str;
use nulib\ValueException; use nulib\ValueException;
use nur\cli\Application as nur_Application; use nur\cli\Application as nur_Application;
use nur\sery\app\cli\Application; use nulib\app\cli\Application;
class app { class app {
private static function isa_Application($app): bool { private static function isa_Application($app): bool {

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\app\cli; namespace nulib\app\cli;
use Exception; use Exception;
use nulib\app\RunFile; use nulib\app\RunFile;
@ -13,7 +13,7 @@ use nulib\ValueException;
use nur\cli\ArgsException; use nur\cli\ArgsException;
use nur\cli\ArgsParser; use nur\cli\ArgsParser;
use nur\config; use nur\config;
use nur\sery\app; use nulib\app;
/** /**
* Class Application: application de base * Class Application: application de base

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\php\access; namespace nulib\php\access;
use nulib\cl; use nulib\cl;
@ -8,6 +8,18 @@ use nulib\cl;
* de {@link IAccess} * de {@link IAccess}
*/ */
abstract class AbstractAccess implements IAccess { abstract class AbstractAccess implements IAccess {
const ALLOW_EMPTY = true;
function __construct(?array $params=null) {
$this->allowEmpty = $params["allow_empty"] ?? static::ALLOW_EMPTY;
}
protected bool $allowEmpty;
function isAllowEmpty(): bool {
return $this->allowEmpty;
}
function inc(): int { function inc(): int {
$value = (int)$this->get(); $value = (int)$this->get();
$this->set(++$value); $this->set(++$value);
@ -33,4 +45,13 @@ abstract class AbstractAccess implements IAccess {
cl::set($array, $key, $value); cl::set($array, $key, $value);
$this->set($array); $this->set($array);
} }
function ensureAssoc(array $keys, ?array $params=null): void {
}
function ensureKeys(array $defaults, ?array $params=null): void {
}
function ensureOrder(array $keys, ?array $params=null): void {
}
} }

View File

@ -0,0 +1,8 @@
<?php
namespace nulib\php\access;
class ArrayAccess extends KeyAccess {
const ALLOW_NULL = true;
const ALLOW_FALSE = false;
const PROTECT_DEST = true;
}

View File

@ -0,0 +1,182 @@
<?php
namespace nulib\php\access;
use nulib\cl;
use nulib\StateException;
use ReflectionClass;
use ReflectionException;
class ChainAccess extends AbstractAccess {
const ACCESS_AUTO = 0, ACCESS_KEY = 1, ACCESS_PROPERTY = 2;
private static function unexpected_access_type(): StateException {
return StateException::unexpected_state("access_type");
}
function __construct(IAccess $access, $key, ?array $params=null) {
parent::__construct();
$this->access = $access;
$this->key = $key;
$this->accessType = $params["access_type"] ?? self::ACCESS_AUTO;
}
protected IAccess $access;
/** @var null|int|string|array */
protected $key;
protected int $accessType;
protected function _accessType($access, $key): int {
$accessType = $this->accessType;
if ($accessType === self::ACCESS_AUTO) {
if (is_object($access) && is_string($key)) {
$accessType = self::ACCESS_PROPERTY;
} else {
$accessType = self::ACCESS_KEY;
}
}
return $accessType;
}
protected function _has(): bool {
$src = $this->access->get();
$key = $this->key;
$accessType = $this->_accessType($src, $key);
if ($accessType === self::ACCESS_KEY) {
return cl::phas($src, $key);
} elseif ($accessType === self::ACCESS_PROPERTY) {
$class = new ReflectionClass($src);
return $class->hasProperty($key) || property_exists($src, $key);
} else {
throw self::unexpected_access_type();
}
}
protected function _get($default=null) {
$src = $this->access->get();
$key = $this->key;
$accessType = $this->_accessType($src, $key);
if ($accessType === self::ACCESS_KEY) {
return cl::pget($src, $key);
} elseif ($accessType === self::ACCESS_PROPERTY) {
$class = new ReflectionClass($src);
try {
$property = $class->getProperty($key);
$property->setAccessible(true);
} catch (ReflectionException $e) {
$property = null;
}
if ($property !== null) {
return $property->getValue($src);
} elseif (property_exists($src, $key)) {
return $src->$key;
} else {
return $default;
}
} else {
throw self::unexpected_access_type();
}
}
protected function _pset(object $dest, $name, $value): void {
$class = new ReflectionClass($dest);
try {
$property = $class->getProperty($name);
$property->setAccessible(true);
} catch (ReflectionException $e) {
$property = null;
}
if ($property !== null) {
$property->setValue($dest, $value);
} else {
$dest->$name = $value;
}
}
function isAllowEmpty(): bool {
return $this->access->isAllowEmpty();
}
function exists(): bool {
if (!$this->access->exists()) return false;
if ($this->key === null) return true;
return $this->_has();
}
function available(): bool {
if (!$this->access->available()) return false;
if ($this->key === null) return true;
if (!$this->_has()) return false;
return $this->isAllowEmpty() || $this->_get() !== "";
}
function get($default=null) {
if ($this->key === null) {
return $this->access->get($default);
}
return $this->_get($default);
}
function set($value): void {
if ($this->key === null) {
$this->access->set($value);
return;
}
$dest = $this->access->get();
$key = $this->key;
$accessType = $this->_accessType($dest, $key);
if ($accessType === self::ACCESS_KEY) {
cl::pset($dest, $key, $value);
$this->access->set($dest);
} elseif ($accessType === self::ACCESS_PROPERTY) {
$this->_pset($dest, $key, $value);
} else {
throw self::unexpected_access_type();
}
}
function del(): void {
if ($this->key === null) {
$this->access->del();
return;
}
$dest = $this->access->get();
$key = $this->key;
$accessType = $this->_accessType($dest, $key);
if ($accessType === self::ACCESS_KEY) {
cl::pdel($dest, $key);
$this->access->set($dest);
} elseif ($accessType === self::ACCESS_PROPERTY) {
$this->_pset($dest, $key, null);
} else {
throw self::unexpected_access_type();
}
}
function addKey($key, ?array $params=null): IAccess {
if ($key === null) return $this;
$accessType = $params["access_type"] ?? $this->accessType;
if ($accessType === self::ACCESS_KEY && $accessType === $this->accessType) {
if ($this->key !== null) $key = cl::merge($this->key, $key);
return new ChainAccess($this->access, $key);
} else {
return new ChainAccess($this, $key);
}
}
function ensureAssoc(array $keys, ?array $params=null): void {
#XXX fonction de $accessType?
#$this->access->ensureAssoc($keys, $params);
}
function ensureKeys(array $defaults, ?array $params=null): void {
#XXX fonction de $accessType?
#$this->access->ensureKeys($defaults, $params);
}
function ensureOrder(array $keys, ?array $params=null): void {
#XXX fonction de $accessType?
#$this->access->ensureOrder($keys, $params);
}
}

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\php\access; namespace nulib\php\access;
use nulib\cl; use nulib\cl;
@ -7,67 +7,99 @@ use nulib\cl;
* Class FormAccess: accès à une valeur de $_POST puis $_GET, dans cet ordre * Class FormAccess: accès à une valeur de $_POST puis $_GET, dans cet ordre
*/ */
class FormAccess extends AbstractAccess { class FormAccess extends AbstractAccess {
const ALLOW_EMPTY = false;
function __construct($key, ?array $params=null) { function __construct($key, ?array $params=null) {
parent::__construct($params);
$this->key = $key; $this->key = $key;
$this->allowEmpty = $params["allow_empty"] ?? false;
} }
/** @var int|string */ /** @var null|int|string|array */
protected $key; protected $key;
protected bool $allowEmpty; protected function _exists(array $first, ?array $second=null): bool {
function exists(): bool {
$key = $this->key; $key = $this->key;
if ($key === null) return false; if ($key === null) return true;
return array_key_exists($key, $_POST) || array_key_exists($key, $_GET); if (cl::phas($first, $key)) return true;
return $second !== null && cl::phas($second, $key);
} }
public function available(): bool { function exists(): bool {
return $this->_exists($_POST, $_GET);
}
protected function _available(array $first, ?array $second=null): bool {
$key = $this->key; $key = $this->key;
if ($key === null) return false; if ($key === null) return true;
if (array_key_exists($key, $_POST)) { if (cl::phas($first, $key)) {
return $this->allowEmpty || $_POST[$key] !== ""; return $this->allowEmpty || cl::pget($first, $key) !== "";
} elseif (array_key_exists($key, $_GET)) { } elseif ($second !== null && cl::phas($second, $key)) {
return $this->allowEmpty || $_GET[$key] !== ""; return $this->allowEmpty || cl::pget($second, $key) !== "";
} else { } else {
return false; return false;
} }
} }
function get($default=null) { public function available(): bool {
return $this->_available($_POST, $_GET);
}
protected function _get($default, array $first, ?array $second=null) {
$key = $this->key; $key = $this->key;
if ($key === null) return $default; if ($key === null) return cl::merge($first, $second);
if (array_key_exists($key, $_POST)) { if (cl::phas($first, $key)) {
$value = $_POST[$key]; $value = cl::pget($first, $key);
if ($value === "" && !$this->allowEmpty) return $default; if ($value !== "" || $this->allowEmpty) return $value;
return $value; } elseif ($second !== null && cl::phas($second, $key)) {
} elseif (array_key_exists($key, $_GET)) { $value = cl::pget($second, $key);
$value = $_GET[$key]; if ($value !== "" || $this->allowEmpty) return $value;
if ($value === "" && !$this->allowEmpty) return $default; }
return $value; return $default;
}
function get($default=null) {
return $this->_get($default, $_POST, $_GET);
}
function _set($value, array &$first, ?array &$second=null): void {
$key = $this->key;
if ($key === null) {
# interdire la modification de la destination
return;
}
if ($second !== null && !cl::phas($first, $key) && cl::phas($second, $key)) {
cl::pset($second, $key, $value);
} else { } else {
return $default; cl::pset($first, $key, $value);
} }
} }
function set($value): void { function set($value): void {
$this->_set($value, $_POST, $_GET);
}
function _del(array &$first, ?array &$second=null): void {
$key = $this->key; $key = $this->key;
if ($key === null) return; if ($key === null) {
if (!array_key_exists($key, $_POST) && array_key_exists($key, $_GET)) { # interdire la modification de la destination
cl::set($_GET, $key, $value); return;
}
if ($second !== null && !cl::phas($first, $key) && cl::phas($second, $key)) {
cl::pdel($second, $key);
} else { } else {
cl::set($_POST, $key, $value); cl::pdel($first, $key);
} }
} }
function del(): void { function del(): void {
$key = $this->key; $this->_del($_POST, $_GET);
if ($key === null) return; }
if (!array_key_exists($key, $_POST) && array_key_exists($key, $_GET)) {
cl::del($_GET, $key); function addKey($key): self {
} else { if ($key === null) return $this;
cl::del($_POST, $key); if ($this->key !== null) $key = cl::merge($this->key, $key);
} return new static($key, [
"allow_empty" => $this->allowEmpty
]);
} }
} }

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\php\access; namespace nulib\php\access;
use nulib\cl; use nulib\cl;
@ -8,42 +8,22 @@ use nulib\cl;
*/ */
class GetAccess extends FormAccess { class GetAccess extends FormAccess {
function exists(): bool { function exists(): bool {
$key = $this->key; return $this->_exists($_GET);
if ($key === null) return false;
return array_key_exists($key, $_GET);
} }
public function available(): bool { public function available(): bool {
$key = $this->key; return $this->_available($_GET);
if ($key === null) return false;
if (array_key_exists($key, $_GET)) {
return $this->allowEmpty || $_GET[$key] !== "";
} else {
return false;
}
} }
function get($default=null) { function get($default=null) {
$key = $this->key; return $this->_get($default, $_GET);
if ($key === null) return $default;
if (array_key_exists($key, $_GET)) {
$value = $_GET[$key];
if ($value === "" && !$this->allowEmpty) return $default;
return $value;
} else {
return $default;
}
} }
function set($value): void { function set($value): void {
$key = $this->key; $this->_set($value, $_GET);
if ($key === null) return;
cl::set($_GET, $key, $value);
} }
function del(): void { function del(): void {
$key = $this->key; $this->_del($_GET);
if ($key === null) return;
cl::del($_GET, $key);
} }
} }

View File

@ -1,5 +1,7 @@
<?php <?php
namespace nur\sery\wip\php\access; namespace nulib\php\access;
use ReflectionClass;
/** /**
* Interface IAccess: abstraction d'un accès complet à une valeur * Interface IAccess: abstraction d'un accès complet à une valeur
@ -25,4 +27,26 @@ interface IAccess extends IGetter, ISetter, IDeleter {
* tableau si $key===null * tableau si $key===null
*/ */
function append($value, $key=null): void; function append($value, $key=null): void;
/** retourner une instance permettant d'accéder à $value[$key] */
function addKey($key): IAccess;
/**
* s'assurer que la destination est un tableau associatif en remplaçant les
* clés numériques par les clés correspondantes du tableau $keys
*/
function ensureAssoc(array $keys, ?array $params=null): void;
/**
* s'assurer que toutes les clés mentionnées dans le tableau $defaults
* existent. si elles n'existent pas, leur donner la valeur du tableau
* $defaults
*/
function ensureKeys(array $defaults, ?array $params=null): void;
/**
* s'assure que les clés de la destination sont dans l'ordre mentionné dans le
* tableau $keys. toutes les clés supplémentaires sont placées à la fin
*/
function ensureOrder(array $keys, ?array $params=null): void;
} }

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\php\access; namespace nulib\php\access;
/** /**
* Class IDeleter: une abstraction d'un objet qui permet de supprimer une valeur * Class IDeleter: une abstraction d'un objet qui permet de supprimer une valeur

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\php\access; namespace nulib\php\access;
/** /**
* Class IGetter: une abstraction d'un objet qui permet d'obtenir une valeur * Class IGetter: une abstraction d'un objet qui permet d'obtenir une valeur
@ -11,6 +11,12 @@ interface IGetter {
*/ */
function exists(): bool; function exists(): bool;
/**
* @return bool true si cet objet autorise les chaines vides. si c'est le cas,
* {@link exists()} et {@link available()} sont fonctionnellement identiques
*/
function isAllowEmpty(): bool;
/** @return bool true si la valeur existe et est utilisable, false sinon */ /** @return bool true si la valeur existe et est utilisable, false sinon */
function available(): bool; function available(): bool;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\php\access; namespace nulib\php\access;
/** /**
* Class ISetter: une abstraction d'un objet qui permet de modifier une valeur * Class ISetter: une abstraction d'un objet qui permet de modifier une valeur

View File

@ -1,69 +1,188 @@
<?php <?php
namespace nur\sery\wip\php\access; namespace nulib\php\access;
use ArrayAccess; use ArrayAccess;
use nulib\cl; use nulib\cl;
use nulib\ref\schema\ref_schema;
/** /**
* Class KeyAccess: accès à une valeur d'une clé dans un tableau * Class KeyAccess: accès
* - soit à une valeur d'un chemin de clé dans un tableau (si $key !== null)
* - soit à une valeur scalaire (si $key === null)
*/ */
class KeyAccess extends AbstractAccess { class KeyAccess extends AbstractAccess {
function __construct(&$array, $key, ?array $params=null) { const ALLOW_NULL = null;
$this->array =& $array; const ALLOW_FALSE = null;
const PROTECT_DEST = false;
function __construct(&$dest, $key=null, ?array $params=null) {
parent::__construct($params);
$this->protectDest = $params["protect_dest"] ?? static::PROTECT_DEST;
$this->dest =& $dest;
$this->key = $key; $this->key = $key;
$this->allowNull = $params["allow_null"] ?? true; $this->allowNull = $params["allow_null"] ?? static::ALLOW_NULL;
$this->allowFalse = $params["allow_false"] ?? false; $this->allowFalse = $params["allow_false"] ?? static::ALLOW_FALSE;
$this->allowEmpty = $params["allow_empty"] ?? true;
} }
/** @var array|ArrayAccess */ protected bool $protectDest;
protected $array;
function reset(&$array): self { /** @var mixed|array|ArrayAccess */
$this->array =& $array; protected $dest;
/** @var null|int|string|array */
protected $key;
function reset(&$dest, $key=null): self {
$this->dest =& $dest;
$this->key = $key;
return $this; return $this;
} }
/** @var int|string */ function resetKey($key=null): self {
protected $key; $this->key = $key;
return $this;
}
protected bool $allowNull; protected ?bool $allowNull;
protected bool $allowFalse; protected function isAllowNull(): bool {
$allowNull = $this->allowNull;
if ($allowNull !== null) return $allowNull;
return $this->key !== null;
}
protected bool $allowEmpty; protected ?bool $allowFalse;
protected function isAllowFalse(): bool {
$allowFalse = $this->allowFalse;
if ($allowFalse !== null) return $allowFalse;
return $this->key === null;
}
function exists(): bool { function exists(): bool {
$key = $this->key; $key = $this->key;
if ($key === null) return false; if ($key === null) {
return cl::has($this->array, $key); return $this->isAllowNull() || $this->dest !== null;
} else {
return cl::phas($this->dest, $key);
}
} }
function available(): bool { function available(): bool {
if (!$this->exists()) return false; if (!$this->exists()) return false;
$value = cl::get($this->array, $this->key); $key = $this->key;
if ($value === null) return $this->allowNull; if ($key === null) $value = $this->dest;
if ($value === false) return $this->allowFalse; else $value = cl::pget($this->dest, $key);
if ($value === "") return $this->allowEmpty; if ($value === "") return $this->allowEmpty;
if ($value === null) return $this->isAllowNull();
if ($value === false) return $this->isAllowFalse();
return true; return true;
} }
function get($default=null) { function get($default=null) {
if ($this->key === null) return $default; $key = $this->key;
$value = cl::get($this->array, $this->key, $default); if ($key === null) $value = $this->dest;
if ($value === null && !$this->allowNull) return $default; else $value = cl::pget($this->dest, $key, $default);
if ($value === false && !$this->allowFalse) return $default;
if ($value === "" && !$this->allowEmpty) return $default; if ($value === "" && !$this->allowEmpty) return $default;
if ($value === null && !$this->isAllowNull()) return $default;
if ($value === false && !$this->isAllowFalse()) return $default;
return $value; return $value;
} }
function set($value): void { function set($value): void {
if ($this->key === null) return; $key = $this->key;
cl::set($this->array, $this->key, $value); if ($key === null) {
if (!$this->protectDest) $this->dest = $value;
} else {
cl::pset($this->dest, $key, $value);
}
} }
function del(): void { function del(): void {
if ($this->key === null) return; $key = $this->key;
cl::del($this->array, $this->key); if ($key === null) {
if (!$this->protectDest) $this->dest = null;
} else {
cl::pdel($this->dest, $key);
}
}
function addKey($key): self {
if ($key === null) return $this;
if ($this->key !== null) $key = cl::merge($this->key, $key);
return new KeyAccess($this->dest, $key, [
"allow_empty" => $this->allowEmpty,
"allow_null" => $this->allowNull,
"allow_false" => $this->allowFalse,
"protect_dest" => $this->protectDest,
]);
}
function ensureAssoc(array $keys, ?array $params=null): void {
$dest =& $this->dest;
$prefix = $params["key_prefix"] ?? null;
$suffix = $params["key_suffix"] ?? null;
$index = 0;
foreach ($keys as $key) {
if ($prefix !== null || $suffix !== null) {
$destKey = "$prefix$key$suffix";
} else {
# préserver les clés numériques
$destKey = $key;
}
if ($dest !== null && array_key_exists($destKey, $dest)) continue;
while (in_array($index, $keys, true)) {
$index++;
}
if ($dest !== null && array_key_exists($index, $dest)) {
$dest[$destKey] = $dest[$index];
unset($dest[$index]);
$index++;
}
}
}
function ensureKeys(array $defaults, ?array $params=null): void {
$dest =& $this->dest;
$keys = array_keys($defaults);
$prefix = $params["key_prefix"] ?? null;
$suffix = $params["key_suffix"] ?? null;
foreach ($keys as $key) {
$destKey = "$prefix$key$suffix";
if ($dest === null || !array_key_exists($destKey, $dest)) {
$dest[$destKey] = $defaults[$key];
}
}
}
function ensureOrder(array $keys, ?array $params=null): void {
$dest =& $this->dest;
if ($dest === null) return;
$prefix = $params["key_prefix"] ?? null;
$suffix = $params["key_suffix"] ?? null;
if ($prefix !== null || $suffix !== null) {
foreach ($keys as &$key) {
$key = "$prefix$key$suffix";
}; unset($key);
}
$destKeys = array_keys($dest);
$keyCount = count($keys);
if (array_slice($destKeys, 0, $keyCount) === $keys) {
# si le tableau a déjà les bonnes clés dans le bon ordre, rien à faire
return;
}
$ordered = [];
foreach ($keys as $key) {
if (array_key_exists($key, $dest)) {
$ordered[$key] = $dest[$key];
unset($dest[$key]);
}
}
$preserveKeys = $params["preserve_keys"] ?? false;
if ($preserveKeys) $dest = cl::merge2($ordered, $dest);
else $dest = array_merge($ordered, $dest);
} }
} }

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\php\access; namespace nulib\php\access;
use nulib\cl; use nulib\cl;
@ -8,42 +8,22 @@ use nulib\cl;
*/ */
class PostAccess extends FormAccess { class PostAccess extends FormAccess {
function exists(): bool { function exists(): bool {
$key = $this->key; return $this->_exists($_POST);
if ($key === null) return false;
return array_key_exists($key, $_POST);
} }
public function available(): bool { public function available(): bool {
$key = $this->key; return $this->_available($_POST);
if ($key === null) return false;
if (array_key_exists($key, $_POST)) {
return $this->allowEmpty || $_POST[$key] !== "";
} else {
return false;
}
} }
function get($default=null) { function get($default=null) {
$key = $this->key; return $this->_get($default, $_POST);
if ($key === null) return $default;
if (array_key_exists($key, $_POST)) {
$value = $_POST[$key];
if ($value === "" && !$this->allowEmpty) return $default;
return $value;
} else {
return $default;
}
} }
function set($value): void { function set($value): void {
$key = $this->key; $this->_set($value, $_POST);
if ($key === null) return;
cl::set($_POST, $key, $value);
} }
function del(): void { function del(): void {
$key = $this->key; $this->_del($_POST);
if ($key === null) return;
cl::del($_POST, $key);
} }
} }

View File

@ -0,0 +1,173 @@
<?php
namespace nulib\php\access;
use nulib\StateException;
use nulib\str;
use ReflectionClass;
use ReflectionException;
use ReflectionProperty;
class PropertyAccess extends AbstractAccess {
const PROTECT_DEST = true;
const MAP_NAMES = true;
const ALLOW_NULL = true;
const ALLOW_FALSE = false;
function __construct(?object $dest, ?string $name=null, ?array $params=null) {
parent::__construct($params);
$this->protectDest = $params["protect_dest"] ?? static::PROTECT_DEST;
$this->mapNames = $params["map_names"] ?? static::MAP_NAMES;
$this->_setName($name);
$this->_setDest($dest);
$this->allowNull = $params["allow_null"] ?? static::ALLOW_NULL;
$this->allowFalse = $params["allow_false"] ?? static::ALLOW_FALSE;
}
protected bool $protectDest;
protected ?object $dest;
protected bool $mapNames;
protected ?string $name;
protected ?ReflectionProperty $property;
private function _getName(string $key): string {
return $this->mapNames? str::us2camel($key): $key;
}
private function _setName(?string $name): void {
if ($name !== null) $name = $this->_getName($name);
$this->name = $name;
}
private function _getProperty(?string $name, ?ReflectionClass $class, ?object $object=null): ?ReflectionProperty {
$property = null;
if ($class === null && $object !== null) {
$class = new ReflectionClass($object);
}
if ($class !== null && $name !== null) {
try {
$property = $class->getProperty($name);
$property->setAccessible(true);
} catch (ReflectionException $e) {
}
}
return $property;
}
private function _setDest(?object $dest): void {
$this->dest = $dest;
$this->property = $this->_getProperty($this->name, null, $dest);
}
function reset(?object $dest, ?string $name=null): self {
$this->_setName($name);
$this->_setDest($dest);
return $this;
}
function resetKey($name=null): self {
$this->_setName($name);
return $this;
}
protected bool $allowNull;
protected bool $allowFalse;
function exists(): bool {
$name = $this->name;
if ($this->dest === null) return false;
return $name === null
|| $this->property !== null
|| property_exists($this->dest, $name);
}
protected function _get($default=null) {
$name = $this->name;
$property = $this->property;
if ($this->dest === null) {
return $default;
} elseif ($name === null) {
return $this->dest;
} elseif ($property !== null) {
return $property->getValue($this->dest);
} elseif (property_exists($this->dest, $name)) {
return $this->dest->$name;
} else {
return $default;
}
}
function available(): bool {
if (!$this->exists()) return false;
$value = $this->_get();
if ($value === "") return $this->allowEmpty;
if ($value === null) return $this->allowNull;
if ($value === false) return $this->allowFalse;
return true;
}
function get($default=null) {
if (!$this->exists()) return $default;
$value = $this->_get();
if ($value === "" && !$this->allowEmpty) return $default;
if ($value === null && !$this->allowNull) return $default;
if ($value === false && !$this->allowFalse) return $default;
return $value;
}
protected function _set($value): void {
$name = $this->name;
$property = $this->property;
if ($this->dest === null) {
throw StateException::unexpected_state("dest is null");
} elseif ($name === null) {
if (!$this->protectDest) $this->_setDest($value);
} elseif ($property !== null) {
$property->setValue($this->dest, $value);
} else {
$this->dest->$name = $value;
}
}
function set($value): void {
$this->_set($value);
}
function del(): void {
$this->_set(null);
}
function addKey($key): IAccess {
if ($key === null) return $this;
return new ChainAccess($this, $key);
}
function ensureKeys(array $defaults, ?array $params=null): void {
$dest = $this->dest;
if ($dest === null) {
# comme ne connait pas la classe de l'objet destination, on n'essaie pas
# de le créer
return;
}
$class = new ReflectionClass($dest);
$keys = array_keys($defaults);
$prefix = $params["key_prefix"] ?? null;
$suffix = $params["key_suffix"] ?? null;
foreach ($keys as $key) {
$name = $this->_getName("$prefix$key$suffix");
$property = $this->_getProperty($name, $class);
if ($property !== null) {
$type = $property->getType();
if ($type !== null && !$property->isInitialized($dest) && $type->allowsNull()) {
# initialiser avec null au lieu de $defaults[$key] pour respecter le
# type de la propriété
$property->setValue($dest, null);
}
} elseif (!property_exists($dest, $name)) {
$dest->$name = $defaults[$key];
}
}
}
}

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\php\access; namespace nulib\php\access;
/** /**
* Class ShadowAccess: accès en lecture depuis une instance de {@link IAccess} * Class ShadowAccess: accès en lecture depuis une instance de {@link IAccess}
@ -16,6 +16,7 @@ namespace nur\sery\wip\php\access;
*/ */
class ShadowAccess extends AbstractAccess { class ShadowAccess extends AbstractAccess {
function __construct(IAccess $reader, IAccess $writer) { function __construct(IAccess $reader, IAccess $writer) {
parent::__construct();
$this->reader = $reader; $this->reader = $reader;
$this->writer = $writer; $this->writer = $writer;
$this->getter = $reader; $this->getter = $reader;
@ -27,6 +28,10 @@ class ShadowAccess extends AbstractAccess {
protected IGetter $getter; protected IGetter $getter;
public function isAllowEmpty(): bool {
return $this->getter->isAllowEmpty();
}
function exists(): bool { function exists(): bool {
return $this->getter->exists(); return $this->getter->exists();
} }
@ -48,4 +53,20 @@ class ShadowAccess extends AbstractAccess {
$this->writer->del(); $this->writer->del();
$this->getter = $this->reader; $this->getter = $this->reader;
} }
function addKey($key): IAccess {
return new ChainAccess($this, $key);
}
function ensureAssoc(array $keys, ?array $params=null): void {
$this->writer->ensureAssoc($keys, $params);
}
function ensureKeys(array $defaults, ?array $params=null): void {
$this->writer->ensureKeys($defaults, $params);
}
function ensureOrder(array $keys, ?array $params=null): void {
$this->writer->ensureOrder($keys, $params);
}
} }

View File

@ -1,56 +1,8 @@
<?php <?php
namespace nur\sery\wip\php\access; namespace nulib\php\access;
/** class ValueAccess extends KeyAccess {
* Class ValueAccess: accès à une valeur unitaire const ALLOW_NULL = false;
*/ const ALLOW_FALSE = true;
class ValueAccess extends AbstractAccess { const PROTECT_DEST = false;
function __construct(&$value, ?array $params=null) {
$this->value =& $value;
$this->allowNull = $params["allow_null"] ?? false;
$this->allowFalse = $params["allow_false"] ?? true;
$this->allowEmpty = $params["allow_empty"] ?? true;
}
/** @var mixed */
protected $value;
function reset(&$value): self {
$this->value =& $value;
return $this;
}
protected bool $allowNull;
protected bool $allowFalse;
protected bool $allowEmpty;
function exists(): bool {
return $this->allowNull || $this->value !== null;
}
function available(): bool {
if (!$this->exists()) return false;
$value = $this->value;
if ($value === false) return $this->allowFalse;
if ($value === "") return $this->allowEmpty;
return true;
}
function get($default=null) {
$value = $this->value;
if ($value === null && !$this->allowNull) return $default;
if ($value === false && !$this->allowFalse) return $default;
if ($value === "" && !$this->allowEmpty) return $default;
return $value;
}
function set($value): void {
$this->value = $value;
}
function del(): void {
$this->value = null;
}
} }

View File

@ -1,11 +1,11 @@
<?php <?php
namespace nur\sery\wip\php\coll; namespace nulib\php\coll;
use Iterator; use Iterator;
use IteratorAggregate; use IteratorAggregate;
use nulib\cl; use nulib\cl;
use nulib\php\func; use nulib\php\func;
use nur\sery\wip\php\iter; use nulib\php\iter;
use Traversable; use Traversable;
/** /**

View File

@ -1,5 +1,5 @@
<?php # -*- coding: utf-8 mode: php -*- vim:sw=2:sts=2:et:ai:si:sta:fenc=utf-8 <?php # -*- coding: utf-8 mode: php -*- vim:sw=2:sts=2:et:ai:si:sta:fenc=utf-8
namespace nur\sery\wip\php; namespace nulib\php;
use Exception; use Exception;
use Generator; use Generator;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\schema; namespace nulib\schema;
class OldSchema { class OldSchema {
/** /**

View File

@ -1,10 +1,8 @@
<?php <?php
namespace nur\sery\wip\schema; namespace nulib\schema;
use IteratorAggregate; use IteratorAggregate;
use nur\sery\wip\schema\_assoc\AssocResult; use Throwable;
use nur\sery\wip\schema\_list\ListResult;
use nur\sery\wip\schema\_scalar\ScalarResult;
/** /**
* Class Result: résultat de l'analyse ou de la normalisation d'une valeur * Class Result: résultat de l'analyse ou de la normalisation d'une valeur
@ -17,6 +15,8 @@ use nur\sery\wip\schema\_scalar\ScalarResult;
* @property bool $normalized si la valeur est valide, est-elle normalisée? * @property bool $normalized si la valeur est valide, est-elle normalisée?
* @property string|null $messageKey clé de message si la valeur n'est pas valide * @property string|null $messageKey clé de message si la valeur n'est pas valide
* @property string|null $message message si la valeur n'est pas valide * @property string|null $message message si la valeur n'est pas valide
* @property Throwable|null $exception l'exception qui a fait échouer la
* validation le cas échéant
* @property string|null $origValue valeur originale avant extraction et analyse * @property string|null $origValue valeur originale avant extraction et analyse
* @property mixed|null $normalizedValue la valeur normalisée si elle est * @property mixed|null $normalizedValue la valeur normalisée si elle est
* disponible, null sinon. ce champ est utilisé comme optimisation si la valeur * disponible, null sinon. ce champ est utilisé comme optimisation si la valeur
@ -26,7 +26,7 @@ abstract class Result implements IteratorAggregate {
const KEYS = [ const KEYS = [
"resultAvailable", "resultAvailable",
"present", "available", "null", "valid", "normalized", "present", "available", "null", "valid", "normalized",
"messageKey", "message", "messageKey", "message", "exception",
"origValue", "normalizedValue", "origValue", "normalizedValue",
]; ];
@ -34,10 +34,6 @@ abstract class Result implements IteratorAggregate {
$this->reset(); $this->reset();
} }
function isAssoc(?AssocResult &$result=null): bool { return false; }
function isList(?ListResult &$result=null): bool { return false; }
function isScalar(?ScalarResult &$result=null): bool { return false; }
/** /**
* Obtenir la liste des clés valides pour les valeurs accessibles via cet * Obtenir la liste des clés valides pour les valeurs accessibles via cet
* objet * objet

View File

@ -1,22 +1,45 @@
<?php <?php
namespace nur\sery\wip\schema; namespace nulib\schema;
use ArrayAccess; use ArrayAccess;
use nulib\AccessException; use nulib\AccessException;
use nulib\cl; use nulib\cl;
use nulib\ref\schema\ref_schema; use nulib\ref\schema\ref_schema;
use nulib\ref\schema\ref_types; use nulib\ref\schema\ref_types;
use nur\sery\wip\schema\_assoc\AssocSchema; use nulib\schema\_assoc\AssocSchema;
use nur\sery\wip\schema\_list\ListSchema; use nulib\schema\_list\ListSchema;
use nur\sery\wip\schema\_scalar\ScalarSchema; use nulib\schema\_scalar\ScalarSchema;
use nur\sery\wip\schema\types\IType; use nulib\schema\types\IType;
use nur\sery\wip\schema\types\tarray; use nulib\schema\types\tarray;
use nur\sery\wip\schema\types\tbool; use nulib\schema\types\tbool;
use nur\sery\wip\schema\types\tcallable; use nulib\schema\types\tfunc;
use nur\sery\wip\schema\types\tcontent; use nulib\schema\types\tcontent;
use nur\sery\wip\schema\types\tpkey; use nulib\schema\types\tpkey;
use nur\sery\wip\schema\types\trawstring; use nulib\schema\types\trawstring;
/**
* Class Schema
*
* @property-read array|IType $type
* @property-read mixed $default
* @property-read string|null $title
* @property-read bool $required
* @property-read bool $nullable
* @property-read string|array|null $desc
* @property-read callable|null $analyzerFunc
* @property-read callable|null $extractorFunc
* @property-read callable|null $parserFunc
* @property-read callable|null $normalizerFunc
* @property-read array|null $messages
* @property-read callable|null $formatterFunc
* @property-read mixed $format
* @property-read array $nature
* @property-read array|null $schema
* @property-read string|int|null $name
* @property-read string|array|null $pkey
* @property-read string|null $header
* @property-read bool|null $computed
*/
abstract class Schema implements ArrayAccess { abstract class Schema implements ArrayAccess {
/** /**
* créer le cas échéant une nouvelle instance de {@link Schema} à partir d'une * créer le cas échéant une nouvelle instance de {@link Schema} à partir d'une
@ -27,7 +50,7 @@ abstract class Schema implements ArrayAccess {
* l'instance de Schema nouvelle créée * l'instance de Schema nouvelle créée
* - sinon, prendre $definition comme définition * - sinon, prendre $definition comme définition
*/ */
static function ns(&$schema, $definition=null, $definitionKey=null, bool $normalize=true): self { static function ns($definition=null, $definitionKey=null, &$schema=null, bool $normalize=true): self {
if (is_array($schema)) { if (is_array($schema)) {
$definition = $schema; $definition = $schema;
$schema = null; $schema = null;
@ -51,13 +74,13 @@ abstract class Schema implements ArrayAccess {
* variable $value (si $valueKey===null) ou $value[$valueKey] si $valueKey * variable $value (si $valueKey===null) ou $value[$valueKey] si $valueKey
* n'est pas null * n'est pas null
*/ */
static function nw(&$value=null, $valueKey=null, &$schema=null, $definition=null, ?Wrapper &$wrapper=null): Wrapper { static function nw(&$value=null, $valueKey=null, $definition=null, &$schema=null, ?Wrapper &$wrapper=null): Wrapper {
if ($definition === null) { if ($definition === null) {
# bien que techniquement, $definition peut être null (il s'agit alors du # bien que techniquement, $definition peut être null (il s'agit alors du
# schéma d'un scalaire quelconque), on ne l'autorise pas ici # schéma d'un scalaire quelconque), on ne l'autorise pas ici
throw SchemaException::invalid_schema("definition is required"); throw SchemaException::invalid_schema("definition is required");
} }
return self::ns($schema, $definition)->getWrapper($value, $valueKey, $wrapper); return self::ns($definition, null, $schema)->getWrapper($value, $valueKey, null, $wrapper);
} }
protected static function have_nature(array $definition, ?string &$nature=null): bool { protected static function have_nature(array $definition, ?string &$nature=null): bool {
@ -75,18 +98,18 @@ abstract class Schema implements ArrayAccess {
return false; return false;
} }
protected static function _normalize(&$definition, $definitionKey=null): void { protected static function _normalize_definition(&$definition, $definitionKey=null, ?array $natureMetaschema=null): void {
if (!is_array($definition)) $definition = [$definition]; if (!is_array($definition)) $definition = [$definition];
# s'assurer que toutes les clés existent avec leur valeur par défaut # s'assurer que toutes les clés existent avec leur valeur par défaut
$index = 0; $index = 0;
foreach (array_keys(ref_schema::SCALAR_METASCHEMA) as $key) { foreach (array_keys(ref_schema::VALUE_METASCHEMA) as $key) {
if (!array_key_exists($key, $definition)) { if (!array_key_exists($key, $definition)) {
if (array_key_exists($index, $definition)) { if (array_key_exists($index, $definition)) {
$definition[$key] = $definition[$index]; $definition[$key] = $definition[$index];
unset($definition[$index]); unset($definition[$index]);
$index++; $index++;
} else { } else {
$definition[$key] = ref_schema::SCALAR_METASCHEMA[$key][1]; $definition[$key] = ref_schema::VALUE_METASCHEMA[$key][1];
} }
} }
} }
@ -138,6 +161,12 @@ abstract class Schema implements ArrayAccess {
# nature # nature
$nature = $definition[""]; $nature = $definition[""];
tarray::ensure_array($nature); tarray::ensure_array($nature);
$natureMetaschema ??= ref_schema::NATURE_METASCHEMA;
foreach (array_keys($natureMetaschema) as $key) {
if (!array_key_exists($key, $nature)) {
$nature[$key] = $natureMetaschema[$key][1];
}
}
$definition[""] = $nature; $definition[""] = $nature;
# name, pkey, header # name, pkey, header
$name = $definition["name"]; $name = $definition["name"];
@ -158,22 +187,22 @@ abstract class Schema implements ArrayAccess {
tbool::ensure_bool($definition["required"]); tbool::ensure_bool($definition["required"]);
tbool::ensure_bool($definition["nullable"]); tbool::ensure_bool($definition["nullable"]);
tcontent::ensure_ncontent($definition["desc"]); tcontent::ensure_ncontent($definition["desc"]);
tcallable::ensure_ncallable($definition["analyzer_func"]); tfunc::ensure_nfunc($definition["analyzer_func"]);
tcallable::ensure_ncallable($definition["extractor_func"]); tfunc::ensure_nfunc($definition["extractor_func"]);
tcallable::ensure_ncallable($definition["parser_func"]); tfunc::ensure_nfunc($definition["parser_func"]);
tcallable::ensure_ncallable($definition["normalizer_func"]); tfunc::ensure_nfunc($definition["normalizer_func"]);
tarray::ensure_narray($definition["messages"]); tarray::ensure_narray($definition["messages"]);
tcallable::ensure_ncallable($definition["formatter_func"]); tfunc::ensure_nfunc($definition["formatter_func"]);
tbool::ensure_nbool($definition["computed"]); tbool::ensure_nbool($definition["computed"]);
switch ($nature[0] ?? null) { switch ($nature[0] ?? null) {
case "assoc": case "assoc":
foreach ($definition["schema"] as $key => &$keydef) { foreach ($definition["schema"] as $key => &$keydef) {
self::_normalize($keydef, $key); self::_normalize_definition($keydef, $key);
}; unset($keydef); }; unset($keydef);
break; break;
case "list": case "list":
self::_normalize($definition["schema"]); self::_normalize_definition($definition["schema"]);
break; break;
} }
} }
@ -223,11 +252,11 @@ abstract class Schema implements ArrayAccess {
case "assoc": case "assoc":
foreach ($definition["schema"] as &$keydef) { foreach ($definition["schema"] as &$keydef) {
self::_ensure_schema_instances($keydef); self::_ensure_schema_instances($keydef);
Schema::ns($keydef, null, null, false); Schema::ns(null, null, $keydef, false);
}; unset($keydef); }; unset($keydef);
break; break;
case "list": case "list":
Schema::ns($definition["schema"], null, null, false); Schema::ns(null, null, $definition["schema"], false);
break; break;
} }
} }
@ -246,14 +275,16 @@ abstract class Schema implements ArrayAccess {
return $this->_definition; return $this->_definition;
} }
/** retourner true si le schéma est de nature tableau associatif */ /**
function isAssoc(?AssocSchema &$schema=null): bool { return false; } * retourner la liste des clés valides pour l'accès aux valeurs et résultats
/** retourner true si le schéma est de nature liste */ */
function isList(?ListSchema &$schema=null): bool { return false; } abstract function getKeys(): array;
/** retourner true si le schéma est de nature scalaire */
function isScalar(?ScalarSchema &$schema=null): bool { return false; }
abstract function getWrapper(&$value=null, $valueKey=null, ?Wrapper &$wrapper=null): Wrapper; abstract function getSchema($key=false): Schema;
abstract protected function newWrapper(): Wrapper;
abstract function getWrapper(&$value=null, $valueKey=null, ?array $params=null, ?Wrapper &$wrapper=null): Wrapper;
############################################################################# #############################################################################
# key & properties # key & properties
@ -272,7 +303,15 @@ abstract class Schema implements ArrayAccess {
throw AccessException::read_only(null, $offset); throw AccessException::read_only(null, $offset);
} }
const _PROPERTY_PKEYS = []; const _PROPERTY_PKEYS = [
"analyzerFunc" => "analyzer_func",
"extractorFunc" => "extractor_func",
"parserFunc" => "parser_func",
"normalizerFunc" => "normalizer_func",
"formatterFunc" => "formatter_func",
"nature" => ["", 0],
];
function __get($name) { function __get($name) {
$pkey = cl::get(static::_PROPERTY_PKEYS, $name, $name); $pkey = cl::get(static::_PROPERTY_PKEYS, $name, $name);
return cl::pget($this->definition, $pkey); return cl::pget($this->definition, $pkey);

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\schema; namespace nulib\schema;
use Exception; use Exception;

View File

@ -1,20 +1,38 @@
# nulib\schema # nulib\schema
* instance de WrapperContext directement dans le schéma * l'ordre est `ensureAssoc [--> ensureKeys] [--> orderKeys]`
* plus de {key} ni {orig} dans messages * si false, supprimer la clé du tableau sauf si ensureKeys
* les messages standard ne sont utilisés que s'il n'y a pas de message dans
l'exception * pour AssocResult, les clés suivantes sont supportées:
* si instance de UserException, prendre le message "non technique" pour * false pour la clé courante
résultat * null pour un résultat aggrégé
* "" pour le résultat du tableau
* $key pour le résultat de la clé correspondante
* rajouter l'attribut "size" pour spécifier la taille maximale des valeurs
* cela pourrait servir pour générer automatiquement des tables SQL
* ou pour modéliser un schéma FSV
* support allowed_values
* valeurs composite/computed * valeurs composite/computed
* analyse / vérification de la valeur complète après calcul du résultat, si * analyse / vérification de la valeur complète après calcul du résultat, si
tous les résultats sont bons tous les résultats sont bons
* calcul des valeurs composites/computed par une fonction avant/après l'analyse * calcul des valeurs composites/computed par une fonction avant/après l'analyse
globale si résultat ok globale si résultat ok
* fonction getter_func, setter_func, deleter_func pour les propriétés de type
computed
* 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 * parse_format pour spécifier le format d'analyse au lieu de l'auto-détecter
* ScalarSchema::from_property() * ScalarSchema::from_property()
* l'argument $format de AssocWrapper::format() est un tableau associatif
`[$key => $format]`
cela permet de spécifier des format spécifiques pour certains champs.
* cela signifie que la valeur de retour n'est pas string :-(
retourner string|array
* 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
~~~php ~~~php
@ -58,6 +76,8 @@
la définition de ces "circonstances" est encore à faire: soit un paramètre la définition de ces "circonstances" est encore à faire: soit un paramètre
lors de la définition du schéma, soit un truc magique du genre "toutes les lors de la définition du schéma, soit un truc magique du genre "toutes les
valeurs séquentielles sont des clés du schéma" valeurs séquentielles sont des clés du schéma", soit un mode automatique
activé par un paramètre où une valeur "val" devient "val"=>true si la clé
"val" existe dans le schéma
-*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary -*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary

View File

@ -1,20 +1,107 @@
<?php <?php
namespace nur\sery\wip\schema; namespace nulib\schema;
use ArrayAccess; use ArrayAccess;
use IteratorAggregate; use IteratorAggregate;
use nur\sery\wip\schema\_assoc\AssocWrapper; use nulib\php\func;
use nur\sery\wip\schema\_list\ListWrapper; use nulib\schema\_assoc\AssocWrapper;
use nur\sery\wip\schema\_scalar\ScalarWrapper; use nulib\schema\_list\ListWrapper;
use nur\sery\wip\schema\types\IType; use nulib\schema\_scalar\ScalarResult;
use nulib\schema\_scalar\ScalarWrapper;
use nulib\schema\input\Input;
use nulib\schema\types\IType;
abstract class Wrapper implements ArrayAccess, IteratorAggregate { abstract class Wrapper implements ArrayAccess, IteratorAggregate {
function isAssoc(?AssocWrapper &$wrapper=null): bool { return false; } protected WrapperContext $context;
function isList(?ListWrapper &$wrapper=null): bool { return false; }
function isScalar(?ScalarWrapper &$wrapper=null): bool { return false; }
/** spécifier la valeur destination gérée par cet objet */ /** changer les paramètres de gestion des valeurs */
abstract function reset(&$value, $valueKey=null, ?bool $verifix=null): self; function resetParams(?array $params): void {
$this->context->resetParams($params);
}
protected function resetContext($resetSelectedKey): void {
$context = $this->context;
$type = $context->schema->type;
if (is_array($type)) $type = $type[0];
if (is_string($type)) $type = types::get($context->schema->nullable, $type);
$context->type = $type;
$context->result->reset();
$context->analyzed = false;
$context->normalized = false;
if ($resetSelectedKey) $context->selectedKey = null;
}
protected function afterModify(?array $params, $resetSelectedKey=false): void {
$context = $this->context;
$this->resetContext($resetSelectedKey);
if ($params["analyze"] ?? $context->analyze) {
$this->analyze($params);
}
if ($context->analyzed) {
if ($params["normalize"] ?? $context->normalize) {
$this->normalize($params);
}
}
}
protected function newInput(&$value): Input {
return new Input($value);
}
/**
* spécifier la valeur destination gérée par cet objet.
*
* @param ?array $params paramètres spécifique à cet appel, qui peuvent être
* différent des paramètres par défaut
*/
function reset(&$value, $valueKey=null, ?array $params=null): Wrapper {
$context = $this->context;
if ($value instanceof Input) $input = $value;
else $input = $this->newInput($value);
$context->input = $input;
$context->valueKey = $valueKey;
$this->afterModify($params, true);
return $this;
}
/** analyser la valeur */
abstract static function _analyze(WrapperContext $context, Wrapper $wrapper, ?array $params): int;
function analyze(?array $params=null): bool {
$context = $this->context;
$reanalyze = $params["reanalyze"] ?? false;
if ($context->analyzed && !$reanalyze) return false;
static::_analyze($context, $this, $params);
$context->analyzed = true;
return true;
}
/** normaliser la valeur */
abstract static function _normalize(WrapperContext $context, Wrapper $wrapper, ?array $params): bool;
function normalize(?array $params=null): bool {
$context = $this->context;
// il faut que la valeur soit analysée avant de la normaliser
static::analyze($params);
if (!$context->analyzed) return false;
$renormalize = $params["renormalize"] ?? false;
if ($renormalize || !$context->normalized) {
$modified = static::_normalize($context, $this, $params);
$context->normalized = true;
} else {
$modified = false;
}
/** @var ScalarResult $result */
$result = $context->result;
if (!$result->valid) {
$result->throw($params["throw"] ?? $context->throw);
}
return $modified;
}
/** /**
* Obtenir la liste des clés valides pour les valeurs accessibles via cet * Obtenir la liste des clés valides pour les valeurs accessibles via cet
@ -38,37 +125,80 @@ abstract class Wrapper implements ArrayAccess, IteratorAggregate {
} }
/** /**
* obtenir le résultat de l'appel d'une des fonctions {@link set()} ou * obtenir le résultat de l'analyse de la valeur du wrapper sélectionné
* {@link unset()} *
* cette fonction doit être appelée après {@link set()} ou {@link unset()} et
* après que le wrapper aie été sélectionné avec {@link select()}
*/ */
abstract function getResult(): Result; function getResult($key=false): Result {
return $this->context->result;
}
/** retourner true si la valeur existe */ /** retourner true si la valeur existe */
abstract function isPresent(): bool; function isPresent($key=false): bool {
return $this->getResult($key)->present;
}
/** retourner le type associé à la valeur */ /** retourner le type associé à la valeur */
abstract function getType(): IType; function getType($key=false): IType {
return $this->context->type;
}
/** retourner true si la valeur est disponible */ /** retourner true si la valeur est disponible */
abstract function isAvailable(): bool; function isAvailable($key=false): bool {
return $this->getResult($key)->available;
}
/** retourner true si la valeur est valide */ /** retourner true si la valeur est valide */
abstract function isValid(): bool; function isValid($key=false): bool {
return $this->getResult($key)->valid;
}
/** retourner true si la valeur est dans sa forme normalisée */ /** retourner true si la valeur est dans sa forme normalisée */
abstract function isNormalized(): bool; function isNormalized($key=false): bool {
return $this->getResult($key)->normalized;
}
/** obtenir la valeur */ function get($default=null, $key=false) {
abstract function get($default=null); $context = $this->context;
if (!$context->result->available) return $default;
return $context->input->get($context->valueKey);
}
/** remplacer la valeur */ function set($value, ?array $params=null, $key=false): self {
abstract function set($value): self; $context = $this->context;
$context->input->set($value, $context->valueKey);
$this->afterModify($params);
return $this;
}
/** supprimer la valeur */ function unset(?array $params=null, $key=false): self {
abstract function unset(): self; $context = $this->context;
$context->input->unset($context->valueKey);
$this->afterModify($params);
return $this;
}
protected function _format(WrapperContext $context, $format=null): string {
$value = $context->input->get($context->valueKey);
/** @var func $formatterFunc */
$formatterFunc = $context->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 ??= $context->schema->format;
return $formatterFunc->invoke([$value, $format, $context, $this]);
} else {
# on assume que le type a été initialisé avec le format de la définition
# le cas échéant
return $context->type->format($value, $format);
}
}
/** formatter la valeur pour affichage */ /** formatter la valeur pour affichage */
abstract function format($format=null): string; function format($format=null, $key=false): string {
return $this->_format($this->context, $format);
}
############################################################################# #############################################################################
# key & properties # key & properties
@ -78,14 +208,14 @@ abstract class Wrapper implements ArrayAccess, IteratorAggregate {
} }
function offsetGet($offset) { function offsetGet($offset) {
return $this->select($offset); return $this->get(null, $offset);
} }
function offsetSet($offset, $value): void { function offsetSet($offset, $value): void {
$this->select($offset)->set($value); $this->set($value, null, $offset);
} }
function offsetUnset($offset): void { function offsetUnset($offset): void {
$this->select($offset)->unset(); $this->unset(null, $offset);
} }
} }

View File

@ -1,30 +1,46 @@
<?php <?php
namespace nur\sery\wip\schema; namespace nulib\schema;
use nur\sery\wip\schema\input\Input; use nulib\ref\schema\ref_schema;
use nur\sery\wip\schema\types\IType; use nulib\schema\input\Input;
use nulib\schema\types\IType;
class WrapperContext { class WrapperContext {
function __construct(Schema $schema, Wrapper $wrapper, Input $input, $valueKey, Result $result) {
function __construct(Schema $schema, ?Input $input, $valueKey, ?array $params) {
$this->resetParams($params);
$this->schema = $schema; $this->schema = $schema;
$this->wrapper = $wrapper; if ($input !== null) $this->input = $input;
$this->input = $input;
$this->result = $result;
$this->type = null;
$this->origValue = null;
$this->value = null;
$this->valueKey = $valueKey; $this->valueKey = $valueKey;
} }
public ?array $params;
public bool $analyze, $analyzed = false;
public bool $normalize, $normalized = false;
public ?bool $throw;
function resetParams(?array $params): void {
$this->params = $params;
$this->analyze = $params["analyze"] ?? ref_schema::PARAMS_SCHEMA["analyze"][1];
$this->normalize = $params["normalize"] ?? ref_schema::PARAMS_SCHEMA["normalize"][1];
$this->throw = $params["throw"] ?? ref_schema::PARAMS_SCHEMA["throw"][1];
}
/** schéma de la valeur */
public Schema $schema; public Schema $schema;
public Wrapper $wrapper; /** source et destination de la valeur */
public Input $input; public Input $input;
public Result $result; /** @var string|int|null clé de la valeur dans le tableau destination */
public ?IType $type;
/** @var mixed */
public $origValue;
/** @var mixed */
public $value;
/** @var int|string|null */
public $valueKey; public $valueKey;
/** @var mixed */
public $origValue = null;
/** @var mixed */
public $value = null;
/** @var string|int|null clé sélectionnée */
public $selectedKey = null;
/** type de la valeur de la clé sélectionnée après analyse */
public ?IType $type = null;
/** résultat de l'analyse de la valeur de la clé sélectionnée */
public ?Result $result = null;
} }

View File

@ -1,53 +0,0 @@
<?php
namespace nur\sery\wip\schema\_assoc;
use nulib\ValueException;
use nur\sery\wip\schema\Result;
class AssocResult extends Result {
function __construct(Result $arrayResult, array &$keyResults) {
$this->arrayResult = $arrayResult;
$this->keyResults =& $keyResults;
$this->result =& $this->arrayResult;
parent::__construct();
}
function isAssoc(?AssocResult &$result=null): bool { $result = $this; return true;}
protected Result $arrayResult;
/** @var Result[] */
protected array $keyResults;
function getKeys(): array {
return array_keys($this->keyResults);
}
protected Result $result;
function select($key): Result {
if ($key === null) {
$this->result =& $this->arrayResult;
} elseif (array_key_exists($key, $this->keyResults)) {
$this->result =& $this->keyResults[$key];
} else {
throw ValueException::invalid_key($key);
}
return $this;
}
function reset(): void {
$this->arrayResult->reset();
foreach ($this->keyResults as $result) {
$result->reset();
}
}
function __get(string $name) {
return $this->result[$name];
}
function __set(string $name, $value): void {
$this->result[$name] = $value;
}
}

View File

@ -1,21 +1,19 @@
<?php <?php
namespace nur\sery\wip\schema\_assoc; namespace nulib\schema\_assoc;
use nulib\cl; use nulib\cl;
use nulib\ref\schema\ref_schema; use nulib\ref\schema\ref_schema;
use nur\sery\wip\schema\Schema; use nulib\ValueException;
use nur\sery\wip\schema\Wrapper; use nulib\schema\Schema;
use nulib\schema\Wrapper;
/** /**
* Class AssocSchema * Class AssocSchema
*/ */
class AssocSchema extends Schema { class AssocSchema extends Schema {
/** @var array meta-schema d'un schéma de nature tableau associatif */
const METASCHEMA = ref_schema::ASSOC_METASCHEMA;
/** /**
* indiquer si $definition est une définition de schéma de nature tableau * indiquer si $definition est une définition de schéma de nature tableau
* associatif que {@link normalize()} pourrait normaliser * associatif que {@link normalize_definition()} pourrait normaliser
*/ */
static function isa_definition($definition): bool { static function isa_definition($definition): bool {
if (!is_array($definition)) return false; if (!is_array($definition)) return false;
@ -27,7 +25,7 @@ class AssocSchema extends Schema {
return !cl::have_num_keys($definition); return !cl::have_num_keys($definition);
} }
static function normalize($definition, $definitionKey=null): array { static function normalize_definition($definition, $definitionKey=null): array {
if (!is_array($definition)) $definition = [$definition]; if (!is_array($definition)) $definition = [$definition];
if (!self::have_nature($definition)) { if (!self::have_nature($definition)) {
$definition = [ $definition = [
@ -36,7 +34,8 @@ class AssocSchema extends Schema {
"schema" => $definition, "schema" => $definition,
]; ];
} }
self::_normalize($definition, $definitionKey); $natureMetaschema = array_merge(ref_schema::NATURE_METASCHEMA, ref_schema::ASSOC_NATURE_METASCHEMA);
self::_normalize_definition($definition, $definitionKey, $natureMetaschema);
self::_ensure_nature($definition, "assoc", "array"); self::_ensure_nature($definition, "assoc", "array");
return $definition; return $definition;
} }
@ -44,25 +43,54 @@ class AssocSchema extends Schema {
function __construct($definition=null, $definitionKey=null, bool $normalize=true) { function __construct($definition=null, $definitionKey=null, bool $normalize=true) {
if ($definition === null) $definition = static::SCHEMA; if ($definition === null) $definition = static::SCHEMA;
if ($normalize) { if ($normalize) {
$definition = self::normalize($definition, $definitionKey); $definition = self::normalize_definition($definition, $definitionKey);
$this->_definition = $definition; $this->_definition = $definition;
self::_ensure_type($definition); self::_ensure_type($definition);
self::_ensure_schema_instances($definition); self::_ensure_schema_instances($definition);
} else {
# ici, $definition contient un schema déjà instancié, mais c'est le mieux
# qu'on puisse faire
$this->_definition = $definition;
} }
$this->definition = $definition; $this->definition = $definition;
$keys = [];
foreach ($definition["schema"] as $key => $schema) {
if (!$schema["computed"]) $keys[] = $key;
}
$this->keys = $keys;
} }
function isAssoc(?AssocSchema &$schema=null): bool { protected array $keys;
$schema = $this;
return true; function getKeys(): array {
return $this->keys;
}
function getSchema($key=false): Schema {
if ($key === null || $key === false) return $this;
$schema = $this->definition["schema"][$key] ?? null;
if ($schema === null) throw ValueException::invalid_key($key);
return $schema;
} }
protected function newWrapper(): AssocWrapper { protected function newWrapper(): AssocWrapper {
return new AssocWrapper($this); return new AssocWrapper($this);
} }
function getWrapper(&$array=null, $arrayKey=null, ?Wrapper &$wrapper=null): AssocWrapper { function getWrapper(&$value=null, $valueKey=null, ?array $params=null, ?Wrapper &$wrapper=null): AssocWrapper {
# si pas de valeur ni de wrapper, pas d'analyse et donc pas d'exception
# cf le code similaire dans AssocWrapper::__construct()
$dontAnalyze = $value === null && $wrapper === null;
if (!($wrapper instanceof AssocWrapper)) $wrapper = $this->newWrapper(); if (!($wrapper instanceof AssocWrapper)) $wrapper = $this->newWrapper();
return $wrapper->reset($array, $arrayKey);
# la nature du schéma peut contenir des paramètres par défaut
$nature = $this->definition[""];
foreach (array_keys(ref_schema::ASSOC_PARAMS_SCHEMA) as $paramKey) {
$paramValue = $nature[$paramKey] ?? null;
if ($paramValue !== null) $params[$paramKey] = $paramValue;
}
if ($params !== null) $wrapper->resetParams($params);
return $wrapper->reset($value, $valueKey, $dontAnalyze? ["analyze" => false]: null);
} }
} }

View File

@ -1,140 +1,185 @@
<?php <?php
namespace nur\sery\wip\schema\_assoc; namespace nulib\schema\_assoc;
use nulib\cl;
use nulib\ref\schema\ref_analyze;
use nulib\ValueException; use nulib\ValueException;
use nur\sery\wip\schema\_scalar\ScalarResult; use nulib\schema\_scalar\ScalarResult;
use nur\sery\wip\schema\_scalar\ScalarWrapper; use nulib\schema\_scalar\ScalarWrapper;
use nur\sery\wip\schema\input\Input; use nulib\schema\input\Input;
use nur\sery\wip\schema\Result; use nulib\schema\Result;
use nur\sery\wip\schema\types\IType; use nulib\schema\types\IType;
use nur\sery\wip\schema\Wrapper; use nulib\schema\Wrapper;
use nulib\schema\WrapperContext;
class AssocWrapper extends Wrapper { class AssocWrapper extends Wrapper {
function __construct(AssocSchema $schema, &$array=null, $arrayKey=null, ?array $params=null) { function __construct(AssocSchema $schema, &$value=null, $valueKey=null, ?array $params=null) {
$verifix = $params["verifix"] ?? true; $keys = $schema->getKeys();
$throw = $params["throw"] ?? null; $keyParams = cl::merge($params, [
if ($array !== null && $throw === null) { "throw" => false,
# Si $value est null, ne pas lancer d'exception, parce qu'on considère que ]);
# c'est une initialisation sans conséquences $keyWrappers = [];
$throw = true; foreach ($keys as $key) {
$value = null;
$keyWrappers[$key] = $schema->getSchema($key)->getWrapper($value, null, $keyParams);
}
$this->context = $context = new AssocWrapperContext($schema, null, null, $params);
$arrayParams = cl::merge($params, [
"throw" => false,
]);
$context->arrayWrapper = new ScalarWrapper($schema, $dummy, null, $arrayParams, $context);
$context->keys = $keys;
$context->keyWrappers = $keyWrappers;
if ($value !== null) {
# n'initialiser que si $value n'est pas null
$this->reset($value, $valueKey);
} }
$this->schema = $schema;
$this->verifix = $verifix;
$this->throw = $throw ?? false;
$this->result = new AssocResult();
$this->reset($array, $arrayKey);
$this->throw = $throw ?? true;
} }
function isAssoc(?AssocWrapper &$wrapper=null): bool { $wrapper = $this; return true; } /** @var AssocWrapperContext */
protected WrapperContext $context;
protected bool $verifix; protected function resetContext($resetSelectedKey): void {
parent::resetContext($resetSelectedKey);
protected bool $throw; $context = $this->context;
$context->arrayWrapper->getResult()->reset();
/** schéma de ce tableau */ foreach ($context->keyWrappers as $wrapper) {
protected AssocSchema $schema; $wrapper->getResult()->reset();
}
/** source et destination de la valeur */
protected Input $input;
/** @var string|int|null clé du tableau dans le tableau destination */
protected $arrayKey;
protected IType $arrayType;
protected ScalarResult $arrayResult;
/** @var IType[] */
protected array $keyTypes;
/** @var Result[] */
protected array $keyResults;
protected AssocResult $result;
protected ?array $keys;
protected ?array $wrappers;
protected function newInput(&$value): Input {
return new Input($value);
} }
function reset(&$array, $arrayKey=null, ?bool $verifix=null): Wrapper { function reset(&$value, $valueKey=null, ?array $params=null): Wrapper {
if ($array instanceof Input) $input = $array; $context = $this->context;
else $input = $this->newInput($array); if ($value instanceof Input) $input = $value;
$this->input = $input; else $input = $this->newInput($value);
$this->arrayKey = $arrayKey; $context->input = $input;
$this->analyze(); $context->valueKey = $valueKey;
if ($verifix ?? $this->verifix) $this->verifix(); foreach ($context->keyWrappers as $key => $keyWrapper) {
$keyInput = $input->addKey($valueKey);
$keyWrapper->reset($keyInput, $key, ["analyze" => false]);
}
$this->afterModify($params, true);
return $this; return $this;
} }
function getKeys(): array { function getKeys(): array {
return $this->keys; return $this->context->keys;
} }
function select($key=null): ScalarWrapper { protected function _getWrapper($key): Wrapper {
$wrapper = $this->wrappers[$key] ?? null; $context = $this->context;
if ($key !== null) return $wrapper; if ($key === null) return $context->arrayWrapper;
throw ValueException::invalid_key($key); $wrapper = $context->keyWrappers[$key] ?? null;
if ($wrapper === null) throw ValueException::invalid_key($key);
return $wrapper;
} }
/** @param Result[] $results */ /** @param string|int|null $key */
function verifix(?bool $throw=null, ?array &$results=null): bool { function select($key=null): Wrapper {
$wrapper = $this->_getWrapper($key);
$this->context->selectedKey = $key;
return $wrapper;
} }
/**
* @param AssocWrapperContext $context
* @param AssocWrapper $wrapper
*/
static function _analyze(WrapperContext $context, Wrapper $wrapper, ?array $params): int {
if ($params["ensure_array"] ?? $context->ensureArray) {
$valueKey = $context->valueKey;
$array = $context->input->get($valueKey);
if ($array === null) $context->input->set([], $valueKey);
}
function getResult(): AssocResult { if ($params["ensure_assoc"] ?? $context->ensureAssoc) {
return $this->result; $context->input->ensureAssoc($context->schema->getKeys());
}
$what = ScalarWrapper::_analyze($context, $wrapper, $params);
/** @var ScalarResult $result */
$result = $context->result;
if (!$result->valid) return $what;
foreach ($context->keyWrappers as $keyWrapper) {
$keyWrapper->analyze($params);
if (!$keyWrapper->isValid()) {
#XXX distinguer MISSING, UNAVAILABLE, NULL et !VALID
$what = ref_analyze::INVALID;
$result->addInvalidMessage($keyWrapper);
}
}
#XXX supprimer les clés "missing" ou "unavailable" sauf si $ensureKeys
return $what;
} }
function isPresent(): bool { /**
return $this->result->present; * @param AssocWrapperContext $context
* @param AssocWrapper $wrapper
*/
static function _normalize(WrapperContext $context, Wrapper $wrapper, ?array $params): bool {
$ensureKeys = $params["ensure_keys"] ?? $context->ensureKeys;
$ensureOrder = $params["ensure_order"] ?? $context->ensureOrder;
if ($ensureKeys || $ensureOrder) {
$schema = $context->schema;
$keys = $schema->getKeys();
if ($ensureKeys) {
$defaults = [];
foreach ($keys as $key) {
$default = $schema->getSchema($key)->default;
if ($default === null) {
$default = $wrapper->getType($key)->getNullValue();
}
$defaults[$key] = $default;
}
}
if ($ensureKeys) $context->input->ensureKeys($defaults, $params);
if ($ensureOrder) $context->input->ensureOrder($keys, $params);
}
$modified = ScalarWrapper::_normalize($context, $wrapper, $params);
foreach ($context->keyWrappers as $keyWrapper) {
if ($keyWrapper->normalize($params)) $modified = true;
}
return $modified;
} }
function getType(): IType { function getResult($key=false): Result {
return $this->arrayType; if ($key === false) $key = $this->context->selectedKey;
return $this->_getWrapper($key)->getResult();
} }
function isAvailable(): bool { function getType($key=false): IType {
return $this->result->available; if ($key === false) $key = $this->context->selectedKey;
return $this->_getWrapper($key)->getType();
} }
function isValid(): bool { function get($default=null, $key=false) {
return $this->result->valid; $context = $this->context;
if (!$context->arrayWrapper->isAvailable()) return $default;
if ($key === false) $key = $context->selectedKey;
return $this->_getWrapper($key)->get($default);
} }
function isNormalized(): bool { function set($value, ?array $params=null, $key=false): Wrapper {
return $this->result->normalized; $context = $this->context;
} if ($key === false) $key = $context->selectedKey;
$this->_getWrapper($key)->set($value);
function get($default=null) {
if ($this->result->available) return $this->input->get($this->arrayKey);
else return $default;
}
function set($value, ?bool $verifix=null): AssocWrapper {
$this->input->set($value, $this->arrayKey);
$this->analyze();
if ($verifix ?? $this->verifix) $this->verifix();
return $this; return $this;
} }
function unset(?bool $verifix=null): AssocWrapper { function unset(?array $params=null, $key=false): Wrapper {
$this->input->unset($this->arrayKey); $context = $this->context;
$this->analyze(); if ($key === false) $key = $context->selectedKey;
if ($verifix ?? $this->verifix) $this->verifix(); $this->_getWrapper($key)->unset();
return $this; return $this;
} }
function format($format = null): string { function format($format=null, $key=false): string {
// TODO: Implement format() method. $context = $this->context;
} if ($key === false) $key = $context->selectedKey;
return $this->_getWrapper($key)->format($format);
function ensureKeys(): bool {
}
function orderKeys(): bool {
} }
} }

View File

@ -0,0 +1,31 @@
<?php
namespace nulib\schema\_assoc;
use nulib\ref\schema\ref_schema;
use nulib\schema\_scalar\ScalarWrapper;
use nulib\schema\Wrapper;
use nulib\schema\WrapperContext;
class AssocWrapperContext extends WrapperContext {
public bool $ensureArray;
public bool $ensureAssoc;
public bool $ensureKeys;
public bool $ensureOrder;
public function resetParams(?array $params): void {
parent::resetParams($params);
$this->ensureArray = $params["ensure_array"] ?? ref_schema::ASSOC_PARAMS_SCHEMA["ensure_array"][1];
$this->ensureAssoc = $params["ensure_assoc"] ?? ref_schema::ASSOC_PARAMS_SCHEMA["ensure_assoc"][1];
$this->ensureKeys = $params["ensure_keys"] ?? ref_schema::ASSOC_PARAMS_SCHEMA["ensure_keys"][1];
$this->ensureOrder = $params["ensure_order"] ?? ref_schema::ASSOC_PARAMS_SCHEMA["ensure_order"][1];
}
public ?ScalarWrapper $arrayWrapper = null;
/** liste des clés valides */
public array $keys;
/** @var Wrapper[] */
public array $keyWrappers;
}

View File

@ -1,8 +1,8 @@
<?php <?php
namespace nur\sery\wip\schema\_list; namespace nulib\schema\_list;
use nulib\ValueException; use nulib\ValueException;
use nur\sery\wip\schema\Result; use nulib\schema\Result;
class ListResult extends Result { class ListResult extends Result {
function __construct(Result $arrayResult, array &$keyResults) { function __construct(Result $arrayResult, array &$keyResults) {
@ -12,8 +12,6 @@ class ListResult extends Result {
parent::__construct(); parent::__construct();
} }
function isList(?ListResult &$result=null): bool { $result = $this; return true;}
protected Result $arrayResult; protected Result $arrayResult;
/** @var Result[] */ /** @var Result[] */

View File

@ -1,9 +1,10 @@
<?php <?php
namespace nur\sery\wip\schema\_list; namespace nulib\schema\_list;
use nulib\ref\schema\ref_schema; use nulib\ref\schema\ref_schema;
use nur\sery\wip\schema\Schema; use nulib\ValueException;
use nur\sery\wip\schema\Wrapper; use nulib\schema\Schema;
use nulib\schema\Wrapper;
class ListSchema extends Schema { class ListSchema extends Schema {
/** @var array meta-schema d'un schéma de nature liste */ /** @var array meta-schema d'un schéma de nature liste */
@ -34,7 +35,7 @@ class ListSchema extends Schema {
"schema" => $definition[0], "schema" => $definition[0],
]; ];
} }
self::_normalize($definition, $definitionKey); self::_normalize_definition($definition, $definitionKey);
self::_ensure_nature($definition, "list", "array"); self::_ensure_nature($definition, "list", "array");
return $definition; return $definition;
} }
@ -50,17 +51,26 @@ class ListSchema extends Schema {
$this->definition = $definition; $this->definition = $definition;
} }
function isList(?ListSchema &$schema=null): bool { const KEYS = [null];
$schema = $this;
return true; function getKeys(): array {
return self::KEYS;
}
public function getSchema($key=false): Schema {
if ($key !== null) throw ValueException::invalid_key($key);
return $this;
} }
protected function newWrapper(): ListWrapper { protected function newWrapper(): ListWrapper {
return new ListWrapper($this); return new ListWrapper($this);
} }
function getWrapper(&$value=null, $valueKey=null, ?Wrapper &$wrapper=null): ListWrapper { function getWrapper(&$value=null, $valueKey=null, ?array $params = null, ?Wrapper &$wrapper=null): ListWrapper {
# 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 ListWrapper)) $wrapper = $this->newWrapper(); if (!($wrapper instanceof ListWrapper)) $wrapper = $this->newWrapper();
return $wrapper->reset($value, $valueKey); return $wrapper->reset($value, $valueKey, $verifix);
} }
} }

View File

@ -1,12 +1,10 @@
<?php <?php
namespace nur\sery\wip\schema\_list; namespace nulib\schema\_list;
use nur\sery\wip\schema\Result; use nulib\schema\Result;
use nur\sery\wip\schema\Wrapper; use nulib\schema\Wrapper;
abstract/*XXX*/ class ListWrapper extends Wrapper { abstract/*XXX*/ class ListWrapper extends Wrapper {
function isList(?ListWrapper &$wrapper=null): bool { $wrapper = $this; return true; }
function ensureKeys(): bool { function ensureKeys(): bool {
} }

View File

@ -1,21 +1,21 @@
<?php <?php
namespace nur\sery\wip\schema\_scalar; namespace nulib\schema\_scalar;
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;
use nulib\ValueException; use nulib\ValueException;
use nur\sery\wip\schema\Result; use nulib\schema\Result;
use nulib\schema\Schema;
use nulib\schema\Wrapper;
use Throwable; use Throwable;
/** /**
* Class ScalarResult: résultat de l'analyse ou de la normalisation d'une valeur * Class ScalarResult: résultat de l'analyse ou de la normalisation d'une valeur
*/ */
class ScalarResult extends Result { class ScalarResult extends Result {
function isScalar(?ScalarResult &$result=null): bool { $result = $this; return true; }
function getKeys(): array { function getKeys(): array {
return [null]; return ScalarSchema::KEYS;
} }
function select($key): Result { function select($key): Result {
@ -23,8 +23,7 @@ class ScalarResult extends Result {
return $this; return $this;
} }
/** @var array */ protected array $result;
protected $result;
function reset(): void { function reset(): void {
$this->result = array_merge( $this->result = array_merge(
@ -46,26 +45,13 @@ class ScalarResult extends Result {
$this->result[$name] = $value; $this->result[$name] = $value;
} }
protected static function replace_key(string &$message, ?string $key): void { protected function getMessage(string $key, Schema $schema): string {
if ($key) {
$message = str_replace("{key}", $key, $message);
} else {
$message = str_replace("{key}: ", "", $message);
$message = str_replace("cette valeur", "la valeur", $message);
}
}
protected static function replace_orig(string &$message, $origValue): void {
$message = str_replace("{orig}", strval($origValue), $message);
}
protected function getMessage(string $key, ScalarSchema $schema): string {
$message = cl::get($schema->messages, $key); $message = cl::get($schema->messages, $key);
if ($message !== null) return $message; if ($message !== null) return $message;
return cl::get(ref_schema::MESSAGES, $key); return cl::get(ref_schema::MESSAGES, $key);
} }
function setMissing(ScalarSchema $schema): int { function setMissing( Schema $schema): int {
$this->resultAvailable = true; $this->resultAvailable = true;
$this->present = false; $this->present = false;
$this->available = false; $this->available = false;
@ -75,15 +61,13 @@ class ScalarResult extends Result {
$this->normalized = true; $this->normalized = true;
return ref_analyze::NORMALIZED; return ref_analyze::NORMALIZED;
} else { } else {
$messageKey = $this->messageKey = "missing"; $this->messageKey = $messageKey = "missing";
$message = $this->getMessage($messageKey, $schema); $this->message = $this->getMessage($messageKey, $schema);
self::replace_key($message, $schema->name);
$this->message = $message;
return ref_analyze::MISSING; return ref_analyze::MISSING;
} }
} }
function setUnavailable(ScalarSchema $schema): int { function setUnavailable( Schema $schema): int {
$this->resultAvailable = true; $this->resultAvailable = true;
$this->present = true; $this->present = true;
$this->available = false; $this->available = false;
@ -93,15 +77,13 @@ class ScalarResult extends Result {
$this->normalized = true; $this->normalized = true;
return ref_analyze::NORMALIZED; return ref_analyze::NORMALIZED;
} else { } else {
$messageKey = $this->messageKey = "unavailable"; $this->messageKey = $messageKey = "unavailable";
$message = $this->getMessage($messageKey, $schema); $this->message = $this->getMessage($messageKey, $schema);
self::replace_key($message, $schema->name);
$this->message = $message;
return ref_analyze::UNAVAILABLE; return ref_analyze::UNAVAILABLE;
} }
} }
function setNull(ScalarSchema $schema): int { function setNull( Schema $schema): int {
$this->resultAvailable = true; $this->resultAvailable = true;
$this->present = true; $this->present = true;
$this->available = true; $this->available = true;
@ -111,33 +93,53 @@ class ScalarResult extends Result {
$this->normalized = true; $this->normalized = true;
return ref_analyze::NORMALIZED; return ref_analyze::NORMALIZED;
} else { } else {
$messageKey = $this->messageKey = "null"; $this->messageKey = $messageKey = "null";
$message = $this->getMessage($messageKey, $schema); $this->message = $this->getMessage($messageKey, $schema);
self::replace_key($message, $schema->name);
$this->message = $message;
return ref_analyze::NULL; return ref_analyze::NULL;
} }
} }
function setInvalid($value, ScalarSchema $schema, ?Throwable $t=null): int { function setInvalid($value, Schema $schema, ?Throwable $exception=null): int {
$this->resultAvailable = true; $this->resultAvailable = true;
$this->present = true; $this->present = true;
$this->available = true; $this->available = true;
$this->null = false; $this->null = false;
$this->valid = false; $this->valid = false;
$this->origValue = $value; $this->origValue = $value;
$messageKey = $this->messageKey = "invalid"; $this->messageKey = $messageKey = "invalid";
$message = $this->getMessage($messageKey, $schema); $message = $this->getMessage($messageKey, $schema);
self::replace_key($message, $schema->name); if ($exception !== null) {
self::replace_orig($message, $schema->orig); $tmessage = ValueException::get_message($exception);
if ($t !== null) { if ($tmessage) $message = $tmessage;
$tmessage = ValueException::get_message($t);
if ($tmessage) $message .= ": $tmessage";
} }
$this->message = $message; $this->message = $message;
$this->exception = $exception;
return ref_analyze::INVALID; return ref_analyze::INVALID;
} }
function addInvalidMessage(Wrapper $wrapper): void {
$this->resultAvailable = true;
$this->present = true;
$this->available = true;
$this->null = false;
$this->valid = false;
$this->messageKey = "invalid";
$result = $wrapper->getResult();
$resultException = $result->exception;
$resultMessage = $result->message;
if ($resultException !== null) {
$tmessage = ValueException::get_message($resultException);
if ($tmessage) {
if ($resultMessage !== null) $resultMessage .= ": ";
$resultMessage .= $tmessage;
}
}
$message = $this->message;
if ($message) $message .= "\n";
$message .= $resultMessage;
$this->message = $message;
}
function setValid($normalizedValue=null): int { function setValid($normalizedValue=null): int {
$this->resultAvailable = true; $this->resultAvailable = true;
$this->present = true; $this->present = true;
@ -159,6 +161,10 @@ class ScalarResult extends Result {
} }
function throw(bool $throw): void { function throw(bool $throw): void {
if ($throw) throw new ValueException($this->message); if ($throw) {
$exception = $this->exception;
if ($exception !== null) throw $exception;
else throw new ValueException($this->message);
}
} }
} }

View File

@ -1,41 +1,19 @@
<?php <?php
namespace nur\sery\wip\schema\_scalar; namespace nulib\schema\_scalar;
use nulib\cl;
use nulib\ref\schema\ref_schema; use nulib\ref\schema\ref_schema;
use nur\sery\wip\schema\Schema; use nulib\ValueException;
use nur\sery\wip\schema\types\IType; use nulib\schema\Schema;
use nur\sery\wip\schema\Wrapper; use nulib\schema\Wrapper;
/** /**
* Class ScalarSchema * Class ScalarSchema
*
* @property-read array|IType $type
* @property-read mixed $default
* @property-read string|null $title
* @property-read bool $required
* @property-read bool $nullable
* @property-read string|array|null $desc
* @property-read callable|null $analyzerFunc
* @property-read callable|null $extractorFunc
* @property-read callable|null $parserFunc
* @property-read callable|null $normalizerFunc
* @property-read array|null $messages
* @property-read callable|null $formatterFunc
* @property-read mixed $format
* @property-read array $nature
* @property-read array|null $schema
* @property-read string|int|null $name
* @property-read string|array|null $pkey
* @property-read string|null $header
* @property-read bool|null $composite
*/ */
class ScalarSchema extends 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 * indiquer si $definition est une définition de schéma scalaire que
* {@link normalize()} pourrait normaliser * {@link normalize_definition()} pourrait normaliser
*/ */
static function isa_definition($definition): bool { static function isa_definition($definition): bool {
# chaine ou null # chaine ou null
@ -64,8 +42,9 @@ class ScalarSchema extends Schema {
return $haveIndex0 && $count > 1; return $haveIndex0 && $count > 1;
} }
static function normalize($definition, $definitionKey=null): array { static function normalize_definition($definition, $definitionKey=null): array {
self::_normalize($definition, $definitionKey); $natureMetaschema = array_merge(ref_schema::NATURE_METASCHEMA, ref_schema::SCALAR_NATURE_METASCHEMA);
self::_normalize_definition($definition, $definitionKey, $natureMetaschema);
self::_ensure_nature($definition, "scalar"); self::_ensure_nature($definition, "scalar");
return $definition; return $definition;
} }
@ -73,40 +52,47 @@ class ScalarSchema extends Schema {
function __construct($definition=null, $definitionKey=null, bool $normalize=true) { function __construct($definition=null, $definitionKey=null, bool $normalize=true) {
if ($definition === null) $definition = static::SCHEMA; if ($definition === null) $definition = static::SCHEMA;
if ($normalize) { if ($normalize) {
$definition = self::normalize($definition, $definitionKey); $definition = self::normalize_definition($definition, $definitionKey);
$this->_definition = $definition; $this->_definition = $definition;
self::_ensure_type($definition); self::_ensure_type($definition);
self::_ensure_schema_instances($definition); self::_ensure_schema_instances($definition);
} else {
# ici, $definition contient un schema déjà instancié, mais c'est le mieux
# qu'on puisse faire
$this->_definition = $definition;
} }
$this->definition = $definition; $this->definition = $definition;
} }
function isScalar(?ScalarSchema &$schema=null): bool { const KEYS = [null];
$schema = $this;
return true; function getKeys(): array {
return self::KEYS;
}
function getSchema($key=false): Schema {
if ($key === null || $key === false) return $this;
throw ValueException::invalid_key($key);
} }
protected function newWrapper(): ScalarWrapper { protected function newWrapper(): ScalarWrapper {
return new ScalarWrapper($this); return new ScalarWrapper($this);
} }
function getWrapper(&$value=null, $valueKey=null, ?Wrapper &$wrapper=null): ScalarWrapper { function getWrapper(&$value=null, $valueKey=null, ?array $params=null, ?Wrapper &$wrapper=null): ScalarWrapper {
# si pas de valeur ni de wrapper, pas de vérification et donc pas d'exception # si pas de valeur ni de wrapper, pas de vérification et donc pas d'exception
# cf le code similaire dans ScalarWrapper::__construct() # cf le code similaire dans ScalarWrapper::__construct()
$verifix = $value !== null || $wrapper !== null; $dontAnalyze = $value === null && $wrapper === null;
if (!($wrapper instanceof ScalarWrapper)) $wrapper = $this->newWrapper(); if (!($wrapper instanceof ScalarWrapper)) $wrapper = $this->newWrapper();
return $wrapper->reset($value, $valueKey, $verifix);
# la nature du schéma peut contenir des paramètres par défaut
$nature = $this->definition[""];
foreach (array_keys(ref_schema::SCALAR_PARAMS_SCHEMA) as $paramKey) {
$paramValue = $nature[$paramKey] ?? null;
if ($paramValue !== null) $params[$paramKey] = $paramValue;
}
if ($params !== null) $wrapper->resetParams($params);
return $wrapper->reset($value, $valueKey, $dontAnalyze? ["analyze" => false]: null);
} }
#############################################################################
# key & properties
const _PROPERTY_PKEYS = [
"analyzerFunc" => "analyzer_func",
"extractorFunc" => "extractor_func",
"parserFunc" => "parser_func",
"normalizerFunc" => "normalizer_func",
"formatterFunc" => "formatter_func",
"nature" => ["", 0],
];
} }

View File

@ -1,70 +1,42 @@
<?php <?php
namespace nur\sery\wip\schema\_scalar; namespace nulib\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 nulib\schema\Schema;
use nur\sery\wip\schema\input\Input; use nulib\schema\types;
use nur\sery\wip\schema\types; use nulib\schema\types\IType;
use nur\sery\wip\schema\types\IType; use nulib\schema\Wrapper;
use nur\sery\wip\schema\Wrapper; use nulib\schema\WrapperContext;
/**
* Class ScalarWrapper
*
* @method ScalarWrapper reset(&$value, $valueKey=null, ?array $params=null)
* @method ScalarResult getResult($key=false)
* @method self set($value, ?array $params=null, $key=false)
* @method self unset(?array $params=null, $key=false)
*/
class ScalarWrapper extends Wrapper { class ScalarWrapper extends Wrapper {
function __construct(ScalarSchema $schema, &$value=null, $valueKey=null, ?array $params=null) { function __construct(Schema $schema, &$value=null, $valueKey=null, ?array $params=null, ?WrapperContext $context=null) {
$verifix = $params["verifix"] ?? true; if ($context === null) $context = new WrapperContext($schema, null, null, $params);
$throw = $params["throw"] ?? null; $context->result = new ScalarResult();
if ($value !== null && $throw === null) { $this->context = $context;
# Si $value est null, ne pas lancer d'exception, parce qu'on considère que
# c'est une initialisation sans conséquences if ($value !== null) {
$throw = true; # n'initialiser que si $value n'est pas null
$this->reset($value, $valueKey);
} else {
# il faut au moins que le type soit disponible
$this->resetContext(false);
} }
$this->verifix = $verifix;
$this->throw = $throw ?? false;
$this->schema = $schema;
$this->result = new ScalarResult();
$this->reset($value, $valueKey);
$this->throw = $throw ?? true;
} }
function isScalar(?ScalarWrapper &$wrapper=null): bool { $wrapper = $this; return true; } protected WrapperContext $context;
protected bool $verifix;
protected bool $throw;
/** schéma de cette valeur */
protected ScalarSchema $schema;
/** source et destination de la valeur */
protected Input $input;
/** @var string|int|null clé de la valeur dans le tableau destination */
protected $valueKey;
/** type de la valeur après analyse */
protected ?IType $type;
/** résultat de l'analyse de la valeur */
protected ScalarResult $result;
protected function newInput(&$value): Input {
return new Input($value);
}
function reset(&$value, $valueKey=null, ?bool $verifix=null): Wrapper {
if ($value instanceof Input) $input = $value;
else $input = $this->newInput($value);
$this->input = $input;
$this->valueKey = $valueKey;
$this->type = null;
$this->analyze();
if ($verifix ?? $this->verifix) $this->verifix();
return $this;
}
function getKeys(): array { function getKeys(): array {
return [null]; return ScalarSchema::KEYS;
} }
/** @param string|int|null $key */ /** @param string|int|null $key */
@ -74,7 +46,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 static function _analyze0(WrapperContext $context): int {
/** @var ScalarSchema $schema */ /** @var ScalarSchema $schema */
$schema = $context->schema; $schema = $context->schema;
$input = $context->input; $input = $context->input;
@ -112,7 +84,7 @@ class ScalarWrapper extends Wrapper {
$args = $name; $args = $name;
$name = $key; $name = $key;
} }
$type = types::get($schema->nullable, $name, $args, $this->schema->getDefinition()); $type = types::get($schema->nullable, $name, $args, $schema->getDefinition());
if ($firstType === null) $firstType = $type; if ($firstType === null) $firstType = $type;
$types[] = $type; $types[] = $type;
if ($type->isAvailable($input, $valueKey)) { if ($type->isAvailable($input, $valueKey)) {
@ -140,7 +112,7 @@ class ScalarWrapper extends Wrapper {
$type = $firstType; $type = $firstType;
} }
} }
$context->type = $this->type = $type; $context->type = $type;
if (!$type->isAvailable($input, $valueKey)) { if (!$type->isAvailable($input, $valueKey)) {
if ($default !== null) { if ($default !== null) {
@ -165,25 +137,28 @@ class ScalarWrapper extends Wrapper {
} }
} }
protected function analyze(): int { /**
$schema = $this->schema; * @param ScalarWrapper $wrapper
$input = $this->input; */
$valueKey = $this->valueKey; static function _analyze(WrapperContext $context, Wrapper $wrapper, ?array $params): int {
$result = $this->result; /** @var ScalarSchema $schema */
$result->reset(); $schema = $context->schema;
$context = new WrapperContext($schema, $this, $input, $valueKey, $result); $input = $context->input;
$valueKey = $context->valueKey;
/** @var ScalarResult $result */
$result = $context->result;
/** @var func $analyzerFunc */ /** @var func $analyzerFunc */
$analyzerFunc = $schema->analyzerFunc; $analyzerFunc = $schema->analyzerFunc;
if ($analyzerFunc !== null) $what = $analyzerFunc->invoke([$context]); if ($analyzerFunc !== null) $what = $analyzerFunc->invoke([$context, $wrapper]);
else $what = $this->analyze0($context); else $what = self::_analyze0($context);
if ($what !== ref_analyze::STRING) return $what; if ($what !== ref_analyze::STRING) return $what;
$value = $context->value; $value = $context->value;
try { try {
/** @var func $extractorFunc */ /** @var func $extractorFunc */
$extractorFunc = $schema->extractorFunc; $extractorFunc = $schema->extractorFunc;
if ($extractorFunc !== null) $extracted = $extractorFunc->invoke([$value, $context]); if ($extractorFunc !== null) $extracted = $extractorFunc->invoke([$value, $context, $wrapper]);
else $extracted = $context->type->extract($value); else $extracted = $context->type->extract($value);
$context->value = $extracted; $context->value = $extracted;
} catch (ValueException $e) { } catch (ValueException $e) {
@ -194,7 +169,7 @@ class ScalarWrapper extends Wrapper {
try { try {
/** @var func $parserFunc */ /** @var func $parserFunc */
$parserFunc = $schema->parserFunc; $parserFunc = $schema->parserFunc;
if ($parserFunc !== null) $parsed = $parserFunc->invoke([$extracted, $context]); if ($parserFunc !== null) $parsed = $parserFunc->invoke([$extracted, $context, $wrapper]);
else $parsed = $context->type->parse($extracted); else $parsed = $context->type->parse($extracted);
$context->value = $parsed; $context->value = $parsed;
} catch (ValueException $e) { } catch (ValueException $e) {
@ -211,107 +186,53 @@ class ScalarWrapper extends Wrapper {
} }
} }
function verifix(?bool $throw=null): bool { /**
$result = $this->result; * @param ScalarWrapper $wrapper
$valueKey = $this->valueKey; */
$verifix = false; static function _normalize(WrapperContext $context, Wrapper $wrapper, ?array $params): bool {
/** @var ScalarSchema $schema */
$schema = $context->schema;
$input = $context->input;
$valueKey = $context->valueKey;
/** @var ScalarResult $result */
$result = $context->result;
$normalize = false;
$modified = false; $modified = false;
if ($result->resultAvailable) { if ($result->resultAvailable) {
if ($result->null) { if ($result->null) {
# forcer la valeur null, parce que la valeur actuelle est peut-être une # forcer la valeur null, parce que la valeur actuelle est peut-être une
# valeur assimilée à null # valeur assimilée à null
$this->input->set(null, $valueKey); $input->set(null, $valueKey);
} elseif ($result->valid && !$result->normalized) { } elseif ($result->valid && !$result->normalized) {
$normalizedValue = $result->normalizedValue; $normalizedValue = $result->normalizedValue;
if ($normalizedValue !== null) { if ($normalizedValue !== null) {
# la valeur normalisée est disponible # la valeur normalisée est disponible
$this->input->set($normalizedValue); $input->set($normalizedValue, $valueKey);
$result->normalizedValue = null; $result->normalizedValue = null;
$modified = true; $modified = true;
} else { } else {
# normaliser la valeur # normaliser la valeur
$verifix = true; $normalize = true;
} }
} }
} else { } else {
$verifix = true; $normalize = true;
} }
if ($verifix) { if ($normalize) {
$value = $this->input->get($valueKey); $value = $input->get($valueKey);
$schema = $this->schema;
/** @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);
$orig = $value; $orig = $value;
$value = $normalizerFunc->invoke([$orig, $context]); $value = $normalizerFunc->invoke([$orig, $context, $wrapper]);
$modified = $value !== $orig; $modified = $value !== $orig;
} else { } else {
$modified = $this->type->verifix($value, $result, $this->schema); $modified = $context->type->normalize($value, $result, $schema);
} }
if ($result->valid) $this->input->set($value, $valueKey); if ($result->valid) $input->set($value, $valueKey);
} }
if (!$result->valid) $result->throw($throw ?? $this->throw);
return $modified; return $modified;
} }
function getResult(): ScalarResult {
return $this->result;
}
function isPresent(): bool {
return $this->result->present;
}
function getType(): IType {
return $this->type;
}
function isAvailable(): bool {
return $this->result->available;
}
function isValid(): bool {
return $this->result->valid;
}
function isNormalized(): bool {
return $this->result->normalized;
}
function get($default=null) {
if ($this->result->available) return $this->input->get($this->valueKey);
else return $default;
}
function set($value, ?bool $verifix=null): ScalarWrapper {
$this->input->set($value, $this->valueKey);
$this->analyze();
if ($verifix ?? $this->verifix) $this->verifix();
return $this;
}
function unset(?bool $verifix=null): ScalarWrapper {
$this->input->unset($this->valueKey);
$this->analyze();
if ($verifix ?? $this->verifix) $this->verifix();
return $this;
}
function format($format=null): string {
$value = $this->input->get($this->valueKey);
/** @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

@ -1,12 +1,11 @@
<?php <?php
namespace nur\sery\wip\schema\input; namespace nulib\schema\input;
#XXX implémenter le renommage de paramètres et faire des méthodes pour #XXX implémenter le renommage de paramètres et faire des méthodes pour
# construire des querystring et paramètres de formulaires # construire des querystring et paramètres de formulaires
use nur\sery\wip\php\access\FormAccess; use nulib\php\access\FormAccess;
use nur\sery\wip\php\access\IAccess; use nulib\php\access\IAccess;
use nur\sery\wip\php\access\KeyAccess; use nulib\php\access\ShadowAccess;
use nur\sery\wip\php\access\ShadowAccess;
/** /**
* Class FormInput: accès à des paramètres de formulaire (POST ou GET, dans cet * Class FormInput: accès à des paramètres de formulaire (POST ou GET, dans cet
@ -18,15 +17,14 @@ use nur\sery\wip\php\access\ShadowAccess;
class FormInput extends Input { class FormInput extends Input {
const ALLOW_EMPTY = false; const ALLOW_EMPTY = false;
protected function formAccess($key): IAccess { function __construct(&$dest=null, ?array $params=null) {
return new FormAccess($key, [ parent::__construct($dest, $params);
"allow_empty" => $this->allowEmpty, $this->access = new ShadowAccess($this->formAccess($this->access), $this->access);
]);
} }
protected function access($key): IAccess { protected function formAccess(IAccess $access): IAccess {
return $this->keyAccess[$key] ??= new ShadowAccess($this->formAccess($key), new KeyAccess($this->value, $key, [ return new FormAccess(null, [
"allow_empty" => $this->allowEmpty, "allow_empty" => $access->isAllowEmpty(),
])); ]);
} }
} }

View File

@ -1,8 +1,8 @@
<?php <?php
namespace nur\sery\wip\schema\input; namespace nulib\schema\input;
use nur\sery\wip\php\access\GetAccess; use nulib\php\access\GetAccess;
use nur\sery\wip\php\access\IAccess; use nulib\php\access\IAccess;
/** /**
* Class GetInput: accès à des paramètres de formulaire de type GET uniquement * Class GetInput: accès à des paramètres de formulaire de type GET uniquement
@ -11,9 +11,9 @@ use nur\sery\wip\php\access\IAccess;
* une référence * une référence
*/ */
class GetInput extends FormInput { class GetInput extends FormInput {
protected function formAccess($key): IAccess { protected function formAccess(IAccess $access): IAccess {
return new GetAccess($key, [ return new GetAccess(null, [
"allow_empty" => $this->allowEmpty, "allow_empty" => $access->isAllowEmpty(),
]); ]);
} }
} }

View File

@ -1,9 +1,11 @@
<?php <?php
namespace nur\sery\wip\schema\input; namespace nulib\schema\input;
use nur\sery\wip\php\access\IAccess; use nulib\ref\schema\ref_input;
use nur\sery\wip\php\access\KeyAccess; use nulib\StateException;
use nur\sery\wip\php\access\ValueAccess; use nulib\php\access\IAccess;
use nulib\php\access\KeyAccess;
use nulib\php\access\PropertyAccess;
/** /**
* Class Input: accès à une valeur * Class Input: accès à une valeur
@ -13,54 +15,72 @@ use nur\sery\wip\php\access\ValueAccess;
class Input { class Input {
const ALLOW_EMPTY = true; const ALLOW_EMPTY = true;
function __construct(&$value=null, ?array $params=null) { private static function unexpected_access_type(): StateException {
$this->value =& $value; return StateException::unexpected_state("access_type");
$this->allowEmpty = $params["allow_empty"] ?? static::ALLOW_EMPTY;
} }
/** @var mixed */ function __construct(&$dest=null, ?array $params=null) {
protected $value; $accessType = $params["access_type"] ?? ref_input::ACCESS_AUTO;
if ($accessType === ref_input::ACCESS_AUTO) {
$accessType = is_object($dest)? ref_input::ACCESS_PROPERTY : ref_input::ACCESS_KEY;
}
/** $allowEmpty = $params["allow_empty"] ?? static::ALLOW_EMPTY;
* @var bool comment considérer une chaine vide: "" si allowEmpty, null sinon if ($accessType == ref_input::ACCESS_PROPERTY) {
*/ $this->access = new PropertyAccess($dest, null, [
protected $allowEmpty; "allow_empty" => $allowEmpty,
"allow_null" => true,
protected ?ValueAccess $valueAccess = null; ]);
protected ?array $keyAccess = null; } elseif ($accessType == ref_input::ACCESS_KEY) {
$this->access = new KeyAccess($dest, null, [
protected function access($key): IAccess { "allow_empty" => $allowEmpty,
if ($key === null) {
return $this->valueAccess ??= new ValueAccess($this->value, [
"allow_null" => true, "allow_null" => true,
"allow_empty" => $this->allowEmpty,
]); ]);
} else { } else {
return $this->keyAccess[$key] ??= new KeyAccess($this->value, $key, [ throw self::unexpected_access_type();
"allow_empty" => $this->allowEmpty,
]);
} }
} }
protected IAccess $access;
/** tester si la valeur existe sans tenir compte de $allowEmpty */ /** tester si la valeur existe sans tenir compte de $allowEmpty */
function isPresent($key=null): bool { function isPresent($key=null): bool {
return $this->access($key)->exists(); return $this->access->resetKey($key)->exists();
} }
/** tester si la valeur est disponible en tenant compte de $allowEmpty */ /** tester si la valeur est disponible en tenant compte de $allowEmpty */
function isAvailable($key=null): bool { function isAvailable($key=null): bool {
return $this->access($key)->available(); return $this->access->resetKey($key)->available();
} }
function get($key=null) { function get($key=null) {
return $this->access($key)->get(); return $this->access->resetKey($key)->get();
} }
function set($value, $key=null): void { function set($value, $key=null): void {
$this->access($key)->set($value); $this->access->resetKey($key)->set($value);
} }
function unset($key=null): void { function unset($key=null): void {
$this->access($key)->del(); $this->access->resetKey($key)->del();
}
function addKey($key): Input {
if ($key === null) return $this;
$input = clone $this;
$input->access = $this->access->addKey($key);
return $input;
}
function ensureAssoc(array $keys, ?array $params=null): void {
$this->access->ensureAssoc($keys, $params);
}
function ensureKeys(array $defaults, ?array $params=null): void {
$this->access->ensureKeys($defaults, $params);
}
function ensureOrder(array $keys, ?array $params=null): void {
$this->access->ensureOrder($keys, $params);
} }
} }

View File

@ -1,8 +1,8 @@
<?php <?php
namespace nur\sery\wip\schema\input; namespace nulib\schema\input;
use nur\sery\wip\php\access\IAccess; use nulib\php\access\IAccess;
use nur\sery\wip\php\access\PostAccess; use nulib\php\access\PostAccess;
/** /**
* Class PostInput: accès à des paramètres de formulaire de type POST uniquement * Class PostInput: accès à des paramètres de formulaire de type POST uniquement
@ -11,9 +11,9 @@ use nur\sery\wip\php\access\PostAccess;
* une référence * une référence
*/ */
class PostInput extends FormInput { class PostInput extends FormInput {
protected function formAccess($key): IAccess { protected function formAccess(IAccess $access): IAccess {
return new PostAccess($key, [ return new PostAccess(null, [
"allow_empty" => $this->allowEmpty, "allow_empty" => $access->isAllowEmpty(),
]); ]);
} }
} }

View File

@ -1,22 +1,22 @@
<?php <?php
namespace nur\sery\wip\schema; namespace nulib\schema;
use nulib\ValueException; use nulib\ValueException;
use nur\sery\wip\schema\types\IType; use nulib\schema\types\IType;
use nur\sery\wip\schema\types\Registry; use nulib\schema\types\Registry;
use nur\sery\wip\schema\types\tarray; use nulib\schema\types\tarray;
use nur\sery\wip\schema\types\tbool; use nulib\schema\types\tbool;
use nur\sery\wip\schema\types\tcallable; use nulib\schema\types\tfunc;
use nur\sery\wip\schema\types\tcontent; use nulib\schema\types\tcontent;
use nur\sery\wip\schema\types\tfloat; use nulib\schema\types\tfloat;
use nur\sery\wip\schema\types\tint; use nulib\schema\types\tint;
use nur\sery\wip\schema\types\tkey; use nulib\schema\types\tkey;
use nur\sery\wip\schema\types\tmixed; use nulib\schema\types\tmixed;
use nur\sery\wip\schema\types\tpkey; use nulib\schema\types\tpkey;
use nur\sery\wip\schema\types\traw; use nulib\schema\types\traw;
use nur\sery\wip\schema\types\trawstring; use nulib\schema\types\trawstring;
use nur\sery\wip\schema\types\tstring; use nulib\schema\types\tstring;
use nur\sery\wip\schema\types\ttext; use nulib\schema\types\ttext;
/** /**
* Class types: classe outil pour gérer le registre de types * Class types: classe outil pour gérer le registre de types
@ -47,7 +47,7 @@ class types {
static function int(bool $nullable=true): tint { return self::get($nullable, "int"); } static function int(bool $nullable=true): tint { return self::get($nullable, "int"); }
static function float(bool $nullable=true): tfloat { return self::get($nullable, "float"); } static function float(bool $nullable=true): tfloat { return self::get($nullable, "float"); }
static function array(bool $nullable=true): tarray { return self::get($nullable, "array"); } static function array(bool $nullable=true): tarray { return self::get($nullable, "array"); }
static function callable(bool $nullable=true): tcallable { return self::get($nullable, "callable"); } static function callable(bool $nullable=true): tfunc { return self::get($nullable, "callable"); }
static function raw(bool $nullable=true): traw { return self::get($nullable, "raw"); } static function raw(bool $nullable=true): traw { return self::get($nullable, "raw"); }
static function mixed(bool $nullable=true): tmixed { return self::get($nullable, "mixed"); } static function mixed(bool $nullable=true): tmixed { return self::get($nullable, "mixed"); }
static function key(bool $nullable=true): tkey { return self::get($nullable, "key"); } static function key(bool $nullable=true): tkey { return self::get($nullable, "key"); }

View File

@ -1,10 +1,10 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
use nulib\ValueException; use nulib\ValueException;
use nur\sery\wip\schema\input\Input; use nulib\schema\input\Input;
use nur\sery\wip\schema\Result; use nulib\schema\Result;
use nur\sery\wip\schema\Schema; use nulib\schema\Schema;
/** /**
* Interface IType: un type de données * Interface IType: un type de données
@ -23,7 +23,7 @@ interface IType {
/** /**
* @return string la classe des objets gérés par ce format: le type attendu * @return string la classe des objets gérés par ce format: le type attendu
* par {@link format()} et le type retourné par {@link verifix()} * par {@link format()} et le type retourné par {@link normalize()}
* *
* Les valeurs "mixed", "bool", "float", "int", "string" et "array" peuvent * Les valeurs "mixed", "bool", "float", "int", "string" et "array" peuvent
* aussi être retournées, bien qu'elles ne soient pas à proprement parler des * aussi être retournées, bien qu'elles ne soient pas à proprement parler des
@ -47,6 +47,9 @@ interface IType {
*/ */
function getPhpType(bool $allowNullable=true): ?string; function getPhpType(bool $allowNullable=true): ?string;
/** obtenir la valeur "nulle" pour les objets de ce type */
function getNullValue();
/** /**
* indiquer si c'est le type d'une valeur qui ne peut prendre que 2 états: une * indiquer si c'est le type d'une valeur qui ne peut prendre que 2 états: une
* "vraie" et une "fausse" * "vraie" et une "fausse"
@ -98,15 +101,18 @@ interface IType {
function parse(string $value); function parse(string $value);
/** /**
* analyser, corriger éventuellement et normaliser la valeur * normaliser la valeur. elle *doit* déjà être valide.
* * Si $value est un string. elle *doit* avoir déjà été traitée au préalable
* NB: si $value est un string. elle doit avoir déjà été traitée au préalable
* par extract() et parse() * par extract() et parse()
* *
* si la valeur était déjà normalisée, ou si une erreur s'est produite, * - si $result indique que la valeur est déjà normalisée, cette méthode ne
* retourner false. * fait rien
* - si la valeur était déjà normalisée, mettre à jour $result pour indiquer
* que la valeur est normalisée et retourner false
* - sinon, retourner true pour indiquer qu'il a fallut normaliser la valeur.
* $result n'est pas modifié
*/ */
function verifix(&$value, Result $result, Schema $schema): bool; function normalize(&$value, Result $result, Schema $schema): bool;
/** /**
* formatter la valeur pour affichage. si $value n'est pas null, elle est * formatter la valeur pour affichage. si $value n'est pas null, elle est

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
use nulib\cl; use nulib\cl;
use nulib\php\func; use nulib\php\func;
@ -12,10 +12,9 @@ class Registry {
"text" => ttext::class, "text" => ttext::class,
"bool" => tbool::class, "boolean" => tbool::class, "bool" => tbool::class, "boolean" => tbool::class,
"int" => tint::class, "integer" => tint::class, "int" => tint::class, "integer" => tint::class,
"float" => tfloat::class, "flt" => tfloat::class, "float" => tfloat::class, "flt" => tfloat::class, "double" => tfloat::class, "dbl" => tfloat::class,
"double" => tfloat::class, "dbl" => tfloat::class,
"array" => tarray::class, "array" => tarray::class,
"callable" => tcallable::class, "func" => tfunc::class, "function" => tfunc::class, "callable" => tfunc::class,
# types spéciaux # types spéciaux
"raw" => traw::class, "raw" => traw::class,
"mixed" => tmixed::class, "mixed" => tmixed::class,

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
abstract class _tformatable extends _tsimple { abstract class _tformatable extends _tsimple {
const FORMAT = null; const FORMAT = null;

View File

@ -1,9 +1,9 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
use nulib\StateException; use nulib\StateException;
use nur\prop; use nur\prop;
use nur\sery\wip\schema\input\Input; use nulib\schema\input\Input;
use nur\str; use nur\str;
abstract class _tsimple implements IType { abstract class _tsimple implements IType {

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
use nulib\str; use nulib\str;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
abstract class _tunion extends _tsimple { abstract class _tunion extends _tsimple {
function getPhpType(bool $allowNullable=true): ?string { function getPhpType(bool $allowNullable=true): ?string {

View File

@ -1,12 +1,12 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
use nulib\cl; use nulib\cl;
use nulib\ValueException; use nulib\ValueException;
use nur\sery\wip\schema\_scalar\ScalarResult; use nulib\schema\_scalar\ScalarResult;
use nur\sery\wip\schema\_scalar\ScalarSchema; use nulib\schema\_scalar\ScalarSchema;
use nur\sery\wip\schema\Result; use nulib\schema\Result;
use nur\sery\wip\schema\Schema; use nulib\schema\Schema;
class tarray extends _tstring { class tarray extends _tstring {
const NAME = "array"; const NAME = "array";
@ -35,9 +35,13 @@ class tarray extends _tstring {
return "array"; return "array";
} }
function getNullValue() {
return $this->nullable? null: [];
}
function isValid($value, ?bool &$normalized=null): bool { function isValid($value, ?bool &$normalized=null): bool {
$normalized = is_array($value); $normalized = is_array($value);
return is_scalar($value) || is_array($value); return $normalized || is_scalar($value);
} }
function parse(string $value) { function parse(string $value) {
@ -49,23 +53,14 @@ class tarray extends _tstring {
* @var ScalarResult $result * @var ScalarResult $result
* @var ScalarSchema $schema * @var ScalarSchema $schema
*/ */
function verifix(&$value, Result $result, Schema $schema): bool { function normalize(&$value, Result $result, Schema $schema): bool {
if (is_array($value)) { if ($result->normalized) {
} elseif (is_array($value)) {
$result->setNormalized(); $result->setNormalized();
return false;
} elseif (is_string($value)) {
try {
$value = $this->parse($value);
$result->setValid();
return true;
} catch (ValueException $e) {
}
} elseif (is_scalar($value)) { } elseif (is_scalar($value)) {
$value = cl::with($value); $value = cl::with($value);
$result->setValid();
return true; return true;
} }
$result->setInvalid($value, $schema);
return false; return false;
} }

View File

@ -1,14 +1,14 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
use nulib\cl; use nulib\cl;
use nulib\ValueException; use nulib\ValueException;
use nur\prop; use nur\prop;
use nur\sery\wip\schema\_scalar\ScalarResult; use nulib\schema\_scalar\ScalarResult;
use nur\sery\wip\schema\_scalar\ScalarSchema; use nulib\schema\_scalar\ScalarSchema;
use nur\sery\wip\schema\input\Input; use nulib\schema\input\Input;
use nur\sery\wip\schema\Result; use nulib\schema\Result;
use nur\sery\wip\schema\Schema; use nulib\schema\Schema;
class tbool extends _tformatable { class tbool extends _tformatable {
const NAME = "bool"; const NAME = "bool";
@ -76,6 +76,10 @@ class tbool extends _tformatable {
return [false, true, null]; return [false, true, null];
} }
function getNullValue() {
return $this->nullable? null: false;
}
function isAvailable(Input $input, $valueKey): bool { function isAvailable(Input $input, $valueKey): bool {
return $input->isAvailable($valueKey); return $input->isAvailable($valueKey);
} }
@ -99,23 +103,14 @@ class tbool extends _tformatable {
* @var ScalarResult $result * @var ScalarResult $result
* @var ScalarSchema $schema * @var ScalarSchema $schema
*/ */
function verifix(&$value, Result $result, Schema $schema): bool { function normalize(&$value, Result $result, Schema $schema): bool {
if (is_bool($value)) { if ($result->normalized) {
} elseif (is_bool($value)) {
$result->setNormalized(); $result->setNormalized();
return false;
} elseif (is_string($value)) {
try {
$value = $this->parse($value);
$result->setValid();
return true;
} catch (ValueException $e) {
}
} elseif (is_scalar($value)) { } elseif (is_scalar($value)) {
$value = boolval($value); $value = boolval($value);
$result->setValid();
return true; return true;
} }
$result->setInvalid($value, $schema);
return false; return false;
} }

View File

@ -1,68 +0,0 @@
<?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 {
const NAME = "callable";
const ALIASES = ["func", "function"];
static function ensure_callable(&$callable): void {
$callable = func::ensure($callable);
}
static function ensure_ncallable(&$callable): void {
if ($callable !== null) self::ensure_callable($callable);
}
function getClass(): string {
return func::class;
}
function isValid($value, ?bool &$normalized=null): bool {
$normalized = is_callable($value);
return func::check($value);
}
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;
} elseif (is_string($value)) {
try {
$value = $this->parse($value);
$result->setValid();
return true;
} catch (ValueException $e) {
}
}
$result->setInvalid($value, $schema);
return false;
}
function format($value, $format=null): string {
}
}

View File

@ -1,11 +1,11 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
use nulib\php\content\c; use nulib\php\content\c;
use nur\sery\wip\schema\_scalar\ScalarResult; use nulib\schema\_scalar\ScalarResult;
use nur\sery\wip\schema\_scalar\ScalarSchema; use nulib\schema\_scalar\ScalarSchema;
use nur\sery\wip\schema\Result; use nulib\schema\Result;
use nur\sery\wip\schema\Schema; use nulib\schema\Schema;
abstract class tcontent extends _tunion { abstract class tcontent extends _tunion {
const NAME = "content"; const NAME = "content";
@ -23,9 +23,13 @@ abstract class tcontent extends _tunion {
return "string|array"; return "string|array";
} }
function getNullValue() {
return $this->nullable? null: [];
}
function isValid($value, ?bool &$normalized=null): bool { function isValid($value, ?bool &$normalized=null): bool {
$normalized = is_string($value) || is_array($value); $normalized = is_string($value) || is_array($value);
return is_scalar($value) || is_array($value); return $normalized || is_scalar($value);
} }
function parse(string $value) { function parse(string $value) {
@ -36,18 +40,15 @@ abstract class tcontent extends _tunion {
* @var ScalarResult $result * @var ScalarResult $result
* @var ScalarSchema $schema * @var ScalarSchema $schema
*/ */
function verifix(&$value, Result $result, Schema $schema): bool { function normalize(&$value, Result $result, Schema $schema): bool {
if (is_string($value) || is_array($value)) { if ($result->normalized) {
} elseif (is_string($value) || is_array($value)) {
$result->setNormalized(); $result->setNormalized();
return false;
} elseif (is_scalar($value)) { } elseif (is_scalar($value)) {
$value = strval($value); $value = strval($value);
$result->setValid();
return true; return true;
} else {
$result->setInvalid($value, $schema);
return false;
} }
return false;
} }
function format($value, $format=null): string { function format($value, $format=null): string {

View File

@ -1,11 +1,11 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
use nulib\ValueException; use nulib\ValueException;
use nur\sery\wip\schema\_scalar\ScalarResult; use nulib\schema\_scalar\ScalarResult;
use nur\sery\wip\schema\_scalar\ScalarSchema; use nulib\schema\_scalar\ScalarSchema;
use nur\sery\wip\schema\Result; use nulib\schema\Result;
use nur\sery\wip\schema\Schema; use nulib\schema\Schema;
class tfloat extends _tformatable { class tfloat extends _tformatable {
const NAME = "float"; const NAME = "float";
@ -24,6 +24,10 @@ class tfloat extends _tformatable {
return "float"; return "float";
} }
function getNullValue() {
return $this->nullable? null: 0.0;
}
function isValid($value, ?bool &$normalized=null): bool { function isValid($value, ?bool &$normalized=null): bool {
$normalized = is_float($value); $normalized = is_float($value);
return is_scalar($value); return is_scalar($value);
@ -43,23 +47,14 @@ class tfloat extends _tformatable {
* @var ScalarResult $result * @var ScalarResult $result
* @var ScalarSchema $schema * @var ScalarSchema $schema
*/ */
function verifix(&$value, Result $result, Schema $schema): bool { function normalize(&$value, Result $result, Schema $schema): bool {
if (is_float($value)) { if ($result->normalized) {
} elseif (is_float($value)) {
$result->setNormalized(); $result->setNormalized();
return false;
} elseif (is_string($value)) {
try {
$value = $this->parse($value);
$result->setValid();
return true;
} catch (ValueException $e) {
}
} elseif (is_scalar($value)) { } elseif (is_scalar($value)) {
$value = floatval($value); $value = floatval($value);
$result->setValid();
return true; return true;
} }
$result->setInvalid($value, $schema);
return false; return false;
} }
} }

View File

@ -0,0 +1,63 @@
<?php
namespace nulib\schema\types;
use Exception;
use nulib\php\func;
use nulib\ValueException;
use nulib\schema\_scalar\ScalarResult;
use nulib\schema\_scalar\ScalarSchema;
use nulib\schema\Result;
use nulib\schema\Schema;
class tfunc extends _tsimple {
const NAME = "func";
const ALIASES = ["function", "callable"];
static function ensure_func(&$func): void {
$func = func::ensure($func);
}
static function ensure_nfunc(&$func): void {
if ($func !== null) self::ensure_func($func);
}
function getClass(): string {
return func::class;
}
function getNullValue() {
return null;
}
function isValid($value, ?bool &$normalized=null): bool {
$normalized = $value instanceof func;
return func::check($value);
}
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 normalize(&$value, Result $result, Schema $schema): bool {
if ($result->normalized) {
} elseif ($value instanceof func) {
$result->setNormalized();
} elseif (is_callable($value)) {
$value = func::with($value);
return true;
}
return false;
}
function format($value, $format=null): string {
}
}

View File

@ -1,12 +1,12 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
use nulib\ValueException; use nulib\ValueException;
use nur\sery\wip\schema\_scalar\ScalarResult; use nulib\schema\_scalar\ScalarResult;
use nur\sery\wip\schema\_scalar\ScalarSchema; use nulib\schema\_scalar\ScalarSchema;
use nur\sery\wip\schema\input\Input; use nulib\schema\input\Input;
use nur\sery\wip\schema\Result; use nulib\schema\Result;
use nur\sery\wip\schema\Schema; use nulib\schema\Schema;
class tgeneric extends _tsimple { class tgeneric extends _tsimple {
function __construct(string $class, bool $nullable, ?array $params=null) { function __construct(string $class, bool $nullable, ?array $params=null) {
@ -20,6 +20,10 @@ class tgeneric extends _tsimple {
return $this->class; return $this->class;
} }
function getNullValue() {
return null;
}
function isAvailable(Input $input, $valueKey): bool { function isAvailable(Input $input, $valueKey): bool {
return $input->isAvailable($valueKey); return $input->isAvailable($valueKey);
} }
@ -29,8 +33,8 @@ class tgeneric extends _tsimple {
} }
function isValid($value, ?bool &$normalized=null): bool { function isValid($value, ?bool &$normalized=null): bool {
$normalized = true; $normalized = $value instanceof $this->class;
return $value instanceof $this->class; return $normalized;
} }
function parse(string $value) { function parse(string $value) {
@ -41,8 +45,8 @@ class tgeneric extends _tsimple {
* @var ScalarResult $result * @var ScalarResult $result
* @var ScalarSchema $schema * @var ScalarSchema $schema
*/ */
function verifix(&$value, Result $result, Schema $schema): bool { function normalize(&$value, Result $result, Schema $schema): bool {
$result->setNormalized(); if (!$result->normalized) $result->setNormalized();
return false; return false;
} }

View File

@ -1,11 +1,11 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
use nulib\ValueException; use nulib\ValueException;
use nur\sery\wip\schema\_scalar\ScalarResult; use nulib\schema\_scalar\ScalarResult;
use nur\sery\wip\schema\_scalar\ScalarSchema; use nulib\schema\_scalar\ScalarSchema;
use nur\sery\wip\schema\Result; use nulib\schema\Result;
use nur\sery\wip\schema\Schema; use nulib\schema\Schema;
class tint extends _tformatable { class tint extends _tformatable {
const NAME = "int"; const NAME = "int";
@ -26,6 +26,10 @@ class tint extends _tformatable {
return "int"; return "int";
} }
function getNullValue() {
return $this->nullable? null: 0;
}
function isValid($value, ?bool &$normalized=null): bool { function isValid($value, ?bool &$normalized=null): bool {
$normalized = is_int($value); $normalized = is_int($value);
return is_scalar($value); return is_scalar($value);
@ -45,23 +49,14 @@ class tint extends _tformatable {
* @var ScalarResult $result * @var ScalarResult $result
* @var ScalarSchema $schema * @var ScalarSchema $schema
*/ */
function verifix(&$value, Result $result, Schema $schema): bool { function normalize(&$value, Result $result, Schema $schema): bool {
if (is_int($value)) { if ($result->normalized) {
} elseif (is_int($value)) {
$result->setNormalized(); $result->setNormalized();
return false;
} elseif (is_string($value)) {
try {
$value = $this->parse($value);
$result->setValid();
return true;
} catch (ValueException $e) {
}
} elseif (is_scalar($value)) { } elseif (is_scalar($value)) {
$value = intval($value); $value = intval($value);
$result->setValid();
return true; return true;
} }
$result->setInvalid($value, $schema);
return false; return false;
} }
} }

View File

@ -1,10 +1,10 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
use nur\sery\wip\schema\_scalar\ScalarResult; use nulib\schema\_scalar\ScalarResult;
use nur\sery\wip\schema\_scalar\ScalarSchema; use nulib\schema\_scalar\ScalarSchema;
use nur\sery\wip\schema\Result; use nulib\schema\Result;
use nur\sery\wip\schema\Schema; use nulib\schema\Schema;
class tkey extends _tunion { class tkey extends _tunion {
const NAME = "key"; const NAME = "key";
@ -23,9 +23,13 @@ class tkey extends _tunion {
return "string|int"; return "string|int";
} }
function getNullValue() {
return $this->nullable? null: "";
}
function isValid($value, ?bool &$normalized=null): bool { function isValid($value, ?bool &$normalized=null): bool {
$normalized = is_string($value) || is_int($value); $normalized = is_string($value) || is_int($value);
return is_scalar($value); return $normalized || is_scalar($value);
} }
function parse(string $value) { function parse(string $value) {
@ -36,18 +40,15 @@ class tkey extends _tunion {
* @var ScalarResult $result * @var ScalarResult $result
* @var ScalarSchema $schema * @var ScalarSchema $schema
*/ */
function verifix(&$value, Result $result, Schema $schema): bool { function normalize(&$value, Result $result, Schema $schema): bool {
if (is_string($value) || is_int($value)) { if ($result->normalized) {
} elseif (is_string($value) || is_int($value)) {
$result->setNormalized(); $result->setNormalized();
return false;
} elseif (is_scalar($value)) { } elseif (is_scalar($value)) {
$value = strval($value); $value = strval($value);
$result->setValid();
return true; return true;
} else {
$result->setInvalid($value, $schema);
return false;
} }
return false;
} }
function format($value, $format=null): string { function format($value, $format=null): string {

View File

@ -1,11 +1,11 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
use nur\sery\wip\schema\_scalar\ScalarResult; use nulib\schema\_scalar\ScalarResult;
use nur\sery\wip\schema\_scalar\ScalarSchema; use nulib\schema\_scalar\ScalarSchema;
use nur\sery\wip\schema\input\Input; use nulib\schema\input\Input;
use nur\sery\wip\schema\Result; use nulib\schema\Result;
use nur\sery\wip\schema\Schema; use nulib\schema\Schema;
class tmixed extends _tsimple { class tmixed extends _tsimple {
const NAME = "mixed"; const NAME = "mixed";
@ -14,6 +14,10 @@ class tmixed extends _tsimple {
return "mixed"; return "mixed";
} }
function getNullValue() {
return null;
}
function isAvailable(Input $input, $valueKey): bool { function isAvailable(Input $input, $valueKey): bool {
return $input->isAvailable($valueKey); return $input->isAvailable($valueKey);
} }
@ -35,8 +39,8 @@ class tmixed extends _tsimple {
* @var ScalarResult $result * @var ScalarResult $result
* @var ScalarSchema $schema * @var ScalarSchema $schema
*/ */
function verifix(&$value, Result $result, Schema $schema): bool { function normalize(&$value, Result $result, Schema $schema): bool {
$result->setNormalized(); if (!$result->normalized) $result->setNormalized();
return false; return false;
} }

View File

@ -1,10 +1,10 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
use nur\sery\wip\schema\_scalar\ScalarResult; use nulib\schema\_scalar\ScalarResult;
use nur\sery\wip\schema\_scalar\ScalarSchema; use nulib\schema\_scalar\ScalarSchema;
use nur\sery\wip\schema\Result; use nulib\schema\Result;
use nur\sery\wip\schema\Schema; use nulib\schema\Schema;
class tpkey extends _tunion { class tpkey extends _tunion {
const NAME = "pkey"; const NAME = "pkey";
@ -28,9 +28,13 @@ class tpkey extends _tunion {
return "string|int|array"; return "string|int|array";
} }
function getNullValue() {
return $this->nullable? null: [];
}
function isValid($value, ?bool &$normalized=null): bool { function isValid($value, ?bool &$normalized=null): bool {
$normalized = is_string($value) || is_int($value) || is_array($value); $normalized = is_string($value) || is_int($value) || is_array($value);
return is_scalar($value) || is_array($value); return $normalized || is_scalar($value);
} }
function parse(string $value) { function parse(string $value) {
@ -41,18 +45,15 @@ class tpkey extends _tunion {
* @var ScalarResult $result * @var ScalarResult $result
* @var ScalarSchema $schema * @var ScalarSchema $schema
*/ */
function verifix(&$value, Result $result, Schema $schema): bool { function normalize(&$value, Result $result, Schema $schema): bool {
if (is_string($value) || is_int($value) || is_array($value)) { if ($result->normalized) {
} elseif (is_string($value) || is_int($value) || is_array($value)) {
$result->setNormalized(); $result->setNormalized();
return false;
} elseif (is_scalar($value)) { } elseif (is_scalar($value)) {
$value = strval($value); $value = strval($value);
$result->setValid();
return true; return true;
} else {
$result->setInvalid($value, $schema);
return false;
} }
return false;
} }
function format($value, $format=null): string { function format($value, $format=null): string {

View File

@ -1,7 +1,7 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
use nur\sery\wip\schema\input\Input; use nulib\schema\input\Input;
class traw extends tmixed { class traw extends tmixed {
const NAME = "raw"; const NAME = "raw";

View File

@ -1,11 +1,11 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
use nulib\str; use nulib\str;
use nur\sery\wip\schema\_scalar\ScalarResult; use nulib\schema\_scalar\ScalarResult;
use nur\sery\wip\schema\_scalar\ScalarSchema; use nulib\schema\_scalar\ScalarSchema;
use nur\sery\wip\schema\Result; use nulib\schema\Result;
use nur\sery\wip\schema\Schema; use nulib\schema\Schema;
class trawstring extends _tstring { class trawstring extends _tstring {
const NAME = "rawstring"; const NAME = "rawstring";
@ -24,6 +24,10 @@ class trawstring extends _tstring {
return "string"; return "string";
} }
function getNullValue() {
return $this->nullable? null: "";
}
function isNull($value): bool { function isNull($value): bool {
return $value === null; return $value === null;
} }
@ -44,18 +48,15 @@ class trawstring extends _tstring {
* @var ScalarResult $result * @var ScalarResult $result
* @var ScalarSchema $schema * @var ScalarSchema $schema
*/ */
function verifix(&$value, Result $result, Schema $schema): bool { function normalize(&$value, Result $result, Schema $schema): bool {
if (is_string($value)) { if ($result->normalized) {
} elseif (is_string($value)) {
$result->setNormalized(); $result->setNormalized();
return false;
} elseif (is_scalar($value)) { } elseif (is_scalar($value)) {
$value = strval($value); $value = strval($value);
$result->setValid();
return true; return true;
} else {
$result->setInvalid($value, $schema);
return false;
} }
return false;
} }
function format($value, $format=null): string { function format($value, $format=null): string {

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
class tstring extends trawstring { class tstring extends trawstring {
const NAME = "string"; const NAME = "string";

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
class ttext extends trawstring { class ttext extends trawstring {
const NAME = "text"; const NAME = "text";

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\web\content; namespace nulib\web\content;
use nulib\A; use nulib\A;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\web\content; namespace nulib\web\content;
/** /**
* Class v: classe outil pour gérer du contenu pour le web * Class v: classe outil pour gérer du contenu pour le web

View File

@ -1,5 +0,0 @@
<?php
namespace nulib;
class app extends \nur\sery\app {
}

View File

@ -1,5 +0,0 @@
<?php
namespace nulib\app\cli;
abstract class Application extends \nur\sery\app\cli\Application {
}

132
tests/appTest.php Normal file
View File

@ -0,0 +1,132 @@
<?php
namespace nulib {
use nulib\tests\TestCase;
use nulib\impl\config;
use nulib\impl\myapp;
use nulib\impl\MyApplication1;
use nulib\impl\MyApplication2;
class appTest extends TestCase {
function testWith() {
$projdir = config::get_projdir();
$cwd = getcwd();
myapp::reset();
$app1 = myapp::with(MyApplication1::class);
self::assertSame([
"projdir" => $projdir,
"vendor" => [
"bindir" => "$projdir/vendor/bin",
"autoload" => "$projdir/vendor/autoload.php",
],
"appcode" => "nur-sery",
"cwd" => $cwd,
"datadir" => "$projdir/devel",
"etcdir" => "$projdir/devel/etc",
"vardir" => "$projdir/devel/var",
"logdir" => "$projdir/devel/log",
"profile" => "devel",
"appgroup" => null,
"name" => "my-application1",
"title" => null,
], $app1->getParams());
$app2 = myapp::with(MyApplication2::class, $app1);
self::assertSame([
"projdir" => $projdir,
"vendor" => [
"bindir" => "$projdir/vendor/bin",
"autoload" => "$projdir/vendor/autoload.php",
],
"appcode" => "nur-sery",
"cwd" => $cwd,
"datadir" => "$projdir/devel",
"etcdir" => "$projdir/devel/etc",
"vardir" => "$projdir/devel/var",
"logdir" => "$projdir/devel/log",
"profile" => "devel",
"appgroup" => null,
"name" => "my-application2",
"title" => null,
], $app2->getParams());
}
function testInit() {
$projdir = config::get_projdir();
$cwd = getcwd();
myapp::reset();
myapp::init(MyApplication1::class);
self::assertSame([
"projdir" => $projdir,
"vendor" => [
"bindir" => "$projdir/vendor/bin",
"autoload" => "$projdir/vendor/autoload.php",
],
"appcode" => "nur-sery",
"cwd" => $cwd,
"datadir" => "$projdir/devel",
"etcdir" => "$projdir/devel/etc",
"vardir" => "$projdir/devel/var",
"logdir" => "$projdir/devel/log",
"profile" => "devel",
"appgroup" => null,
"name" => "my-application1",
"title" => null,
], myapp::get()->getParams());
myapp::init(MyApplication2::class);
self::assertSame([
"projdir" => $projdir,
"vendor" => [
"bindir" => "$projdir/vendor/bin",
"autoload" => "$projdir/vendor/autoload.php",
],
"appcode" => "nur-sery",
"cwd" => $cwd,
"datadir" => "$projdir/devel",
"etcdir" => "$projdir/devel/etc",
"vardir" => "$projdir/devel/var",
"logdir" => "$projdir/devel/log",
"profile" => "devel",
"appgroup" => null,
"name" => "my-application2",
"title" => null,
], myapp::get()->getParams());
}
}
}
namespace nulib\impl {
use nulib\app\cli\Application;
use nulib\os\path;
use nulib\app;
class config {
const PROJDIR = __DIR__.'/..';
static function get_projdir(): string {
return path::abspath(self::PROJDIR);
}
}
class myapp extends app {
static function reset(): void {
self::$app = null;
}
}
class MyApplication1 extends Application {
const PROJDIR = config::PROJDIR;
function main() {
}
}
class MyApplication2 extends Application {
const PROJDIR = null;
function main() {
}
}
}

View File

@ -0,0 +1,215 @@
<?php
namespace nulib\php\access;
use nulib\tests\TestCase;
use stdClass;
class KeyAccessTest extends TestCase {
function testValueAccess() {
$default = new stdClass();
#
$i = null;
$a = new KeyAccess($i);
self::assertFalse($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$i = false;
$a = new KeyAccess($i);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame(false, $a->get($default));
$i = "";
$a = new KeyAccess($i);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame("", $a->get($default));
#
$i = null;
$a = new KeyAccess($i, null, ["allow_null" => false]);
self::assertFalse($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$i = null;
$a = new KeyAccess($i, null, ["allow_null" => true]);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame(null, $a->get($default));
#
$i = false;
$a = new KeyAccess($i, null, ["allow_false" => false]);
self::assertTrue($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$i = false;
$a = new KeyAccess($i, null, ["allow_false" => true]);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame(false, $a->get($default));
#
$i = "";
$a = new KeyAccess($i, null, ["allow_empty" => false]);
self::assertTrue($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$i = "";
$a = new KeyAccess($i, null, ["allow_empty" => true]);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame("", $a->get($default));
}
function testArrayAccess() {
$default = new stdClass();
$array = ["null" => null, "false" => false, "empty" => ""];
#
$a = new KeyAccess($array, "inexistant");
self::assertFalse($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$a = new KeyAccess($array, "null");
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame(null, $a->get($default));
$a = new KeyAccess($array, "false");
self::assertTrue($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$a = new KeyAccess($array, "empty");
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame("", $a->get($default));
#
$a = new KeyAccess($array, "null", ["allow_null" => false]);
self::assertTrue($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$a = new KeyAccess($array, "null", ["allow_null" => true]);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame(null, $a->get($default));
#
$a = new KeyAccess($array, "false", ["allow_false" => false]);
self::assertTrue($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$a = new KeyAccess($array, "false", ["allow_false" => true]);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame(false, $a->get($default));
#
$a = new KeyAccess($array, "empty", ["allow_empty" => false]);
self::assertTrue($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$a = new KeyAccess($array, "empty", ["allow_empty" => true]);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame("", $a->get($default));
}
private function _ensureAssoc(?array $orig, ?array $expected, array $keys, ?array $params=null) {
$v = $orig; $a = new KeyAccess($v);
$a->ensureAssoc($keys, $params);
self::assertSame($expected, $v);
}
function testEnsureAssoc() {
$keys = ["a", "b", "c"];
$this->_ensureAssoc(null, null, $keys);
$this->_ensureAssoc([], [], $keys);
$this->_ensureAssoc([1], ["a" => 1], $keys);
$this->_ensureAssoc([1, 2, 3], ["a" => 1, "b" => 2, "c" => 3], $keys);
$this->_ensureAssoc([1, 2, 3, 4], [3 => 4, "a" => 1, "b" => 2, "c" => 3], $keys);
$this->_ensureAssoc(["c" => 3, 1], ["c" => 3, "a" => 1], $keys);
$this->_ensureAssoc(["c" => 3, "b" => 2, 1], ["c" => 3, "b" => 2, "a" => 1], $keys);
$this->_ensureAssoc(["c" => 3, "b" => 2, "a" => 1], ["c" => 3, "b" => 2, "a" => 1], $keys);
$this->_ensureAssoc(["a" => 1, 2], ["a" => 1, "b" => 2], $keys);
$this->_ensureAssoc([2, "a" => 1], ["a" => 1, "b" => 2], $keys);
$keys = [0, "a", "b"];
$this->_ensureAssoc([1], [1], $keys);
$this->_ensureAssoc([1, 2], [1, "a" => 2], $keys);
}
private function _ensureKeys(?array $orig, ?array $expected, array $defaults, ?array $params=null) {
$v = $orig; $a = new KeyAccess($v);
$a->ensureKeys($defaults, $params);
self::assertSame($expected, $v);
}
function testEnsureKeys() {
$defaults = ["a" => false, "b" => false, "c" => false];
$this->_ensureKeys(null, ["a" => false, "b" => false, "c" => false], $defaults);
$this->_ensureKeys([], ["a" => false, "b" => false, "c" => false], $defaults);
$this->_ensureKeys(["a" => 1], ["a" => 1, "b" => false, "c" => false], $defaults);
$this->_ensureKeys(["a" => 1, "b" => 2, "c" => 3], ["a" => 1, "b" => 2, "c" => 3], $defaults);
$this->_ensureKeys(["x"], ["x", "a" => false, "b" => false, "c" => false], $defaults);
$this->_ensureKeys(["x", "a" => 1], ["x", "a" => 1, "b" => false, "c" => false], $defaults);
$this->_ensureKeys(["a" => 1, "x"], ["a" => 1, "x", "b" => false, "c" => false], $defaults);
$this->_ensureKeys(["a" => 1, "b" => 2, "c" => 3, "x"], ["a" => 1, "b" => 2, "c" => 3, "x"], $defaults);
}
private function _ensureOrder(?array $orig, ?array $expected, array $keys, ?array $params=null) {
$v = $orig; $a = new KeyAccess($v);
$a->ensureOrder($keys, $params);
self::assertSame($expected, $v);
}
function testEnsureOrder() {
$keys = ["a", "b", "c"];
$this->_ensureOrder(null, null, $keys);
$this->_ensureOrder([], [], $keys);
$this->_ensureOrder([1], [1], $keys);
$this->_ensureOrder(["b" => 2, "a" => 1], ["a" => 1, "b" => 2], $keys);
$this->_ensureOrder(["c" => 3, "a" => 1], ["a" => 1, "c" => 3], $keys);
}
private function _ensureAssocKeysOrder(?array $orig, ?array $expected, array $defaults, ?array $params=null) {
$v = $orig; $a = new KeyAccess($v);
$keys = array_keys($defaults);
$a->ensureAssoc($keys, $params);
$a->ensureKeys($defaults, $params);
$a->ensureOrder($keys, $params);
self::assertSame($expected, $v);
}
function testEnsureAssocKeysOrder() {
$defaults = ["a" => false, "b" => false, "c" => false];
$this->_ensureAssocKeysOrder(null, ["a" => false, "b" => false, "c" => false], $defaults);
$this->_ensureAssocKeysOrder([], ["a" => false, "b" => false, "c" => false], $defaults);
$this->_ensureAssocKeysOrder([1], ["a" => 1, "b" => false, "c" => false], $defaults);
$this->_ensureAssocKeysOrder([1, 2, 3], ["a" => 1, "b" => 2, "c" => 3], $defaults);
$this->_ensureAssocKeysOrder([1, 2, 3, 4], ["a" => 1, "b" => 2, "c" => 3, 4], $defaults);
$this->_ensureAssocKeysOrder([1, 2, 3, 4], ["a" => 1, "b" => 2, "c" => 3, 3 => 4], $defaults, [
"preserve_keys" => true,
]);
$this->_ensureAssocKeysOrder(["c" => 3, 1], ["a" => 1, "b" => false, "c" => 3], $defaults);
$this->_ensureAssocKeysOrder(["c" => 3, "b" => 2, 1], ["a" => 1, "b" => 2, "c" => 3], $defaults);
$this->_ensureAssocKeysOrder(["c" => 3, "b" => 2, "a" => 1], ["a" => 1, "b" => 2, "c" => 3], $defaults);
$this->_ensureAssocKeysOrder(["a" => 1, 2], ["a" => 1, "b" => 2, "c" => false], $defaults);
$this->_ensureAssocKeysOrder([2, "a" => 1], ["a" => 1, "b" => 2, "c" => false], $defaults);
$this->_ensureAssocKeysOrder([1], ["x_a" => 1, "x_b" => false, "x_c" => false], $defaults, [
"key_prefix" => "x_",
]);
}
}

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\php\coll; namespace nulib\php\coll;
use Exception; use Exception;
use nulib\cl; use nulib\cl;

View File

@ -1,9 +1,9 @@
<?php <?php
namespace nur\sery\wip\php\content; namespace nulib\php\content;
use nulib\php\content\c; use nulib\php\content\c;
use nur\sery\wip\php\content\impl\html; use nulib\php\content\impl\html;
use nur\sery\wip\web\content\v; use nulib\web\content\v;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
class cTest extends TestCase { class cTest extends TestCase {

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\php\content\impl; namespace nulib\php\content\impl;
use nulib\php\content\IContent; use nulib\php\content\IContent;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\php\content\impl; namespace nulib\php\content\impl;
use nulib\php\content\IPrintable; use nulib\php\content\IPrintable;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\php\content\impl; namespace nulib\php\content\impl;
use nulib\php\content\c; use nulib\php\content\c;
use nulib\php\content\IContent; use nulib\php\content\IContent;

View File

@ -1,5 +1,5 @@
<?php <?php
namespace nur\sery\wip\php\content\impl; namespace nulib\php\content\impl;
class html { class html {
const H1 = [self::class, "h1"]; const H1 = [self::class, "h1"];

View File

@ -0,0 +1,353 @@
<?php
namespace nulib\schema\_assoc;
use nulib\ext\yaml;
use nulib\tests\TestCase;
use nulib\ValueException;
use nulib\schema\_scalar\ScalarSchemaTest;
use nulib\schema\Schema;
class AssocSchemaTest extends TestCase {
const NULL_SCHEMA = [
"" => [
"assoc",
"compute_func" => null,
"validate_func" => null,
"ensure_array" => null,
"ensure_assoc" => null,
"ensure_keys" => null,
"ensure_order" => null,
],
"schema" => null,
"type" => [null],
"default" => null,
"title" => null,
"required" => false,
"nullable" => true,
"desc" => null,
"analyzer_func" => null,
"extractor_func" => null,
"parser_func" => null,
"normalizer_func" => null,
"messages" => null,
"formatter_func" => null,
"format" => null,
"name" => null,
"pkey" => null,
"header" => null,
"computed" => null,
];
static function schema(array $definition, array $keyDefinitions): array {
$definition = array_merge(self::NULL_SCHEMA, $definition, ["schema" => []]);
foreach ($keyDefinitions as $key => $keydef) {
$definition["schema"][$key] = array_merge(ScalarSchemaTest::NULL_SCHEMA, $keydef);
}; unset($subdef);
return $definition;
}
function testNormalize() {
self::assertSame(self::schema([
"type" => ["array"], "nullable" => true,
], [
"a" => [
"type" => ["string"], "nullable" => false,
"name" => "a", "pkey" => "a", "header" => "a",
],
]), AssocSchema::normalize_definition(["a" => "string"]));
self::assertSame(self::schema([
"type" => ["array"], "nullable" => true,
], [
"a" => [
"type" => ["string"], "nullable" => false,
"name" => "a", "pkey" => "a", "header" => "a",
],
"b" => [
"type" => ["int"], "nullable" => false,
"name" => "b", "pkey" => "b", "header" => "b",
],
"c" => [
"type" => ["bool"], "nullable" => false,
"name" => "c", "pkey" => "c", "header" => "c",
],
]), AssocSchema::normalize_definition([
"a" => "string",
"b" => "int",
"c" => "bool",
]));
}
function testConstructor() {
$schema = new AssocSchema([
"a" => "string",
"b" => "int",
"c" => "bool",
]);
self::assertSame(self::schema([
"type" => ["array"], "nullable" => true,
], [
"a" => [
"type" => ["string"], "nullable" => false,
"name" => "a", "pkey" => "a", "header" => "a",
],
"b" => [
"type" => ["int"], "nullable" => false,
"name" => "b", "pkey" => "b", "header" => "b",
],
"c" => [
"type" => ["bool"], "nullable" => false,
"name" => "c", "pkey" => "c", "header" => "c",
],
]), $schema->getDefinition());
//yaml::dump($schema->getDefinition());
}
function testWrapper() {
$schema = new AssocSchema([
"a" => "?string",
"b" => "?int",
"c" => "?bool",
]);
$array = ["a" => " string ", "b" => " 42 ", "c" => false];
$schema->getWrapper($array);
self::assertSame([
"a" => "string",
"b" => 42,
"c" => false,
], $array);
###########################################################################
$schema = new AssocSchema([
"a" => "string",
"b" => "int",
"c" => "bool",
]);
$array = ["a" => " string "];
$schema->getWrapper($array);
self::assertSame([
"a" => "string",
"b" => 0,
"c" => false,
], $array);
$array = ["c" => false, "a" => " string "];
$schema->getWrapper($array);
self::assertSame([
"a" => "string",
"b" => 0,
"c" => false,
], $array);
$array = ["a" => " string "];
$schema->getWrapper($array, null, ["ensure_order" => false]);
self::assertSame([
"a" => "string",
"b" => 0,
"c" => false,
], $array);
$array = ["c" => false, "a" => " string "];
$schema->getWrapper($array, null, ["ensure_order" => false]);
self::assertSame([
"c" => false,
"a" => "string",
"b" => 0,
], $array);
$array = ["a" => " string "];
$schema->getWrapper($array, null, ["ensure_keys" => false]);
self::assertSame([
"a" => "string",
], $array);
$array = ["c" => false, "a" => " string "];
$schema->getWrapper($array, null, ["ensure_keys" => false]);
self::assertSame([
"a" => "string",
"c" => false,
], $array);
}
const STRING_SCHEMA = [
"s" => "string",
"f" => "string",
"m" => "string",
];
const NSTRING_SCHEMA = [
"s" => "?string",
"f" => "?string",
"m" => "?string",
];
const RSTRING_SCHEMA = [
"s" => ["string", "required" => true],
"f" => ["string", "required" => true],
"m" => ["string", "required" => true],
];
const RNSTRING_SCHEMA = [
"s" => ["?string", "required" => true],
"f" => ["?string", "required" => true],
"m" => ["?string", "required" => true],
];
const STRINGS = ["s" => "string", "f" => false];
const NSTRINGS = ["s" => null, "f" => null];
function testString() {
/** @var AssocSchema $schema */
$schema = Schema::ns(self::STRING_SCHEMA);
$array = self::STRINGS;
$wrapper = $schema->getWrapper($array, null, ["throw" => false]);
self::assertSame(["s" => "string", "f" => false, "m" => ""], $array);
$result = $wrapper->getResult("s");
self::assertTrue($result->normalized);
$result = $wrapper->getResult("f");
self::assertTrue($result->present);
self::assertFalse($result->available);
$result = $wrapper->getResult("m");
self::assertFalse($result->present);
self::assertNotException(function() use ($schema) {
$array = self::STRINGS;
$schema->getWrapper($array);
});
$array = self::NSTRINGS;
$wrapper = $schema->getWrapper($array, null, ["throw" => false]);
self::assertSame(["s" => null, "f" => null, "m" => ""], $array);
$result = $wrapper->getResult("s");
self::assertFalse($result->valid);
self::assertSame("null", $result->messageKey);
$result = $wrapper->getResult("f");
self::assertFalse($result->valid);
self::assertSame("null", $result->messageKey);
$result = $wrapper->getResult("m");
self::assertFalse($result->present);
self::assertException(ValueException::class, function() use ($schema) {
$array = self::NSTRINGS;
$schema->getWrapper($array);
});
}
function testNstring() {
/** @var AssocSchema $schema */
$schema = Schema::ns(self::NSTRING_SCHEMA);
$array = self::STRINGS;
$wrapper = $schema->getWrapper($array, null, ["throw" => false]);
self::assertSame(["s" => "string", "f" => false, "m" => null], $array);
$result = $wrapper->getResult("s");
self::assertTrue($result->normalized);
$result = $wrapper->getResult("f");
self::assertTrue($result->present);
self::assertFalse($result->available);
$result = $wrapper->getResult("m");
self::assertFalse($result->present);
self::assertNotException(function() use ($schema) {
$array = self::STRINGS;
$schema->getWrapper($array);
});
$array = self::NSTRINGS;
$wrapper = $schema->getWrapper($array, null, ["throw" => false]);
self::assertSame(["s" => null, "f" => null, "m" => null], $array);
$result = $wrapper->getResult("s");
self::assertTrue($result->normalized);
$result = $wrapper->getResult("f");
self::assertTrue($result->normalized);
$result = $wrapper->getResult("m");
self::assertFalse($result->present);
self::assertNotException(function() use ($schema) {
$array = self::NSTRINGS;
$schema->getWrapper($array);
});
}
function testRstring() {
/** @var AssocSchema $schema */
$schema = Schema::ns(self::RSTRING_SCHEMA);
$array = self::STRINGS;
$wrapper = $schema->getWrapper($array, null, ["throw" => false]);
self::assertSame(["s" => "string", "f" => false, "m" => ""], $array);
$result = $wrapper->getResult("s");
self::assertTrue($result->normalized);
$result = $wrapper->getResult("f");
self::assertTrue($result->present);
self::assertFalse($result->available);
self::assertSame("unavailable", $result->messageKey);
$result = $wrapper->getResult("m");
self::assertFalse($result->present);
self::assertSame("missing", $result->messageKey);
self::assertException(ValueException::class, function() use ($schema) {
$array = self::STRINGS;
$schema->getWrapper($array);
});
$array = self::NSTRINGS;
$wrapper = $schema->getWrapper($array, null, ["throw" => false]);
self::assertSame(["s" => null, "f" => null, "m" => ""], $array);
$result = $wrapper->getResult("s");
self::assertFalse($result->valid);
self::assertSame("null", $result->messageKey);
$result = $wrapper->getResult("f");
self::assertFalse($result->valid);
self::assertSame("null", $result->messageKey);
$result = $wrapper->getResult("m");
self::assertFalse($result->present);
self::assertSame("missing", $result->messageKey);
self::assertException(ValueException::class, function() use ($schema) {
$array = self::NSTRINGS;
$schema->getWrapper($array);
});
}
function testRnstring() {
/** @var AssocSchema $schema */
$schema = Schema::ns(self::RNSTRING_SCHEMA);
$array = self::STRINGS;
$wrapper = $schema->getWrapper($array, null, ["throw" => false]);
self::assertSame(["s" => "string", "f" => false, "m" => null], $array);
$result = $wrapper->getResult("s");
self::assertTrue($result->normalized);
$result = $wrapper->getResult("f");
self::assertTrue($result->present);
self::assertFalse($result->available);
self::assertSame("unavailable", $result->messageKey);
$result = $wrapper->getResult("m");
self::assertFalse($result->present);
self::assertSame("missing", $result->messageKey);
self::assertException(ValueException::class, function() use ($schema) {
$array = self::STRINGS;
$schema->getWrapper($array);
});
$array = self::NSTRINGS;
$wrapper = $schema->getWrapper($array, null, ["throw" => false]);
self::assertSame(["s" => null, "f" => null, "m" => null], $array);
$result = $wrapper->getResult("s");
self::assertTrue($result->normalized);
$result = $wrapper->getResult("f");
self::assertTrue($result->normalized);
$result = $wrapper->getResult("m");
self::assertFalse($result->present);
self::assertSame("missing", $result->messageKey);
self::assertException(ValueException::class, function() use ($schema) {
$array = self::NSTRINGS;
$schema->getWrapper($array);
});
}
}

View File

@ -0,0 +1,68 @@
<?php
namespace nulib\schema\_scalar;
use nulib\tests\TestCase;
use nulib\schema\SchemaException;
class ScalarSchemaTest extends TestCase {
const NULL_SCHEMA = [
"type" => [null],
"default" => null,
"title" => null,
"required" => false,
"nullable" => true,
"desc" => null,
"analyzer_func" => null,
"extractor_func" => null,
"parser_func" => null,
"normalizer_func" => null,
"messages" => null,
"formatter_func" => null,
"format" => null,
"" => [
"scalar",
"compute_func" => null,
"validate_func" => null,
],
"schema" => null,
"name" => null,
"pkey" => null,
"header" => null,
"computed" => null,
];
static function schema(array $schema): array {
return array_merge(self::NULL_SCHEMA, $schema);
}
function testNormalize() {
self::assertSame(self::NULL_SCHEMA, ScalarSchema::normalize_definition(null));
self::assertSame(self::NULL_SCHEMA, ScalarSchema::normalize_definition([]));
self::assertSame(self::NULL_SCHEMA, ScalarSchema::normalize_definition([null]));
self::assertException(SchemaException::class, function () {
ScalarSchema::normalize_definition([[]]);
});
self::assertException(SchemaException::class, function () {
ScalarSchema::normalize_definition([[null]]);
});
$string = self::schema(["type" => ["string"], "nullable" => false]);
self::assertSame($string, ScalarSchema::normalize_definition("string"));
self::assertSame($string, ScalarSchema::normalize_definition(["string"]));
$nstring = self::schema(["type" => ["string"]]);
self::assertSame($nstring, ScalarSchema::normalize_definition(["?string"]));
self::assertSame($nstring, ScalarSchema::normalize_definition(["?string|null"]));
self::assertSame($nstring, ScalarSchema::normalize_definition(["string|null"]));
self::assertSame($nstring, ScalarSchema::normalize_definition([["?string", "null"]]));
self::assertSame($nstring, ScalarSchema::normalize_definition([["string", "null"]]));
self::assertSame($nstring, ScalarSchema::normalize_definition([["string", null]]));
$key = self::schema(["type" => ["string", "int"], "nullable" => false]);
self::assertSame($key, ScalarSchema::normalize_definition("string|int"));
$nkey = self::schema(["type" => ["string", "int"], "nullable" => true]);
self::assertSame($nkey, ScalarSchema::normalize_definition("?string|int"));
self::assertSame($nkey, ScalarSchema::normalize_definition("string|?int"));
}
}

View File

@ -0,0 +1,296 @@
<?php
namespace nulib\schema\_scalar;
use nulib\tests\TestCase;
use nulib\ValueException;
use nulib\schema\input\Input;
use stdClass;
class ScalarWrapperTest extends TestCase {
function checkValue(ScalarWrapper $wrapper, $value, bool $present, bool $available, bool $valid, bool $normalized): void {
self::assertSame($value, $wrapper->get(), "value");
self::assertSame($present, $wrapper->isPresent(), "present");
self::assertSame($available, $wrapper->isAvailable(), "available");
self::assertSame($valid, $wrapper->isValid(), "valid");
self::assertSame($normalized, $wrapper->isNormalized(), "normalized");
}
function checkNormalize(ScalarSchema $schema, $orig, bool $normalize, $value, bool $present, bool $available, bool $valid, bool $normalized, ?array $inputParams=null): void {
$wrapper = $schema->getWrapper();
$wrapper->resetParams(["normalize" => $normalize]);
if ($inputParams !== null) $input = new Input($orig, $inputParams);
else $input = $orig;
$wrapper->reset($input);
$this->checkValue($wrapper, $value, $present, $available, $valid, $normalized);
}
function checkException(ScalarSchema $schema, $orig, bool $normalize, string $exceptionClass, ?array $inputParams=null) {
$wrapper = $schema->getWrapper();
if ($inputParams !== null) $orig = new Input($orig, $inputParams);
self::assertException($exceptionClass, function() use ($wrapper, &$orig, $normalize) {
$wrapper->resetParams(["normalize" => $normalize]);
$wrapper->reset($orig);
});
}
function testRaw() {
$schema = new ScalarSchema();
$this->checkNormalize($schema, false, false, false, true, true, true, true);
$this->checkNormalize($schema, false, true, false, true, true, true, true);
$this->checkNormalize($schema, null, false, null, true, true, true, true);
$this->checkNormalize($schema, null, true, null, true, true, true, true);
$obj = new stdClass();
$this->checkNormalize($schema, $obj, false, $obj, true, true, true, true);
$this->checkNormalize($schema, $obj, true, $obj, true, true, true, true);
$schema = new ScalarSchema("raw");
$this->checkNormalize($schema, false, false, false, true, true, true, true);
$this->checkNormalize($schema, false, true, false, true, true, true, true);
$this->checkNormalize($schema, null, false, null, true, true, true, true);
$this->checkNormalize($schema, null, true, null, true, true, true, true);
$obj = new stdClass();
$this->checkNormalize($schema, $obj, false, $obj, true, true, true, true);
$this->checkNormalize($schema, $obj, true, $obj, true, true, true, true);
}
function testMixed() {
$schema = new ScalarSchema("mixed");
$this->checkNormalize($schema, false, false, false, true, true, true, true);
$this->checkNormalize($schema, false, true, false, true, true, true, true);
$this->checkNormalize($schema, null, false, null, true, true, false, false);
$this->checkException($schema, null, true, ValueException::class);
$obj = new stdClass();
$this->checkNormalize($schema, $obj, false, $obj, true, true, true, true);
$this->checkNormalize($schema, $obj, true, $obj, true, true, true, true);
$schema = new ScalarSchema("?mixed");
$this->checkNormalize($schema, false, false, false, true, true, true, true);
$this->checkNormalize($schema, false, true, false, true, true, true, true);
$this->checkNormalize($schema, null, false, null, true, true, true, true);
$this->checkNormalize($schema, null, true, null, true, true, true, true);
$obj = new stdClass();
$this->checkNormalize($schema, $obj, false, $obj, true, true, true, true);
$this->checkNormalize($schema, $obj, true, $obj, true, true, true, true);
}
function testRawstring() {
$schema = new ScalarSchema("rawstring");
$this->checkNormalize($schema, false, false, null, true, false, true, true);
$this->checkNormalize($schema, false, true, null, true, false, true, true);
$this->checkNormalize($schema, null, false, null, true, true, false, false);
$this->checkException($schema, null, true, ValueException::class);
$this->checkNormalize($schema, "", false, "", true, true, true, true);
$this->checkNormalize($schema, "", true, "", true, true, true, true);
$this->checkNormalize($schema, " ", false, " ", true, true, true, true);
$this->checkNormalize($schema, " ", true, " ", true, true, true, true);
$this->checkNormalize($schema, "text", false, "text", true, true, true, true);
$this->checkNormalize($schema, "text", true, "text", true, true, true, true);
$this->checkNormalize($schema, " text ", false, " text ", true, true, true, true);
$this->checkNormalize($schema, " text ", true, " text ", true, true, true, true);
$this->checkNormalize($schema, true, false, true, true, true, true, false);
$this->checkNormalize($schema, true, true, "1", true, true, true, false);
$this->checkNormalize($schema, 42, false, 42, true, true, true, false);
$this->checkNormalize($schema, 42, true, "42", true, true, true, false);
$this->checkNormalize($schema, [], false, [], true, true, false, false);
$this->checkException($schema, [], true, ValueException::class);
## Tester valeur par défaut
$schema = new ScalarSchema(["rawstring", null]);
$this->checkNormalize($schema, false, false, null, true, false, true, true);
$this->checkNormalize($schema, false, true, null, true, false, true, true);
$this->checkNormalize($schema, null, false, null, true, true, false, false);
$this->checkException($schema, null, true, ValueException::class);
$schema = new ScalarSchema(["rawstring", "default"]);
$this->checkNormalize($schema, false, false, "default", true, true, true, true);
$this->checkNormalize($schema, false, true, "default", true, true, true, true);
$this->checkNormalize($schema, null, false, null, true, true, false, false);
$this->checkException($schema, null, true, ValueException::class);
## Tester nullable
$schema = new ScalarSchema("?rawstring");
$this->checkNormalize($schema, null, false, null, true, true, true, true);
$this->checkNormalize($schema, null, true, null, true, true, true, true);
## Tester required
$schema = new ScalarSchema(["rawstring", "required" => true]);
$this->checkNormalize($schema, false, false, null, true, false, false, false);
$this->checkException($schema, false, true, ValueException::class);
## Tester allow_empty === false
$inputParams = ["allow_empty" => false];
$schema = new ScalarSchema("rawstring");
$this->checkNormalize($schema, null, false, null, true, true, false, false, $inputParams);
$this->checkException($schema, null, true, ValueException::class, $inputParams);
$this->checkNormalize($schema, "", false, null, true, false, true, true, $inputParams);
$this->checkNormalize($schema, "", true, null, true, false, true, true, $inputParams);
$schema = new ScalarSchema("?rawstring");
$this->checkNormalize($schema, null, false, null, true, true, true, true, $inputParams);
$this->checkNormalize($schema, null, true, null, true, true, true, true, $inputParams);
$this->checkNormalize($schema, "", false, null, true, false, true, true, $inputParams);
$this->checkNormalize($schema, "", true, null, true, false, true, true, $inputParams);
}
function testString() {
$schema = new ScalarSchema("string");
$this->checkNormalize($schema, false, false, null, true, false, true, true);
$this->checkNormalize($schema, false, true, null, true, false, true, true);
$this->checkNormalize($schema, null, false, null, true, true, false, false);
$this->checkException($schema, null, true, ValueException::class);
$this->checkNormalize($schema, "", false, "", true, true, true, true);
$this->checkNormalize($schema, "", true, "", true, true, true, true);
$this->checkNormalize($schema, " ", false, "", true, true, true, false);
$this->checkNormalize($schema, " ", true, "", true, true, true, false);
$this->checkNormalize($schema, "text", false, "text", true, true, true, true);
$this->checkNormalize($schema, "text", true, "text", true, true, true, true);
$this->checkNormalize($schema, " text ", false, "text", true, true, true, false);
$this->checkNormalize($schema, " text ", true, "text", true, true, true, false);
$this->checkNormalize($schema, true, false, true, true, true, true, false);
$this->checkNormalize($schema, true, true, "1", true, true, true, false);
$this->checkNormalize($schema, 42, false, 42, true, true, true, false);
$this->checkNormalize($schema, 42, true, "42", true, true, true, false);
$this->checkNormalize($schema, [], false, [], true, true, false, false);
$this->checkException($schema, [], true, ValueException::class);
## Tester nullable
$schema = new ScalarSchema("?string");
$this->checkNormalize($schema, null, false, null, true, true, true, true);
$this->checkNormalize($schema, null, true, null, true, true, true, true);
## Tester required
$schema = new ScalarSchema(["string", "required" => true]);
$this->checkNormalize($schema, false, false, null, true, false, false, false);
$this->checkException($schema, false, true, ValueException::class);
## Tester allow_empty === false
$inputParams = ["allow_empty" => false];
$schema = new ScalarSchema("string");
$this->checkNormalize($schema, null, false, null, true, true, false, false, $inputParams);
$this->checkException($schema, null, true, ValueException::class, $inputParams);
$this->checkNormalize($schema, "", false, null, true, false, true, true, $inputParams);
$this->checkNormalize($schema, "", true, null, true, false, true, true, $inputParams);
$schema = new ScalarSchema("?string");
$this->checkNormalize($schema, null, false, null, true, true, true, true, $inputParams);
$this->checkNormalize($schema, null, true, null, true, true, true, true, $inputParams);
$this->checkNormalize($schema, "", false, null, true, false, true, true, $inputParams);
$this->checkNormalize($schema, "", true, null, true, false, true, true, $inputParams);
}
function testInt() {
$schema = new ScalarSchema("int");
$this->checkNormalize($schema, false, false, null, true, false, true, true);
$this->checkNormalize($schema, false, true, null, true, false, true, true);
$this->checkNormalize($schema, null, false, null, true, true, false, false);
$this->checkException($schema, null, true, ValueException::class);
$this->checkNormalize($schema, 42, false, 42, true, true, true, true);
$this->checkNormalize($schema, 42, true, 42, true, true, true, true);
$this->checkNormalize($schema, "42", false, "42", true, true, true, false);
$this->checkNormalize($schema, "42", true, 42, true, true, true, false);
$this->checkNormalize($schema, "42.5", false, "42.5", true, true, true, false);
$this->checkNormalize($schema, "42.5", true, 42, true, true, true, false);
$this->checkNormalize($schema, "42,5", false, "42,5", true, true, true, false);
$this->checkNormalize($schema, "42,5", true, 42, true, true, true, false);
$this->checkNormalize($schema, " 42 ", false, "42", true, true, true, false);
$this->checkNormalize($schema, " 42 ", true, 42, true, true, true, false);
$this->checkNormalize($schema, "", false, "", true, true, false, false);
$this->checkException($schema, "", true, ValueException::class);
$this->checkNormalize($schema, " ", false, " ", true, true, false, false);
$this->checkException($schema, " ", true, ValueException::class);
$this->checkNormalize($schema, "text", false, "text", true, true, false, false);
$this->checkException($schema, "text", true, ValueException::class);
$this->checkNormalize($schema, true, false, true, true, true, true, false);
$this->checkNormalize($schema, true, true, 1, true, true, true, false);
$this->checkNormalize($schema, [], false, [], true, true, false, false);
$this->checkException($schema, [], true, ValueException::class);
## Tester nullable
$schema = new ScalarSchema("?int");
$this->checkNormalize($schema, null, false, null, true, true, true, true);
$this->checkNormalize($schema, null, true, null, true, true, true, true);
## Tester required
$schema = new ScalarSchema(["int", "required" => true]);
$this->checkNormalize($schema, false, false, null, true, false, false, false);
$this->checkException($schema, false, true, ValueException::class);
## Tester allow_empty === false
$inputParams = ["allow_empty" => false];
$schema = new ScalarSchema("int");
$this->checkNormalize($schema, null, false, null, true, true, false, false, $inputParams);
$this->checkException($schema, null, true, ValueException::class, $inputParams);
$this->checkNormalize($schema, "", false, null, true, false, true, true, $inputParams);
$this->checkNormalize($schema, "", true, null, true, false, true, true, $inputParams);
$schema = new ScalarSchema("?int");
$this->checkNormalize($schema, null, false, null, true, true, true, true, $inputParams);
$this->checkNormalize($schema, null, true, null, true, true, true, true, $inputParams);
$this->checkNormalize($schema, "", false, null, true, false, true, true, $inputParams);
$this->checkNormalize($schema, "", true, null, true, false, true, true, $inputParams);
}
}

View File

@ -1,10 +1,10 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
use Exception; use Exception;
use nulib\tests\TestCase; use nulib\tests\TestCase;
use nur\sery\wip\schema\_scalar\ScalarWrapper; use nulib\schema\_scalar\ScalarWrapper;
use nur\sery\wip\schema\Schema; use nulib\schema\Schema;
class boolTest extends TestCase { class boolTest extends TestCase {
function commonTests($wrapper, &$value, callable $wrapperSetter): void { function commonTests($wrapper, &$value, callable $wrapperSetter): void {
@ -59,7 +59,7 @@ class boolTest extends TestCase {
function testBool() { function testBool() {
/** @var ScalarWrapper $wrapper */ /** @var ScalarWrapper $wrapper */
Schema::nw($value, null, $schema, "bool", $wrapper); Schema::nw($value, null, "bool", $schema, $wrapper);
$wrapperSetter = function($value) use($wrapper) { $wrapperSetter = function($value) use($wrapper) {
return function() use($wrapper, $value) { return function() use($wrapper, $value) {
$wrapper->set($value); $wrapper->set($value);
@ -75,7 +75,7 @@ class boolTest extends TestCase {
function testNbool() { function testNbool() {
/** @var ScalarWrapper $wrapper */ /** @var ScalarWrapper $wrapper */
Schema::nw($value, null, $schema, "?bool", $wrapper); Schema::nw($value, null, "?bool", $schema, $wrapper);
$wrapperSetter = function($value) use($wrapper) { $wrapperSetter = function($value) use($wrapper) {
return function() use($wrapper, $value) { return function() use($wrapper, $value) {
$wrapper->set($value); $wrapper->set($value);

View File

@ -1,10 +1,10 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
use Exception; use Exception;
use nulib\tests\TestCase; use nulib\tests\TestCase;
use nur\sery\wip\schema\_scalar\ScalarWrapper; use nulib\schema\_scalar\ScalarWrapper;
use nur\sery\wip\schema\Schema; use nulib\schema\Schema;
class floatTest extends TestCase { class floatTest extends TestCase {
function commonTests($wrapper, &$value, callable $wrapperSetter): void { function commonTests($wrapper, &$value, callable $wrapperSetter): void {
@ -33,7 +33,7 @@ class floatTest extends TestCase {
function testFloat() { function testFloat() {
/** @var ScalarWrapper $wrapper */ /** @var ScalarWrapper $wrapper */
Schema::nw($value, null, $schema, "float", $wrapper); Schema::nw($value, null, "float", $schema, $wrapper);
$wrapperSetter = function($value) use($wrapper) { $wrapperSetter = function($value) use($wrapper) {
return function() use($wrapper, $value) { return function() use($wrapper, $value) {
$wrapper->set($value); $wrapper->set($value);
@ -53,10 +53,10 @@ class floatTest extends TestCase {
function testRequiredFloat() { function testRequiredFloat() {
/** @var ScalarWrapper $wrapper */ /** @var ScalarWrapper $wrapper */
Schema::nw($value, null, $schema, [ Schema::nw($value, null, [
"float", null, "float", null,
"required" => true, "required" => true,
], $wrapper); ], $schema, $wrapper);
$wrapperSetter = function($value) use($wrapper) { $wrapperSetter = function($value) use($wrapper) {
return function() use($wrapper, $value) { return function() use($wrapper, $value) {
$wrapper->set($value); $wrapper->set($value);
@ -75,7 +75,7 @@ class floatTest extends TestCase {
function testNfloat() { function testNfloat() {
/** @var ScalarWrapper $wrapper */ /** @var ScalarWrapper $wrapper */
Schema::nw($value, null, $schema, "?float", $wrapper); Schema::nw($value, null, "?float", $schema, $wrapper);
$wrapperSetter = function($value) use($wrapper) { $wrapperSetter = function($value) use($wrapper) {
return function() use($wrapper, $value) { return function() use($wrapper, $value) {
$wrapper->set($value); $wrapper->set($value);
@ -106,10 +106,10 @@ class floatTest extends TestCase {
function testRequiredNfloat() { function testRequiredNfloat() {
/** @var ScalarWrapper $wrapper */ /** @var ScalarWrapper $wrapper */
Schema::nw($value, null, $schema, [ Schema::nw($value, null, [
"?float", null, "?float", null,
"required" => true, "required" => true,
], $wrapper); ], $schema, $wrapper);
$wrapperSetter = function($value) use($wrapper) { $wrapperSetter = function($value) use($wrapper) {
return function() use($wrapper, $value) { return function() use($wrapper, $value) {
$wrapper->set($value); $wrapper->set($value);

View File

@ -1,10 +1,10 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
use Exception; use Exception;
use nulib\tests\TestCase; use nulib\tests\TestCase;
use nur\sery\wip\schema\_scalar\ScalarWrapper; use nulib\schema\_scalar\ScalarWrapper;
use nur\sery\wip\schema\Schema; use nulib\schema\Schema;
class intTest extends TestCase { class intTest extends TestCase {
function commonTests($wrapper, &$value, callable $wrapperSetter): void { function commonTests($wrapper, &$value, callable $wrapperSetter): void {
@ -33,7 +33,7 @@ class intTest extends TestCase {
function testInt() { function testInt() {
/** @var ScalarWrapper $wrapper */ /** @var ScalarWrapper $wrapper */
Schema::nw($value, null, $schema, "int", $wrapper); Schema::nw($value, null, "int", $schema, $wrapper);
$wrapperSetter = function($value) use($wrapper) { $wrapperSetter = function($value) use($wrapper) {
return function() use($wrapper, $value) { return function() use($wrapper, $value) {
$wrapper->set($value); $wrapper->set($value);
@ -53,10 +53,10 @@ class intTest extends TestCase {
function testRequiredInt() { function testRequiredInt() {
/** @var ScalarWrapper $wrapper */ /** @var ScalarWrapper $wrapper */
Schema::nw($value, null, $schema, [ Schema::nw($value, null, [
"int", null, "int", null,
"required" => true, "required" => true,
], $wrapper); ], $schema, $wrapper);
$wrapperSetter = function($value) use($wrapper) { $wrapperSetter = function($value) use($wrapper) {
return function() use($wrapper, $value) { return function() use($wrapper, $value) {
$wrapper->set($value); $wrapper->set($value);
@ -75,7 +75,7 @@ class intTest extends TestCase {
function testNint() { function testNint() {
/** @var ScalarWrapper $wrapper */ /** @var ScalarWrapper $wrapper */
Schema::nw($value, null, $schema, "?int", $wrapper); Schema::nw($value, null, "?int", $schema, $wrapper);
$wrapperSetter = function($value) use($wrapper) { $wrapperSetter = function($value) use($wrapper) {
return function() use($wrapper, $value) { return function() use($wrapper, $value) {
$wrapper->set($value); $wrapper->set($value);
@ -106,10 +106,10 @@ class intTest extends TestCase {
function testRequiredNint() { function testRequiredNint() {
/** @var ScalarWrapper $wrapper */ /** @var ScalarWrapper $wrapper */
Schema::nw($value, null, $schema, [ Schema::nw($value, null, [
"?int", null, "?int", null,
"required" => true, "required" => true,
], $wrapper); ], $schema, $wrapper);
$wrapperSetter = function($value) use($wrapper) { $wrapperSetter = function($value) use($wrapper) {
return function() use($wrapper, $value) { return function() use($wrapper, $value) {
$wrapper->set($value); $wrapper->set($value);

View File

@ -1,10 +1,10 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
use Exception; use Exception;
use nulib\tests\TestCase; use nulib\tests\TestCase;
use nur\sery\wip\schema\_scalar\ScalarWrapper; use nulib\schema\_scalar\ScalarWrapper;
use nur\sery\wip\schema\Schema; use nulib\schema\Schema;
class strTest extends TestCase { class strTest extends TestCase {
function commonTests($wrapper, &$value, callable $wrapperSetter): void { function commonTests($wrapper, &$value, callable $wrapperSetter): void {
@ -41,7 +41,7 @@ class strTest extends TestCase {
function testStr() { function testStr() {
/** @var ScalarWrapper $wrapper */ /** @var ScalarWrapper $wrapper */
Schema::nw($value, null, $schema, "string", $wrapper); Schema::nw($value, null, "string", $schema, $wrapper);
$wrapperSetter = function($value) use($wrapper) { $wrapperSetter = function($value) use($wrapper) {
return function() use($wrapper, $value) { return function() use($wrapper, $value) {
$wrapper->set($value); $wrapper->set($value);
@ -59,10 +59,10 @@ class strTest extends TestCase {
function testRequiredStr() { function testRequiredStr() {
/** @var ScalarWrapper $wrapper */ /** @var ScalarWrapper $wrapper */
Schema::nw($value, null, $schema, [ Schema::nw($value, null, [
"string", null, "string", null,
"required" => true, "required" => true,
], $wrapper); ], $schema, $wrapper);
$wrapperSetter = function($value) use($wrapper) { $wrapperSetter = function($value) use($wrapper) {
return function() use($wrapper, $value) { return function() use($wrapper, $value) {
$wrapper->set($value); $wrapper->set($value);
@ -79,7 +79,7 @@ class strTest extends TestCase {
function testNstr() { function testNstr() {
/** @var ScalarWrapper $wrapper */ /** @var ScalarWrapper $wrapper */
Schema::nw($value, null, $schema, "?string", $wrapper); Schema::nw($value, null, "?string", $schema, $wrapper);
$wrapperSetter = function($value) use($wrapper) { $wrapperSetter = function($value) use($wrapper) {
return function() use($wrapper, $value) { return function() use($wrapper, $value) {
$wrapper->set($value); $wrapper->set($value);
@ -100,10 +100,10 @@ class strTest extends TestCase {
function testRequiredNstr() { function testRequiredNstr() {
/** @var ScalarWrapper $wrapper */ /** @var ScalarWrapper $wrapper */
Schema::nw($value, null, $schema, [ Schema::nw($value, null, [
"?string", null, "?string", null,
"required" => true, "required" => true,
], $wrapper); ], $schema, $wrapper);
$wrapperSetter = function($value) use($wrapper) { $wrapperSetter = function($value) use($wrapper) {
return function() use($wrapper, $value) { return function() use($wrapper, $value) {
$wrapper->set($value); $wrapper->set($value);

View File

@ -1,9 +1,9 @@
<?php <?php
namespace nur\sery\wip\schema\types; namespace nulib\schema\types;
use nulib\tests\TestCase; use nulib\tests\TestCase;
use nur\sery\wip\schema\_scalar\ScalarWrapper; use nulib\schema\_scalar\ScalarWrapper;
use nur\sery\wip\schema\Schema; use nulib\schema\Schema;
class unionTest extends TestCase { class unionTest extends TestCase {
function testUnionTypes() { function testUnionTypes() {
@ -11,7 +11,7 @@ class unionTest extends TestCase {
# string puis int # string puis int
/** @var ScalarWrapper $siw */ /** @var ScalarWrapper $siw */
Schema::nw($si, null, $sis, "string|int", $siw); Schema::nw($si, null, "string|int", $sis, $siw);
$siw->set("12"); $siw->set("12");
self::assertSame("12", $si); self::assertSame("12", $si);
@ -20,7 +20,7 @@ class unionTest extends TestCase {
# int puis string # int puis string
/** @var ScalarWrapper $isw */ /** @var ScalarWrapper $isw */
Schema::nw($is, null, $iss, "int|string", $isw); Schema::nw($is, null, "int|string", $iss, $isw);
$isw->set("12"); $isw->set("12");
self::assertSame("12", $is); self::assertSame("12", $is);

View File

@ -1,66 +0,0 @@
<?php
namespace nur\sery\wip\php\access;
use nulib\tests\TestCase;
use stdClass;
class KeyAccessTest extends TestCase {
function testAccess() {
$default = new stdClass();
$array = ["null" => null, "false" => false, "empty" => ""];
#
$a = new KeyAccess($array, "inexistant");
self::assertFalse($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$a = new KeyAccess($array, "null");
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame(null, $a->get($default));
$a = new KeyAccess($array, "false");
self::assertTrue($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$a = new KeyAccess($array, "empty");
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame("", $a->get($default));
#
$a = new KeyAccess($array, "null", ["allow_null" => false]);
self::assertTrue($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$a = new KeyAccess($array, "null", ["allow_null" => true]);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame(null, $a->get($default));
#
$a = new KeyAccess($array, "false", ["allow_false" => false]);
self::assertTrue($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$a = new KeyAccess($array, "false", ["allow_false" => true]);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame(false, $a->get($default));
#
$a = new KeyAccess($array, "empty", ["allow_empty" => false]);
self::assertTrue($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$a = new KeyAccess($array, "empty", ["allow_empty" => true]);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame("", $a->get($default));
}
}

View File

@ -1,69 +0,0 @@
<?php
namespace nur\sery\wip\php\access;
use nulib\tests\TestCase;
use stdClass;
class ValueAccessTest extends TestCase {
function testAccess() {
$default = new stdClass();
#
$i = null;
$a = new ValueAccess($i);
self::assertFalse($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$i = false;
$a = new ValueAccess($i);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame(false, $a->get($default));
$i = "";
$a = new ValueAccess($i);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame("", $a->get($default));
#
$i = null;
$a = new ValueAccess($i, ["allow_null" => false]);
self::assertFalse($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$i = null;
$a = new ValueAccess($i, ["allow_null" => true]);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame(null, $a->get($default));
#
$i = false;
$a = new ValueAccess($i, ["allow_false" => false]);
self::assertTrue($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$i = false;
$a = new ValueAccess($i, ["allow_false" => true]);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame(false, $a->get($default));
#
$i = "";
$a = new ValueAccess($i, ["allow_empty" => false]);
self::assertTrue($a->exists());
self::assertFalse($a->available());
self::assertSame($default, $a->get($default));
$i = "";
$a = new ValueAccess($i, ["allow_empty" => true]);
self::assertTrue($a->exists());
self::assertTrue($a->available());
self::assertSame("", $a->get($default));
}
}

View File

@ -1,95 +0,0 @@
<?php
namespace nur\sery\wip\schema\_assoc;
use nulib\ext\yaml;
use nulib\tests\TestCase;
use nur\sery\wip\schema\_scalar\ScalarSchemaTest;
class AssocSchemaTest extends TestCase {
const NULL_SCHEMA = [
"" => ["assoc"],
"schema" => null,
"type" => [null],
"default" => null,
"title" => null,
"required" => false,
"nullable" => true,
"desc" => null,
"analyzer_func" => null,
"extractor_func" => null,
"parser_func" => null,
"normalizer_func" => null,
"messages" => null,
"formatter_func" => null,
"format" => null,
"name" => null,
"pkey" => null,
"header" => null,
"computed" => null,
];
static function schema(array $definition, array $keyDefinitions): array {
$definition = array_merge(self::NULL_SCHEMA, $definition, ["schema" => []]);
foreach ($keyDefinitions as $key => $keydef) {
$definition["schema"][$key] = array_merge(ScalarSchemaTest::NULL_SCHEMA, $keydef);
}; unset($subdef);
return $definition;
}
function testNormalize() {
self::assertSame(self::schema([
"type" => ["array"], "nullable" => true,
], [
"a" => [
"type" => ["string"], "nullable" => false,
"name" => "a", "pkey" => "a", "header" => "a",
],
]), AssocSchema::normalize(["a" => "string"]));
self::assertSame(self::schema([
"type" => ["array"], "nullable" => true,
], [
"a" => [
"type" => ["string"], "nullable" => false,
"name" => "a", "pkey" => "a", "header" => "a",
],
"b" => [
"type" => ["int"], "nullable" => false,
"name" => "b", "pkey" => "b", "header" => "b",
],
"c" => [
"type" => ["bool"], "nullable" => false,
"name" => "c", "pkey" => "c", "header" => "c",
],
]), AssocSchema::normalize([
"a" => "string",
"b" => "int",
"c" => "bool",
]));
}
function testConstructor() {
$schema = new AssocSchema([
"a" => "string",
"b" => "int",
"c" => "bool",
]);
self::assertSame(self::schema([
"type" => ["array"], "nullable" => true,
], [
"a" => [
"type" => ["string"], "nullable" => false,
"name" => "a", "pkey" => "a", "header" => "a",
],
"b" => [
"type" => ["int"], "nullable" => false,
"name" => "b", "pkey" => "b", "header" => "b",
],
"c" => [
"type" => ["bool"], "nullable" => false,
"name" => "c", "pkey" => "c", "header" => "c",
],
]), $schema->getDefinition());
yaml::dump($schema->getDefinition());
}
}

View File

@ -1,64 +0,0 @@
<?php
namespace nur\sery\wip\schema\_scalar;
use nulib\tests\TestCase;
use nur\sery\wip\schema\SchemaException;
class ScalarSchemaTest extends TestCase {
const NULL_SCHEMA = [
"type" => [null],
"default" => null,
"title" => null,
"required" => false,
"nullable" => true,
"desc" => null,
"analyzer_func" => null,
"extractor_func" => null,
"parser_func" => null,
"normalizer_func" => null,
"messages" => null,
"formatter_func" => null,
"format" => null,
"" => ["scalar"],
"schema" => null,
"name" => null,
"pkey" => null,
"header" => null,
"computed" => null,
];
static function schema(array $schema): array {
return array_merge(self::NULL_SCHEMA, $schema);
}
function testNormalize() {
self::assertSame(self::NULL_SCHEMA, ScalarSchema::normalize(null));
self::assertSame(self::NULL_SCHEMA, ScalarSchema::normalize([]));
self::assertSame(self::NULL_SCHEMA, ScalarSchema::normalize([null]));
self::assertException(SchemaException::class, function () {
ScalarSchema::normalize([[]]);
});
self::assertException(SchemaException::class, function () {
ScalarSchema::normalize([[null]]);
});
$string = self::schema(["type" => ["string"], "nullable" => false]);
self::assertSame($string, ScalarSchema::normalize("string"));
self::assertSame($string, ScalarSchema::normalize(["string"]));
$nstring = self::schema(["type" => ["string"]]);
self::assertSame($nstring, ScalarSchema::normalize(["?string"]));
self::assertSame($nstring, ScalarSchema::normalize(["?string|null"]));
self::assertSame($nstring, ScalarSchema::normalize(["string|null"]));
self::assertSame($nstring, ScalarSchema::normalize([["?string", "null"]]));
self::assertSame($nstring, ScalarSchema::normalize([["string", "null"]]));
self::assertSame($nstring, ScalarSchema::normalize([["string", null]]));
$key = self::schema(["type" => ["string", "int"], "nullable" => false]);
self::assertSame($key, ScalarSchema::normalize("string|int"));
$nkey = self::schema(["type" => ["string", "int"], "nullable" => true]);
self::assertSame($nkey, ScalarSchema::normalize("?string|int"));
self::assertSame($nkey, ScalarSchema::normalize("string|?int"));
}
}

View File

@ -1,294 +0,0 @@
<?php
namespace nur\sery\wip\schema\_scalar;
use nulib\tests\TestCase;
use nulib\ValueException;
use nur\sery\wip\schema\input\Input;
use stdClass;
class ScalarWrapperTest extends TestCase {
function checkValue(ScalarWrapper $wrapper, $value, bool $present, bool $available, bool $valid, bool $normalized): void {
self::assertSame($value, $wrapper->get(), "value");
self::assertSame($present, $wrapper->isPresent(), "present");
self::assertSame($available, $wrapper->isAvailable(), "available");
self::assertSame($valid, $wrapper->isValid(), "valid");
self::assertSame($normalized, $wrapper->isNormalized(), "normalized");
}
function checkVerifix(ScalarSchema $schema, $orig, bool $verifix, $value, bool $present, bool $available, bool $valid, bool $normalized, ?array $inputParams=null): void {
$wrapper = $schema->getWrapper();
if ($inputParams !== null) $input = new Input($orig, $inputParams);
else $input = $orig;
$wrapper->reset($input, null, $verifix);
$this->checkValue($wrapper, $value, $present, $available, $valid, $normalized);
}
function checkException(ScalarSchema $schema, $orig, bool $verifix, string $exceptionClass, ?array $inputParams=null) {
$wrapper = $schema->getWrapper();
if ($inputParams !== null) $orig = new Input($orig, $inputParams);
self::assertException($exceptionClass, function() use ($wrapper, &$orig, $verifix) {
$wrapper->reset($orig, null, $verifix);
});
}
function testRaw() {
$schema = new ScalarSchema();
$this->checkVerifix($schema, false, false, false, true, true, true, true);
$this->checkVerifix($schema, false, true, false, true, true, true, true);
$this->checkVerifix($schema, null, false, null, true, true, true, true);
$this->checkVerifix($schema, null, true, null, true, true, true, true);
$obj = new stdClass();
$this->checkVerifix($schema, $obj, false, $obj, true, true, true, true);
$this->checkVerifix($schema, $obj, true, $obj, true, true, true, true);
$schema = new ScalarSchema("raw");
$this->checkVerifix($schema, false, false, false, true, true, true, true);
$this->checkVerifix($schema, false, true, false, true, true, true, true);
$this->checkVerifix($schema, null, false, null, true, true, true, true);
$this->checkVerifix($schema, null, true, null, true, true, true, true);
$obj = new stdClass();
$this->checkVerifix($schema, $obj, false, $obj, true, true, true, true);
$this->checkVerifix($schema, $obj, true, $obj, true, true, true, true);
}
function testMixed() {
$schema = new ScalarSchema("mixed");
$this->checkVerifix($schema, false, false, false, true, true, true, true);
$this->checkVerifix($schema, false, true, false, true, true, true, true);
$this->checkVerifix($schema, null, false, null, true, true, false, false);
$this->checkException($schema, null, true, ValueException::class);
$obj = new stdClass();
$this->checkVerifix($schema, $obj, false, $obj, true, true, true, true);
$this->checkVerifix($schema, $obj, true, $obj, true, true, true, true);
$schema = new ScalarSchema("?mixed");
$this->checkVerifix($schema, false, false, false, true, true, true, true);
$this->checkVerifix($schema, false, true, false, true, true, true, true);
$this->checkVerifix($schema, null, false, null, true, true, true, true);
$this->checkVerifix($schema, null, true, null, true, true, true, true);
$obj = new stdClass();
$this->checkVerifix($schema, $obj, false, $obj, true, true, true, true);
$this->checkVerifix($schema, $obj, true, $obj, true, true, true, true);
}
function testRawstring() {
$schema = new ScalarSchema("rawstring");
$this->checkVerifix($schema, false, false, null, true, false, true, true);
$this->checkVerifix($schema, false, true, null, true, false, true, true);
$this->checkVerifix($schema, null, false, null, true, true, false, false);
$this->checkException($schema, null, true, ValueException::class);
$this->checkVerifix($schema, "", false, "", true, true, true, true);
$this->checkVerifix($schema, "", true, "", true, true, true, true);
$this->checkVerifix($schema, " ", false, " ", true, true, true, true);
$this->checkVerifix($schema, " ", true, " ", true, true, true, true);
$this->checkVerifix($schema, "text", false, "text", true, true, true, true);
$this->checkVerifix($schema, "text", true, "text", true, true, true, true);
$this->checkVerifix($schema, " text ", false, " text ", true, true, true, true);
$this->checkVerifix($schema, " text ", true, " text ", true, true, true, true);
$this->checkVerifix($schema, true, false, true, true, true, true, false);
$this->checkVerifix($schema, true, true, "1", true, true, true, false);
$this->checkVerifix($schema, 42, false, 42, true, true, true, false);
$this->checkVerifix($schema, 42, true, "42", true, true, true, false);
$this->checkVerifix($schema, [], false, [], true, true, false, false);
$this->checkException($schema, [], true, ValueException::class);
## Tester valeur par défaut
$schema = new ScalarSchema(["rawstring", null]);
$this->checkVerifix($schema, false, false, null, true, false, true, true);
$this->checkVerifix($schema, false, true, null, true, false, true, true);
$this->checkVerifix($schema, null, false, null, true, true, false, false);
$this->checkException($schema, null, true, ValueException::class);
$schema = new ScalarSchema(["rawstring", "default"]);
$this->checkVerifix($schema, false, false, "default", true, true, true, true);
$this->checkVerifix($schema, false, true, "default", true, true, true, true);
$this->checkVerifix($schema, null, false, null, true, true, false, false);
$this->checkException($schema, null, true, ValueException::class);
## Tester nullable
$schema = new ScalarSchema("?rawstring");
$this->checkVerifix($schema, null, false, null, true, true, true, true);
$this->checkVerifix($schema, null, true, null, true, true, true, true);
## Tester required
$schema = new ScalarSchema(["rawstring", "required" => true]);
$this->checkVerifix($schema, false, false, null, true, false, false, false);
$this->checkException($schema, false, true, ValueException::class);
## Tester allow_empty === false
$inputParams = ["allow_empty" => false];
$schema = new ScalarSchema("rawstring");
$this->checkVerifix($schema, null, false, null, true, true, false, false, $inputParams);
$this->checkException($schema, null, true, ValueException::class, $inputParams);
$this->checkVerifix($schema, "", false, null, true, false, true, true, $inputParams);
$this->checkVerifix($schema, "", true, null, true, false, true, true, $inputParams);
$schema = new ScalarSchema("?rawstring");
$this->checkVerifix($schema, null, false, null, true, true, true, true, $inputParams);
$this->checkVerifix($schema, null, true, null, true, true, true, true, $inputParams);
$this->checkVerifix($schema, "", false, null, true, false, true, true, $inputParams);
$this->checkVerifix($schema, "", true, null, true, false, true, true, $inputParams);
}
function testString() {
$schema = new ScalarSchema("string");
$this->checkVerifix($schema, false, false, null, true, false, true, true);
$this->checkVerifix($schema, false, true, null, true, false, true, true);
$this->checkVerifix($schema, null, false, null, true, true, false, false);
$this->checkException($schema, null, true, ValueException::class);
$this->checkVerifix($schema, "", false, "", true, true, true, true);
$this->checkVerifix($schema, "", true, "", true, true, true, true);
$this->checkVerifix($schema, " ", false, "", true, true, true, false);
$this->checkVerifix($schema, " ", true, "", true, true, true, false);
$this->checkVerifix($schema, "text", false, "text", true, true, true, true);
$this->checkVerifix($schema, "text", true, "text", true, true, true, true);
$this->checkVerifix($schema, " text ", false, "text", true, true, true, false);
$this->checkVerifix($schema, " text ", true, "text", true, true, true, false);
$this->checkVerifix($schema, true, false, true, true, true, true, false);
$this->checkVerifix($schema, true, true, "1", true, true, true, false);
$this->checkVerifix($schema, 42, false, 42, true, true, true, false);
$this->checkVerifix($schema, 42, true, "42", true, true, true, false);
$this->checkVerifix($schema, [], false, [], true, true, false, false);
$this->checkException($schema, [], true, ValueException::class);
## Tester nullable
$schema = new ScalarSchema("?string");
$this->checkVerifix($schema, null, false, null, true, true, true, true);
$this->checkVerifix($schema, null, true, null, true, true, true, true);
## Tester required
$schema = new ScalarSchema(["string", "required" => true]);
$this->checkVerifix($schema, false, false, null, true, false, false, false);
$this->checkException($schema, false, true, ValueException::class);
## Tester allow_empty === false
$inputParams = ["allow_empty" => false];
$schema = new ScalarSchema("string");
$this->checkVerifix($schema, null, false, null, true, true, false, false, $inputParams);
$this->checkException($schema, null, true, ValueException::class, $inputParams);
$this->checkVerifix($schema, "", false, null, true, false, true, true, $inputParams);
$this->checkVerifix($schema, "", true, null, true, false, true, true, $inputParams);
$schema = new ScalarSchema("?string");
$this->checkVerifix($schema, null, false, null, true, true, true, true, $inputParams);
$this->checkVerifix($schema, null, true, null, true, true, true, true, $inputParams);
$this->checkVerifix($schema, "", false, null, true, false, true, true, $inputParams);
$this->checkVerifix($schema, "", true, null, true, false, true, true, $inputParams);
}
function testInt() {
$schema = new ScalarSchema("int");
$this->checkVerifix($schema, false, false, null, true, false, true, true);
$this->checkVerifix($schema, false, true, null, true, false, true, true);
$this->checkVerifix($schema, null, false, null, true, true, false, false);
$this->checkException($schema, null, true, ValueException::class);
$this->checkVerifix($schema, 42, false, 42, true, true, true, true);
$this->checkVerifix($schema, 42, true, 42, true, true, true, true);
$this->checkVerifix($schema, "42", false, "42", true, true, true, false);
$this->checkVerifix($schema, "42", true, 42, true, true, true, false);
$this->checkVerifix($schema, "42.5", false, "42.5", true, true, true, false);
$this->checkVerifix($schema, "42.5", true, 42, true, true, true, false);
$this->checkVerifix($schema, "42,5", false, "42,5", true, true, true, false);
$this->checkVerifix($schema, "42,5", true, 42, true, true, true, false);
$this->checkVerifix($schema, " 42 ", false, "42", true, true, true, false);
$this->checkVerifix($schema, " 42 ", true, 42, true, true, true, false);
$this->checkVerifix($schema, "", false, "", true, true, false, false);
$this->checkException($schema, "", true, ValueException::class);
$this->checkVerifix($schema, " ", false, " ", true, true, false, false);
$this->checkException($schema, " ", true, ValueException::class);
$this->checkVerifix($schema, "text", false, "text", true, true, false, false);
$this->checkException($schema, "text", true, ValueException::class);
$this->checkVerifix($schema, true, false, true, true, true, true, false);
$this->checkVerifix($schema, true, true, 1, true, true, true, false);
$this->checkVerifix($schema, [], false, [], true, true, false, false);
$this->checkException($schema, [], true, ValueException::class);
## Tester nullable
$schema = new ScalarSchema("?int");
$this->checkVerifix($schema, null, false, null, true, true, true, true);
$this->checkVerifix($schema, null, true, null, true, true, true, true);
## Tester required
$schema = new ScalarSchema(["int", "required" => true]);
$this->checkVerifix($schema, false, false, null, true, false, false, false);
$this->checkException($schema, false, true, ValueException::class);
## Tester allow_empty === false
$inputParams = ["allow_empty" => false];
$schema = new ScalarSchema("int");
$this->checkVerifix($schema, null, false, null, true, true, false, false, $inputParams);
$this->checkException($schema, null, true, ValueException::class, $inputParams);
$this->checkVerifix($schema, "", false, null, true, false, true, true, $inputParams);
$this->checkVerifix($schema, "", true, null, true, false, true, true, $inputParams);
$schema = new ScalarSchema("?int");
$this->checkVerifix($schema, null, false, null, true, true, true, true, $inputParams);
$this->checkVerifix($schema, null, true, null, true, true, true, true, $inputParams);
$this->checkVerifix($schema, "", false, null, true, false, true, true, $inputParams);
$this->checkVerifix($schema, "", true, null, true, false, true, true, $inputParams);
}
}