Compare commits

..

22 Commits

Author SHA1 Message Date
2da0780a56 <pman>Intégration de la branche rel82-0.4.1 2025-03-17 17:23:56 +04:00
3c90d2fdfb <pman>deps de dist 2025-03-17 17:23:56 +04:00
1579fe28cc <pman>Init changelog & version 0.4.1p82 2025-03-17 17:23:44 +04:00
8e18999f20 <pman>Intégration de la branche dev74 2025-03-17 17:21:02 +04:00
c51809e476 <pman>Intégration de la branche dev74 2025-03-17 16:50:58 +04:00
fc795bbfcb <pman>deps de dev 2025-03-14 15:46:52 +04:00
b364e797ea <pman>Intégration de la branche rel82-0.4.0 2025-03-14 15:46:49 +04:00
c9630dcf67 <pman>Intégration de la branche rel82-0.4.0 2025-03-14 15:46:49 +04:00
eb74c5ee4e <pman>deps de dist 2025-03-14 15:46:49 +04:00
bb3db4ccd3 <pman>Init changelog & version 0.4.0p82 2025-03-14 15:46:42 +04:00
3d7e72ed53 maj deps 2025-03-14 15:46:27 +04:00
62b8b76ae5 <pman>Intégration de la branche dev74 2025-03-14 15:46:01 +04:00
cf5da535b3 <pman>Intégration de la branche dev74 2025-03-02 19:22:43 +04:00
6bbcafc45d maj deps 8.2 2025-03-02 15:40:56 +04:00
5f2ecda649 <pman>Intégration de la branche dev74 2025-03-02 15:40:18 +04:00
191f6a8a5b <pman>deps de dev 2025-03-01 13:50:53 +04:00
75bef42ac0 <pman>Intégration de la branche rel82-0.3.0 2025-03-01 13:50:13 +04:00
02b3b9f993 <pman>Intégration de la branche rel82-0.3.0 2025-03-01 13:50:12 +04:00
ab4a4bd89c maj deps 2025-03-01 13:50:06 +04:00
cbf29dae66 <pman>Init changelog & version 0.3.0p82 2025-03-01 13:49:22 +04:00
6cae1c73b1 <pman>Intégration de la branche dev74 2025-03-01 13:48:55 +04:00
537d1a8a94 maj deps php8.2 2025-03-01 13:44:03 +04:00
101 changed files with 2026 additions and 3528 deletions

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

@ -4,8 +4,10 @@
<content url="file://$MODULE_DIR$">
<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$/src" isTestSource="false" packagePrefix="nulib\" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="nulib\" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="nur\sery\wip\" />
<sourceFolder url="file://$MODULE_DIR$/src_app" isTestSource="false" packagePrefix="nur\sery\" />
<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" />
</content>
<orderEntry type="inheritedJdk" />

View File

@ -1,13 +1,13 @@
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
UPSTREAM=
DEVELOP=dev74
FEATURE=wip74/
RELEASE=rel74-
MAIN=dist74
UPSTREAM=dev74
DEVELOP=dev82
FEATURE=wip82/
RELEASE=rel82-
MAIN=dist82
TAG_PREFIX=
TAG_SUFFIX=p74
HOTFIX=hotf74-
TAG_SUFFIX=p82
HOTFIX=hotf82-
DIST=
NOAUTO=

View File

@ -5,12 +5,12 @@ composer:
dev:
link: true
require-dev:
nulib/php: ^7.4-dev
nulib/spout: ^7.4-dev
nulib/phpss: ^7.4-dev
nulib/php: ^8.2-dev
nulib/spout: ^8.2-dev
nulib/phpss: ^8.2-dev
dist:
link: false
require-dev:
nulib/php: ^0.4.0p74
nulib/spout: ^0.4.0p74
nulib/phpss: ^0.4.0p74
nulib/php: ^0.4.0p82
nulib/spout: ^0.4.0p82
nulib/phpss: ^0.4.0p82

View File

@ -4,5 +4,5 @@
RUNPHP=
# Si RUNPHP n'est pas défini, les variables suivantes peuvent être définies
DIST=d11
DIST=d12
#REGISTRY=pubdocker.univ-reunion.fr/dist

View File

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

1017
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@ -32,7 +32,6 @@ class nb {
}
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];
if ($options !== null) $item = array_merge($item, $options);
return $item;

View File

@ -1,7 +1,6 @@
<?php
namespace nur\v\vp;
use nulib\app;
use nur\authz;
use nur\b\authnz\IAuthzUser;
use nur\config;
@ -47,21 +46,6 @@ class NavigablePage extends AInitAuthzPage implements INavigablePage {
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 {
$username = $user->getUsername();
$role = $user->getRole();
@ -111,7 +95,6 @@ class NavigablePage extends AInitAuthzPage implements INavigablePage {
$user = authz::get();
navbar::nav(["align" => "right"], [
nb::menu(icon::user($user->getShortName()), [
$this->getAppVersionNbtext(),
$this->getAuthzNbtext($user),
$this->getLogoutNblink(),
]),

View File

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

View File

@ -1,5 +1,5 @@
<?php
namespace nulib\php\access;
namespace nur\sery\wip\php\access;
use nulib\cl;
@ -8,18 +8,6 @@ use nulib\cl;
* de {@link 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 {
$value = (int)$this->get();
$this->set(++$value);
@ -45,13 +33,4 @@ abstract class AbstractAccess implements IAccess {
cl::set($array, $key, $value);
$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

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

View File

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

View File

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

View File

@ -1,7 +1,5 @@
<?php
namespace nulib\php\access;
use ReflectionClass;
namespace nur\sery\wip\php\access;
/**
* Interface IAccess: abstraction d'un accès complet à une valeur
@ -27,26 +25,4 @@ interface IAccess extends IGetter, ISetter, IDeleter {
* tableau si $key===null
*/
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
namespace nulib\php\access;
namespace nur\sery\wip\php\access;
/**
* Class IDeleter: une abstraction d'un objet qui permet de supprimer une valeur

View File

@ -1,5 +1,5 @@
<?php
namespace nulib\php\access;
namespace nur\sery\wip\php\access;
/**
* Class IGetter: une abstraction d'un objet qui permet d'obtenir une valeur
@ -11,12 +11,6 @@ interface IGetter {
*/
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 */
function available(): bool;

View File

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

View File

@ -1,188 +1,69 @@
<?php
namespace nulib\php\access;
namespace nur\sery\wip\php\access;
use ArrayAccess;
use nulib\cl;
use nulib\ref\schema\ref_schema;
/**
* 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: accès à une valeur d'une clé dans un tableau
*/
class KeyAccess extends AbstractAccess {
const ALLOW_NULL = null;
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;
function __construct(&$array, $key, ?array $params=null) {
$this->array =& $array;
$this->key = $key;
$this->allowNull = $params["allow_null"] ?? static::ALLOW_NULL;
$this->allowFalse = $params["allow_false"] ?? static::ALLOW_FALSE;
$this->allowNull = $params["allow_null"] ?? true;
$this->allowFalse = $params["allow_false"] ?? false;
$this->allowEmpty = $params["allow_empty"] ?? true;
}
protected bool $protectDest;
/** @var array|ArrayAccess */
protected $array;
/** @var mixed|array|ArrayAccess */
protected $dest;
function reset(&$array): self {
$this->array =& $array;
return $this;
}
/** @var null|int|string|array */
/** @var int|string */
protected $key;
function reset(&$dest, $key=null): self {
$this->dest =& $dest;
$this->key = $key;
return $this;
}
protected bool $allowNull;
function resetKey($key=null): self {
$this->key = $key;
return $this;
}
protected bool $allowFalse;
protected ?bool $allowNull;
protected function isAllowNull(): bool {
$allowNull = $this->allowNull;
if ($allowNull !== null) return $allowNull;
return $this->key !== null;
}
protected ?bool $allowFalse;
protected function isAllowFalse(): bool {
$allowFalse = $this->allowFalse;
if ($allowFalse !== null) return $allowFalse;
return $this->key === null;
}
protected bool $allowEmpty;
function exists(): bool {
$key = $this->key;
if ($key === null) {
return $this->isAllowNull() || $this->dest !== null;
} else {
return cl::phas($this->dest, $key);
}
if ($key === null) return false;
return cl::has($this->array, $key);
}
function available(): bool {
if (!$this->exists()) return false;
$key = $this->key;
if ($key === null) $value = $this->dest;
else $value = cl::pget($this->dest, $key);
$value = cl::get($this->array, $this->key);
if ($value === null) return $this->allowNull;
if ($value === false) return $this->allowFalse;
if ($value === "") return $this->allowEmpty;
if ($value === null) return $this->isAllowNull();
if ($value === false) return $this->isAllowFalse();
return true;
}
function get($default=null) {
$key = $this->key;
if ($key === null) $value = $this->dest;
else $value = cl::pget($this->dest, $key, $default);
if ($this->key === null) return $default;
$value = cl::get($this->array, $this->key, $default);
if ($value === null && !$this->allowNull) return $default;
if ($value === false && !$this->allowFalse) return $default;
if ($value === "" && !$this->allowEmpty) return $default;
if ($value === null && !$this->isAllowNull()) return $default;
if ($value === false && !$this->isAllowFalse()) return $default;
return $value;
}
function set($value): void {
$key = $this->key;
if ($key === null) {
if (!$this->protectDest) $this->dest = $value;
} else {
cl::pset($this->dest, $key, $value);
}
if ($this->key === null) return;
cl::set($this->array, $this->key, $value);
}
function del(): void {
$key = $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);
if ($this->key === null) return;
cl::del($this->array, $this->key);
}
}

View File

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

View File

@ -1,173 +0,0 @@
<?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
namespace nulib\php\access;
namespace nur\sery\wip\php\access;
/**
* Class ShadowAccess: accès en lecture depuis une instance de {@link IAccess}
@ -16,7 +16,6 @@ namespace nulib\php\access;
*/
class ShadowAccess extends AbstractAccess {
function __construct(IAccess $reader, IAccess $writer) {
parent::__construct();
$this->reader = $reader;
$this->writer = $writer;
$this->getter = $reader;
@ -28,10 +27,6 @@ class ShadowAccess extends AbstractAccess {
protected IGetter $getter;
public function isAllowEmpty(): bool {
return $this->getter->isAllowEmpty();
}
function exists(): bool {
return $this->getter->exists();
}
@ -53,20 +48,4 @@ class ShadowAccess extends AbstractAccess {
$this->writer->del();
$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,8 +1,56 @@
<?php
namespace nulib\php\access;
namespace nur\sery\wip\php\access;
class ValueAccess extends KeyAccess {
const ALLOW_NULL = false;
const ALLOW_FALSE = true;
const PROTECT_DEST = false;
/**
* Class ValueAccess: accès à une valeur unitaire
*/
class ValueAccess extends AbstractAccess {
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
namespace nulib\php\coll;
namespace nur\sery\wip\php\coll;
use Iterator;
use IteratorAggregate;
use nulib\cl;
use nulib\php\func;
use nulib\php\iter;
use nur\sery\wip\php\iter;
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
namespace nulib\php;
namespace nur\sery\wip\php;
use Exception;
use Generator;

View File

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

View File

@ -1,8 +1,10 @@
<?php
namespace nulib\schema;
namespace nur\sery\wip\schema;
use IteratorAggregate;
use Throwable;
use nur\sery\wip\schema\_assoc\AssocResult;
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
@ -15,8 +17,6 @@ use Throwable;
* @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 $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 mixed|null $normalizedValue la valeur normalisée si elle est
* disponible, null sinon. ce champ est utilisé comme optimisation si la valeur
@ -26,7 +26,7 @@ abstract class Result implements IteratorAggregate {
const KEYS = [
"resultAvailable",
"present", "available", "null", "valid", "normalized",
"messageKey", "message", "exception",
"messageKey", "message",
"origValue", "normalizedValue",
];
@ -34,6 +34,10 @@ abstract class Result implements IteratorAggregate {
$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
* objet

View File

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

View File

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

View File

@ -1,38 +1,20 @@
# nulib\schema
* l'ordre est `ensureAssoc [--> ensureKeys] [--> orderKeys]`
* si false, supprimer la clé du tableau sauf si ensureKeys
* pour AssocResult, les clés suivantes sont supportées:
* false pour la clé courante
* 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
* instance de WrapperContext directement dans le schéma
* plus de {key} ni {orig} dans messages
* les messages standard ne sont utilisés que s'il n'y a pas de message dans
l'exception
* si instance de UserException, prendre le message "non technique" pour
résultat
* valeurs composite/computed
* analyse / vérification de la valeur complète après calcul du résultat, si
tous les résultats sont bons
* calcul des valeurs composites/computed par une fonction avant/après l'analyse
globale si résultat ok
* 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.)
* parse_format pour spécifier le format d'analyse au lieu de l'auto-détecter
* possibilité de spécifier le format de la date à analyser
* 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
commun aux champs dans le tableau destination, e.g
~~~php
@ -76,8 +58,6 @@
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
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
valeurs séquentielles sont des clés du schéma"
-*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary

View File

@ -1,107 +1,20 @@
<?php
namespace nulib\schema;
namespace nur\sery\wip\schema;
use ArrayAccess;
use IteratorAggregate;
use nulib\php\func;
use nulib\schema\_assoc\AssocWrapper;
use nulib\schema\_list\ListWrapper;
use nulib\schema\_scalar\ScalarResult;
use nulib\schema\_scalar\ScalarWrapper;
use nulib\schema\input\Input;
use nulib\schema\types\IType;
use nur\sery\wip\schema\_assoc\AssocWrapper;
use nur\sery\wip\schema\_list\ListWrapper;
use nur\sery\wip\schema\_scalar\ScalarWrapper;
use nur\sery\wip\schema\types\IType;
abstract class Wrapper implements ArrayAccess, IteratorAggregate {
protected WrapperContext $context;
function isAssoc(?AssocWrapper &$wrapper=null): bool { return false; }
function isList(?ListWrapper &$wrapper=null): bool { return false; }
function isScalar(?ScalarWrapper &$wrapper=null): bool { return false; }
/** changer les paramètres de gestion des valeurs */
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;
}
/** spécifier la valeur destination gérée par cet objet */
abstract function reset(&$value, $valueKey=null, ?bool $verifix=null): self;
/**
* Obtenir la liste des clés valides pour les valeurs accessibles via cet
@ -125,80 +38,37 @@ abstract class Wrapper implements ArrayAccess, IteratorAggregate {
}
/**
* obtenir le résultat de l'analyse de la valeur du wrapper sélectionné
*
* 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()}
* obtenir le résultat de l'appel d'une des fonctions {@link set()} ou
* {@link unset()}
*/
function getResult($key=false): Result {
return $this->context->result;
}
abstract function getResult(): Result;
/** retourner true si la valeur existe */
function isPresent($key=false): bool {
return $this->getResult($key)->present;
}
abstract function isPresent(): bool;
/** retourner le type associé à la valeur */
function getType($key=false): IType {
return $this->context->type;
}
abstract function getType(): IType;
/** retourner true si la valeur est disponible */
function isAvailable($key=false): bool {
return $this->getResult($key)->available;
}
abstract function isAvailable(): bool;
/** retourner true si la valeur est valide */
function isValid($key=false): bool {
return $this->getResult($key)->valid;
}
abstract function isValid(): bool;
/** retourner true si la valeur est dans sa forme normalisée */
function isNormalized($key=false): bool {
return $this->getResult($key)->normalized;
}
abstract function isNormalized(): bool;
function get($default=null, $key=false) {
$context = $this->context;
if (!$context->result->available) return $default;
return $context->input->get($context->valueKey);
}
/** obtenir la valeur */
abstract function get($default=null);
function set($value, ?array $params=null, $key=false): self {
$context = $this->context;
$context->input->set($value, $context->valueKey);
$this->afterModify($params);
return $this;
}
/** remplacer la valeur */
abstract function set($value): self;
function unset(?array $params=null, $key=false): 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);
}
}
/** supprimer la valeur */
abstract function unset(): self;
/** formatter la valeur pour affichage */
function format($format=null, $key=false): string {
return $this->_format($this->context, $format);
}
abstract function format($format=null): string;
#############################################################################
# key & properties
@ -208,14 +78,14 @@ abstract class Wrapper implements ArrayAccess, IteratorAggregate {
}
function offsetGet($offset) {
return $this->get(null, $offset);
return $this->select($offset);
}
function offsetSet($offset, $value): void {
$this->set($value, null, $offset);
$this->select($offset)->set($value);
}
function offsetUnset($offset): void {
$this->unset(null, $offset);
$this->select($offset)->unset();
}
}

View File

@ -1,46 +1,30 @@
<?php
namespace nulib\schema;
namespace nur\sery\wip\schema;
use nulib\ref\schema\ref_schema;
use nulib\schema\input\Input;
use nulib\schema\types\IType;
use nur\sery\wip\schema\input\Input;
use nur\sery\wip\schema\types\IType;
class WrapperContext {
function __construct(Schema $schema, ?Input $input, $valueKey, ?array $params) {
$this->resetParams($params);
function __construct(Schema $schema, Wrapper $wrapper, Input $input, $valueKey, Result $result) {
$this->schema = $schema;
if ($input !== null) $this->input = $input;
$this->wrapper = $wrapper;
$this->input = $input;
$this->result = $result;
$this->type = null;
$this->origValue = null;
$this->value = null;
$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;
/** source et destination de la valeur */
public Wrapper $wrapper;
public Input $input;
/** @var string|int|null clé de la valeur dans le tableau destination */
public Result $result;
public ?IType $type;
/** @var mixed */
public $origValue;
/** @var mixed */
public $value;
/** @var int|string|null */
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

@ -0,0 +1,53 @@
<?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,19 +1,21 @@
<?php
namespace nulib\schema\_assoc;
namespace nur\sery\wip\schema\_assoc;
use nulib\cl;
use nulib\ref\schema\ref_schema;
use nulib\ValueException;
use nulib\schema\Schema;
use nulib\schema\Wrapper;
use nur\sery\wip\schema\Schema;
use nur\sery\wip\schema\Wrapper;
/**
* Class AssocSchema
*/
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
* associatif que {@link normalize_definition()} pourrait normaliser
* associatif que {@link normalize()} pourrait normaliser
*/
static function isa_definition($definition): bool {
if (!is_array($definition)) return false;
@ -25,7 +27,7 @@ class AssocSchema extends Schema {
return !cl::have_num_keys($definition);
}
static function normalize_definition($definition, $definitionKey=null): array {
static function normalize($definition, $definitionKey=null): array {
if (!is_array($definition)) $definition = [$definition];
if (!self::have_nature($definition)) {
$definition = [
@ -34,8 +36,7 @@ class AssocSchema extends Schema {
"schema" => $definition,
];
}
$natureMetaschema = array_merge(ref_schema::NATURE_METASCHEMA, ref_schema::ASSOC_NATURE_METASCHEMA);
self::_normalize_definition($definition, $definitionKey, $natureMetaschema);
self::_normalize($definition, $definitionKey);
self::_ensure_nature($definition, "assoc", "array");
return $definition;
}
@ -43,54 +44,25 @@ class AssocSchema extends Schema {
function __construct($definition=null, $definitionKey=null, bool $normalize=true) {
if ($definition === null) $definition = static::SCHEMA;
if ($normalize) {
$definition = self::normalize_definition($definition, $definitionKey);
$definition = self::normalize($definition, $definitionKey);
$this->_definition = $definition;
self::_ensure_type($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;
$keys = [];
foreach ($definition["schema"] as $key => $schema) {
if (!$schema["computed"]) $keys[] = $key;
}
$this->keys = $keys;
}
protected array $keys;
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;
function isAssoc(?AssocSchema &$schema=null): bool {
$schema = $this;
return true;
}
protected function newWrapper(): AssocWrapper {
return new AssocWrapper($this);
}
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;
function getWrapper(&$array=null, $arrayKey=null, ?Wrapper &$wrapper=null): AssocWrapper {
if (!($wrapper instanceof AssocWrapper)) $wrapper = $this->newWrapper();
# 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);
return $wrapper->reset($array, $arrayKey);
}
}

View File

@ -1,185 +1,140 @@
<?php
namespace nulib\schema\_assoc;
namespace nur\sery\wip\schema\_assoc;
use nulib\cl;
use nulib\ref\schema\ref_analyze;
use nulib\ValueException;
use nulib\schema\_scalar\ScalarResult;
use nulib\schema\_scalar\ScalarWrapper;
use nulib\schema\input\Input;
use nulib\schema\Result;
use nulib\schema\types\IType;
use nulib\schema\Wrapper;
use nulib\schema\WrapperContext;
use nur\sery\wip\schema\_scalar\ScalarResult;
use nur\sery\wip\schema\_scalar\ScalarWrapper;
use nur\sery\wip\schema\input\Input;
use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\types\IType;
use nur\sery\wip\schema\Wrapper;
class AssocWrapper extends Wrapper {
function __construct(AssocSchema $schema, &$value=null, $valueKey=null, ?array $params=null) {
$keys = $schema->getKeys();
$keyParams = cl::merge($params, [
"throw" => false,
]);
$keyWrappers = [];
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);
function __construct(AssocSchema $schema, &$array=null, $arrayKey=null, ?array $params=null) {
$verifix = $params["verifix"] ?? true;
$throw = $params["throw"] ?? null;
if ($array !== null && $throw === null) {
# Si $value est null, ne pas lancer d'exception, parce qu'on considère que
# c'est une initialisation sans conséquences
$throw = true;
}
$this->schema = $schema;
$this->verifix = $verifix;
$this->throw = $throw ?? false;
$this->result = new AssocResult();
$this->reset($array, $arrayKey);
$this->throw = $throw ?? true;
}
/** @var AssocWrapperContext */
protected WrapperContext $context;
function isAssoc(?AssocWrapper &$wrapper=null): bool { $wrapper = $this; return true; }
protected function resetContext($resetSelectedKey): void {
parent::resetContext($resetSelectedKey);
$context = $this->context;
$context->arrayWrapper->getResult()->reset();
foreach ($context->keyWrappers as $wrapper) {
$wrapper->getResult()->reset();
}
protected bool $verifix;
protected bool $throw;
/** schéma de ce tableau */
protected AssocSchema $schema;
/** 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(&$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;
foreach ($context->keyWrappers as $key => $keyWrapper) {
$keyInput = $input->addKey($valueKey);
$keyWrapper->reset($keyInput, $key, ["analyze" => false]);
}
$this->afterModify($params, true);
function reset(&$array, $arrayKey=null, ?bool $verifix=null): Wrapper {
if ($array instanceof Input) $input = $array;
else $input = $this->newInput($array);
$this->input = $input;
$this->arrayKey = $arrayKey;
$this->analyze();
if ($verifix ?? $this->verifix) $this->verifix();
return $this;
}
function getKeys(): array {
return $this->context->keys;
return $this->keys;
}
protected function _getWrapper($key): Wrapper {
$context = $this->context;
if ($key === null) return $context->arrayWrapper;
$wrapper = $context->keyWrappers[$key] ?? null;
if ($wrapper === null) throw ValueException::invalid_key($key);
return $wrapper;
function select($key=null): ScalarWrapper {
$wrapper = $this->wrappers[$key] ?? null;
if ($key !== null) return $wrapper;
throw ValueException::invalid_key($key);
}
/** @param string|int|null $key */
function select($key=null): Wrapper {
$wrapper = $this->_getWrapper($key);
$this->context->selectedKey = $key;
return $wrapper;
/** @param Result[] $results */
function verifix(?bool $throw=null, ?array &$results=null): bool {
}
/**
* @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);
}
if ($params["ensure_assoc"] ?? $context->ensureAssoc) {
$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 getResult(): AssocResult {
return $this->result;
}
/**
* @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 isPresent(): bool {
return $this->result->present;
}
function getResult($key=false): Result {
if ($key === false) $key = $this->context->selectedKey;
return $this->_getWrapper($key)->getResult();
function getType(): IType {
return $this->arrayType;
}
function getType($key=false): IType {
if ($key === false) $key = $this->context->selectedKey;
return $this->_getWrapper($key)->getType();
function isAvailable(): bool {
return $this->result->available;
}
function get($default=null, $key=false) {
$context = $this->context;
if (!$context->arrayWrapper->isAvailable()) return $default;
if ($key === false) $key = $context->selectedKey;
return $this->_getWrapper($key)->get($default);
function isValid(): bool {
return $this->result->valid;
}
function set($value, ?array $params=null, $key=false): Wrapper {
$context = $this->context;
if ($key === false) $key = $context->selectedKey;
$this->_getWrapper($key)->set($value);
function isNormalized(): bool {
return $this->result->normalized;
}
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;
}
function unset(?array $params=null, $key=false): Wrapper {
$context = $this->context;
if ($key === false) $key = $context->selectedKey;
$this->_getWrapper($key)->unset();
function unset(?bool $verifix=null): AssocWrapper {
$this->input->unset($this->arrayKey);
$this->analyze();
if ($verifix ?? $this->verifix) $this->verifix();
return $this;
}
function format($format=null, $key=false): string {
$context = $this->context;
if ($key === false) $key = $context->selectedKey;
return $this->_getWrapper($key)->format($format);
function format($format = null): string {
// TODO: Implement format() method.
}
function ensureKeys(): bool {
}
function orderKeys(): bool {
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,19 +1,41 @@
<?php
namespace nulib\schema\_scalar;
namespace nur\sery\wip\schema\_scalar;
use nulib\cl;
use nulib\ref\schema\ref_schema;
use nulib\ValueException;
use nulib\schema\Schema;
use nulib\schema\Wrapper;
use nur\sery\wip\schema\Schema;
use nur\sery\wip\schema\types\IType;
use nur\sery\wip\schema\Wrapper;
/**
* 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 {
/** @var array meta-schema d'un schéma de nature scalaire */
const METASCHEMA = ref_schema::SCALAR_METASCHEMA;
/**
* indiquer si $definition est une définition de schéma scalaire que
* {@link normalize_definition()} pourrait normaliser
* {@link normalize()} pourrait normaliser
*/
static function isa_definition($definition): bool {
# chaine ou null
@ -42,9 +64,8 @@ class ScalarSchema extends Schema {
return $haveIndex0 && $count > 1;
}
static function normalize_definition($definition, $definitionKey=null): array {
$natureMetaschema = array_merge(ref_schema::NATURE_METASCHEMA, ref_schema::SCALAR_NATURE_METASCHEMA);
self::_normalize_definition($definition, $definitionKey, $natureMetaschema);
static function normalize($definition, $definitionKey=null): array {
self::_normalize($definition, $definitionKey);
self::_ensure_nature($definition, "scalar");
return $definition;
}
@ -52,47 +73,40 @@ class ScalarSchema extends Schema {
function __construct($definition=null, $definitionKey=null, bool $normalize=true) {
if ($definition === null) $definition = static::SCHEMA;
if ($normalize) {
$definition = self::normalize_definition($definition, $definitionKey);
$definition = self::normalize($definition, $definitionKey);
$this->_definition = $definition;
self::_ensure_type($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;
}
const KEYS = [null];
function getKeys(): array {
return self::KEYS;
}
function getSchema($key=false): Schema {
if ($key === null || $key === false) return $this;
throw ValueException::invalid_key($key);
function isScalar(?ScalarSchema &$schema=null): bool {
$schema = $this;
return true;
}
protected function newWrapper(): ScalarWrapper {
return new ScalarWrapper($this);
}
function getWrapper(&$value=null, $valueKey=null, ?array $params=null, ?Wrapper &$wrapper=null): ScalarWrapper {
function getWrapper(&$value=null, $valueKey=null, ?Wrapper &$wrapper=null): ScalarWrapper {
# si pas de valeur ni de wrapper, pas de vérification et donc pas d'exception
# cf le code similaire dans ScalarWrapper::__construct()
$dontAnalyze = $value === null && $wrapper === null;
$verifix = $value !== null || $wrapper !== null;
if (!($wrapper instanceof ScalarWrapper)) $wrapper = $this->newWrapper();
# 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);
return $wrapper->reset($value, $valueKey, $verifix);
}
#############################################################################
# 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,42 +1,70 @@
<?php
namespace nulib\schema\_scalar;
namespace nur\sery\wip\schema\_scalar;
use nulib\php\func;
use nulib\ref\schema\ref_analyze;
use nulib\ValueException;
use nulib\schema\Schema;
use nulib\schema\types;
use nulib\schema\types\IType;
use nulib\schema\Wrapper;
use nulib\schema\WrapperContext;
use nur\sery\wip\schema\WrapperContext;
use nur\sery\wip\schema\input\Input;
use nur\sery\wip\schema\types;
use nur\sery\wip\schema\types\IType;
use nur\sery\wip\schema\Wrapper;
/**
* 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 {
function __construct(Schema $schema, &$value=null, $valueKey=null, ?array $params=null, ?WrapperContext $context=null) {
if ($context === null) $context = new WrapperContext($schema, null, null, $params);
$context->result = new ScalarResult();
$this->context = $context;
if ($value !== null) {
# 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);
function __construct(ScalarSchema $schema, &$value=null, $valueKey=null, ?array $params=null) {
$verifix = $params["verifix"] ?? true;
$throw = $params["throw"] ?? null;
if ($value !== null && $throw === null) {
# Si $value est null, ne pas lancer d'exception, parce qu'on considère que
# c'est une initialisation sans conséquences
$throw = true;
}
$this->verifix = $verifix;
$this->throw = $throw ?? false;
$this->schema = $schema;
$this->result = new ScalarResult();
$this->reset($value, $valueKey);
$this->throw = $throw ?? true;
}
protected WrapperContext $context;
function isScalar(?ScalarWrapper &$wrapper=null): bool { $wrapper = $this; return true; }
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 {
return ScalarSchema::KEYS;
return [null];
}
/** @param string|int|null $key */
@ -46,7 +74,7 @@ class ScalarWrapper extends Wrapper {
}
/** analyser la valeur et résoudre son type */
protected static function _analyze0(WrapperContext $context): int {
protected function analyze0(WrapperContext $context): int {
/** @var ScalarSchema $schema */
$schema = $context->schema;
$input = $context->input;
@ -84,7 +112,7 @@ class ScalarWrapper extends Wrapper {
$args = $name;
$name = $key;
}
$type = types::get($schema->nullable, $name, $args, $schema->getDefinition());
$type = types::get($schema->nullable, $name, $args, $this->schema->getDefinition());
if ($firstType === null) $firstType = $type;
$types[] = $type;
if ($type->isAvailable($input, $valueKey)) {
@ -112,7 +140,7 @@ class ScalarWrapper extends Wrapper {
$type = $firstType;
}
}
$context->type = $type;
$context->type = $this->type = $type;
if (!$type->isAvailable($input, $valueKey)) {
if ($default !== null) {
@ -137,28 +165,25 @@ class ScalarWrapper extends Wrapper {
}
}
/**
* @param ScalarWrapper $wrapper
*/
static function _analyze(WrapperContext $context, Wrapper $wrapper, ?array $params): int {
/** @var ScalarSchema $schema */
$schema = $context->schema;
$input = $context->input;
$valueKey = $context->valueKey;
/** @var ScalarResult $result */
$result = $context->result;
protected function analyze(): int {
$schema = $this->schema;
$input = $this->input;
$valueKey = $this->valueKey;
$result = $this->result;
$result->reset();
$context = new WrapperContext($schema, $this, $input, $valueKey, $result);
/** @var func $analyzerFunc */
$analyzerFunc = $schema->analyzerFunc;
if ($analyzerFunc !== null) $what = $analyzerFunc->invoke([$context, $wrapper]);
else $what = self::_analyze0($context);
if ($analyzerFunc !== null) $what = $analyzerFunc->invoke([$context]);
else $what = $this->analyze0($context);
if ($what !== ref_analyze::STRING) return $what;
$value = $context->value;
try {
/** @var func $extractorFunc */
$extractorFunc = $schema->extractorFunc;
if ($extractorFunc !== null) $extracted = $extractorFunc->invoke([$value, $context, $wrapper]);
if ($extractorFunc !== null) $extracted = $extractorFunc->invoke([$value, $context]);
else $extracted = $context->type->extract($value);
$context->value = $extracted;
} catch (ValueException $e) {
@ -169,7 +194,7 @@ class ScalarWrapper extends Wrapper {
try {
/** @var func $parserFunc */
$parserFunc = $schema->parserFunc;
if ($parserFunc !== null) $parsed = $parserFunc->invoke([$extracted, $context, $wrapper]);
if ($parserFunc !== null) $parsed = $parserFunc->invoke([$extracted, $context]);
else $parsed = $context->type->parse($extracted);
$context->value = $parsed;
} catch (ValueException $e) {
@ -186,53 +211,107 @@ class ScalarWrapper extends Wrapper {
}
}
/**
* @param ScalarWrapper $wrapper
*/
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;
function verifix(?bool $throw=null): bool {
$result = $this->result;
$valueKey = $this->valueKey;
$verifix = false;
$modified = false;
if ($result->resultAvailable) {
if ($result->null) {
# forcer la valeur null, parce que la valeur actuelle est peut-être une
# valeur assimilée à null
$input->set(null, $valueKey);
$this->input->set(null, $valueKey);
} elseif ($result->valid && !$result->normalized) {
$normalizedValue = $result->normalizedValue;
if ($normalizedValue !== null) {
# la valeur normalisée est disponible
$input->set($normalizedValue, $valueKey);
$this->input->set($normalizedValue);
$result->normalizedValue = null;
$modified = true;
} else {
# normaliser la valeur
$normalize = true;
$verifix = true;
}
}
} else {
$normalize = true;
$verifix = true;
}
if ($normalize) {
$value = $input->get($valueKey);
if ($verifix) {
$value = $this->input->get($valueKey);
$schema = $this->schema;
/** @var func $normalizerFunc */
$normalizerFunc = $schema->normalizerFunc;
if ($normalizerFunc !== null) {
$context = new WrapperContext($schema, $this, $this->input, $valueKey, $result);
$orig = $value;
$value = $normalizerFunc->invoke([$orig, $context, $wrapper]);
$value = $normalizerFunc->invoke([$orig, $context]);
$modified = $value !== $orig;
} else {
$modified = $context->type->normalize($value, $result, $schema);
$modified = $this->type->verifix($value, $result, $this->schema);
}
if ($result->valid) $input->set($value, $valueKey);
if ($result->valid) $this->input->set($value, $valueKey);
}
if (!$result->valid) $result->throw($throw ?? $this->throw);
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,11 +1,12 @@
<?php
namespace nulib\schema\input;
namespace nur\sery\wip\schema\input;
#XXX implémenter le renommage de paramètres et faire des méthodes pour
# construire des querystring et paramètres de formulaires
use nulib\php\access\FormAccess;
use nulib\php\access\IAccess;
use nulib\php\access\ShadowAccess;
use nur\sery\wip\php\access\FormAccess;
use nur\sery\wip\php\access\IAccess;
use nur\sery\wip\php\access\KeyAccess;
use nur\sery\wip\php\access\ShadowAccess;
/**
* Class FormInput: accès à des paramètres de formulaire (POST ou GET, dans cet
@ -17,14 +18,15 @@ use nulib\php\access\ShadowAccess;
class FormInput extends Input {
const ALLOW_EMPTY = false;
function __construct(&$dest=null, ?array $params=null) {
parent::__construct($dest, $params);
$this->access = new ShadowAccess($this->formAccess($this->access), $this->access);
}
protected function formAccess(IAccess $access): IAccess {
return new FormAccess(null, [
"allow_empty" => $access->isAllowEmpty(),
protected function formAccess($key): IAccess {
return new FormAccess($key, [
"allow_empty" => $this->allowEmpty,
]);
}
protected function access($key): IAccess {
return $this->keyAccess[$key] ??= new ShadowAccess($this->formAccess($key), new KeyAccess($this->value, $key, [
"allow_empty" => $this->allowEmpty,
]));
}
}

View File

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

View File

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

View File

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

View File

@ -1,22 +1,22 @@
<?php
namespace nulib\schema;
namespace nur\sery\wip\schema;
use nulib\ValueException;
use nulib\schema\types\IType;
use nulib\schema\types\Registry;
use nulib\schema\types\tarray;
use nulib\schema\types\tbool;
use nulib\schema\types\tfunc;
use nulib\schema\types\tcontent;
use nulib\schema\types\tfloat;
use nulib\schema\types\tint;
use nulib\schema\types\tkey;
use nulib\schema\types\tmixed;
use nulib\schema\types\tpkey;
use nulib\schema\types\traw;
use nulib\schema\types\trawstring;
use nulib\schema\types\tstring;
use nulib\schema\types\ttext;
use nur\sery\wip\schema\types\IType;
use nur\sery\wip\schema\types\Registry;
use nur\sery\wip\schema\types\tarray;
use nur\sery\wip\schema\types\tbool;
use nur\sery\wip\schema\types\tcallable;
use nur\sery\wip\schema\types\tcontent;
use nur\sery\wip\schema\types\tfloat;
use nur\sery\wip\schema\types\tint;
use nur\sery\wip\schema\types\tkey;
use nur\sery\wip\schema\types\tmixed;
use nur\sery\wip\schema\types\tpkey;
use nur\sery\wip\schema\types\traw;
use nur\sery\wip\schema\types\trawstring;
use nur\sery\wip\schema\types\tstring;
use nur\sery\wip\schema\types\ttext;
/**
* 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 float(bool $nullable=true): tfloat { return self::get($nullable, "float"); }
static function array(bool $nullable=true): tarray { return self::get($nullable, "array"); }
static function callable(bool $nullable=true): tfunc { return self::get($nullable, "callable"); }
static function callable(bool $nullable=true): tcallable { return self::get($nullable, "callable"); }
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 key(bool $nullable=true): tkey { return self::get($nullable, "key"); }

View File

@ -1,10 +1,10 @@
<?php
namespace nulib\schema\types;
namespace nur\sery\wip\schema\types;
use nulib\ValueException;
use nulib\schema\input\Input;
use nulib\schema\Result;
use nulib\schema\Schema;
use nur\sery\wip\schema\input\Input;
use nur\sery\wip\schema\Result;
use nur\sery\wip\schema\Schema;
/**
* 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
* par {@link format()} et le type retourné par {@link normalize()}
* par {@link format()} et le type retourné par {@link verifix()}
*
* Les valeurs "mixed", "bool", "float", "int", "string" et "array" peuvent
* aussi être retournées, bien qu'elles ne soient pas à proprement parler des
@ -47,9 +47,6 @@ interface IType {
*/
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
* "vraie" et une "fausse"
@ -101,18 +98,15 @@ interface IType {
function parse(string $value);
/**
* 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
* analyser, corriger éventuellement et normaliser la valeur
*
* NB: si $value est un string. elle doit avoir déjà été traitée au préalable
* par extract() et parse()
*
* - si $result indique que la valeur est déjà normalisée, cette méthode ne
* 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é
* si la valeur était déjà normalisée, ou si une erreur s'est produite,
* retourner false.
*/
function normalize(&$value, Result $result, Schema $schema): bool;
function verifix(&$value, Result $result, Schema $schema): bool;
/**
* formatter la valeur pour affichage. si $value n'est pas null, elle est

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

5
src_glue/app.php Normal file
View File

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

View File

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

View File

@ -1,132 +0,0 @@
<?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

@ -1,215 +0,0 @@
<?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,353 +0,0 @@
<?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

@ -1,68 +0,0 @@
<?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

@ -1,296 +0,0 @@
<?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

@ -0,0 +1,66 @@
<?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

@ -0,0 +1,69 @@
<?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,5 +1,5 @@
<?php
namespace nulib\php\coll;
namespace nur\sery\wip\php\coll;
use Exception;
use nulib\cl;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,95 @@
<?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

@ -0,0 +1,64 @@
<?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

@ -0,0 +1,294 @@
<?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);
}
}

View File

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

View File

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

View File

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

View File

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

Some files were not shown because too many files have changed in this diff Show More