Compare commits
35 Commits
Author | SHA1 | Date | |
---|---|---|---|
68f5dc5209 | |||
f005692cd8 | |||
d844bd03ad | |||
c4e02d5bcf | |||
2a92a9a07e | |||
c274adb6e6 | |||
ff02ffdf4f | |||
9109e0fe39 | |||
fd1ebaf611 | |||
26817d2826 | |||
7257654753 | |||
e2bec38540 | |||
c2ec23be30 | |||
741a807420 | |||
e9f4826a94 | |||
fd9b3b29bc | |||
f37a53cfbd | |||
6e8245dbcb | |||
f4e252a6e0 | |||
19f6f9c9e1 | |||
baa770d969 | |||
c5bfa3940c | |||
39af99ffa4 | |||
1fc4e7637b | |||
ef7e8551aa | |||
9328aac9e9 | |||
62fc315b9e | |||
b9e91bd917 | |||
3608b02749 | |||
d148850c12 | |||
189c7aba68 | |||
91e6c0dcd2 | |||
bb311708d7 | |||
1feffb6c0f | |||
62987d576e |
6
.idea/nur-ture.iml
generated
6
.idea/nur-ture.iml
generated
@ -4,10 +4,8 @@
|
||||
<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="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\" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="nulib\" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="nulib\" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
|
@ -1,3 +1,5 @@
|
||||
## Release 0.4.1p82 du 17/03/2025-17:23
|
||||
|
||||
## Release 0.4.1p74 du 17/03/2025-17:19
|
||||
|
||||
* `56fda96` changer le type de variables gérées par EnvConfig
|
||||
|
@ -64,9 +64,7 @@
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"nulib\\": "src_glue",
|
||||
"nur\\sery\\wip\\": "src",
|
||||
"nur\\sery\\": "src_app",
|
||||
"nulib\\": "src",
|
||||
"nur\\": "nur_src"
|
||||
},
|
||||
"files": [
|
||||
@ -75,7 +73,7 @@
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"nur\\sery\\": "tests",
|
||||
"nulib\\": "tests",
|
||||
"nur\\": "nur_tests"
|
||||
}
|
||||
},
|
||||
|
2
composer.lock
generated
2
composer.lock
generated
@ -589,7 +589,7 @@
|
||||
"dist": {
|
||||
"type": "path",
|
||||
"url": "../nulib",
|
||||
"reference": "2cdc05981013dc403afe26c08f3cfef36f737642"
|
||||
"reference": "1536e091fb0020858204f59462a7a80b5f9775d9"
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
|
@ -2,6 +2,6 @@
|
||||
<?php
|
||||
require $_composer_autoload_path?? __DIR__.'/../vendor/autoload.php';
|
||||
|
||||
use nur\sery\tools\SteamTrainApp;
|
||||
use nulib\tools\SteamTrainApp;
|
||||
|
||||
SteamTrainApp::run();
|
||||
|
@ -2,6 +2,7 @@
|
||||
namespace nur\cli;
|
||||
|
||||
use Exception;
|
||||
use nulib\app;
|
||||
use nulib\app\RunFile;
|
||||
use nulib\ExitError;
|
||||
use nulib\ext\yaml;
|
||||
@ -16,7 +17,6 @@ use nur\config\ArrayConfig;
|
||||
use nur\msg;
|
||||
use nur\os;
|
||||
use nur\path;
|
||||
use nur\sery\app;
|
||||
|
||||
/**
|
||||
* Class Application: application de base
|
||||
|
@ -105,7 +105,7 @@ class ref_type {
|
||||
/** comme {@link c} mais nullable */
|
||||
const NCONTENT = "?".self::CONTENT;
|
||||
|
||||
/** comme {@link \nur\sery\FILE} mais nullable */
|
||||
/** comme {@link FILE} mais nullable */
|
||||
const NFILE = "?".self::FILE;
|
||||
|
||||
/** comme {@link DATETIME} mais nullable */
|
||||
|
@ -32,6 +32,7 @@ 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;
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace nur\v\vp;
|
||||
|
||||
use nulib\app;
|
||||
use nur\authz;
|
||||
use nur\b\authnz\IAuthzUser;
|
||||
use nur\config;
|
||||
@ -46,6 +47,21 @@ 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();
|
||||
@ -95,6 +111,7 @@ 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(),
|
||||
]),
|
||||
|
@ -2,7 +2,7 @@
|
||||
require(__DIR__.'/../../vendor/autoload.php');
|
||||
|
||||
use nur\cli\Application;
|
||||
use nur\sery\output\msg;
|
||||
use nulib\output\msg;
|
||||
|
||||
class TestArgs4 extends Application {
|
||||
protected $query;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery;
|
||||
namespace nulib;
|
||||
|
||||
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 nur\sery\app\cli\Application;
|
||||
use nulib\app\cli\Application;
|
||||
|
||||
class app {
|
||||
private static function isa_Application($app): bool {
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\app\cli;
|
||||
namespace nulib\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 nur\sery\app;
|
||||
use nulib\app;
|
||||
|
||||
/**
|
||||
* Class Application: application de base
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\php\access;
|
||||
namespace nulib\php\access;
|
||||
|
||||
use nulib\cl;
|
||||
|
||||
@ -8,6 +8,18 @@ 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);
|
||||
@ -33,4 +45,13 @@ 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 {
|
||||
}
|
||||
}
|
||||
|
8
src/php/access/ArrayAccess.php
Normal file
8
src/php/access/ArrayAccess.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
namespace nulib\php\access;
|
||||
|
||||
class ArrayAccess extends KeyAccess {
|
||||
const ALLOW_NULL = true;
|
||||
const ALLOW_FALSE = false;
|
||||
const PROTECT_DEST = true;
|
||||
}
|
182
src/php/access/ChainAccess.php
Normal file
182
src/php/access/ChainAccess.php
Normal file
@ -0,0 +1,182 @@
|
||||
<?php
|
||||
namespace nulib\php\access;
|
||||
|
||||
use nulib\cl;
|
||||
use nulib\StateException;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
|
||||
class ChainAccess extends AbstractAccess {
|
||||
const ACCESS_AUTO = 0, ACCESS_KEY = 1, ACCESS_PROPERTY = 2;
|
||||
|
||||
private static function unexpected_access_type(): StateException {
|
||||
return StateException::unexpected_state("access_type");
|
||||
}
|
||||
|
||||
function __construct(IAccess $access, $key, ?array $params=null) {
|
||||
parent::__construct();
|
||||
$this->access = $access;
|
||||
$this->key = $key;
|
||||
$this->accessType = $params["access_type"] ?? self::ACCESS_AUTO;
|
||||
}
|
||||
|
||||
protected IAccess $access;
|
||||
|
||||
/** @var null|int|string|array */
|
||||
protected $key;
|
||||
|
||||
protected int $accessType;
|
||||
|
||||
protected function _accessType($access, $key): int {
|
||||
$accessType = $this->accessType;
|
||||
if ($accessType === self::ACCESS_AUTO) {
|
||||
if (is_object($access) && is_string($key)) {
|
||||
$accessType = self::ACCESS_PROPERTY;
|
||||
} else {
|
||||
$accessType = self::ACCESS_KEY;
|
||||
}
|
||||
}
|
||||
return $accessType;
|
||||
}
|
||||
|
||||
protected function _has(): bool {
|
||||
$src = $this->access->get();
|
||||
$key = $this->key;
|
||||
$accessType = $this->_accessType($src, $key);
|
||||
if ($accessType === self::ACCESS_KEY) {
|
||||
return cl::phas($src, $key);
|
||||
} elseif ($accessType === self::ACCESS_PROPERTY) {
|
||||
$class = new ReflectionClass($src);
|
||||
return $class->hasProperty($key) || property_exists($src, $key);
|
||||
} else {
|
||||
throw self::unexpected_access_type();
|
||||
}
|
||||
}
|
||||
|
||||
protected function _get($default=null) {
|
||||
$src = $this->access->get();
|
||||
$key = $this->key;
|
||||
$accessType = $this->_accessType($src, $key);
|
||||
if ($accessType === self::ACCESS_KEY) {
|
||||
return cl::pget($src, $key);
|
||||
} elseif ($accessType === self::ACCESS_PROPERTY) {
|
||||
$class = new ReflectionClass($src);
|
||||
try {
|
||||
$property = $class->getProperty($key);
|
||||
$property->setAccessible(true);
|
||||
} catch (ReflectionException $e) {
|
||||
$property = null;
|
||||
}
|
||||
if ($property !== null) {
|
||||
return $property->getValue($src);
|
||||
} elseif (property_exists($src, $key)) {
|
||||
return $src->$key;
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
} else {
|
||||
throw self::unexpected_access_type();
|
||||
}
|
||||
}
|
||||
|
||||
protected function _pset(object $dest, $name, $value): void {
|
||||
$class = new ReflectionClass($dest);
|
||||
try {
|
||||
$property = $class->getProperty($name);
|
||||
$property->setAccessible(true);
|
||||
} catch (ReflectionException $e) {
|
||||
$property = null;
|
||||
}
|
||||
if ($property !== null) {
|
||||
$property->setValue($dest, $value);
|
||||
} else {
|
||||
$dest->$name = $value;
|
||||
}
|
||||
}
|
||||
|
||||
function isAllowEmpty(): bool {
|
||||
return $this->access->isAllowEmpty();
|
||||
}
|
||||
|
||||
function exists(): bool {
|
||||
if (!$this->access->exists()) return false;
|
||||
if ($this->key === null) return true;
|
||||
return $this->_has();
|
||||
}
|
||||
|
||||
function available(): bool {
|
||||
if (!$this->access->available()) return false;
|
||||
if ($this->key === null) return true;
|
||||
if (!$this->_has()) return false;
|
||||
return $this->isAllowEmpty() || $this->_get() !== "";
|
||||
}
|
||||
|
||||
function get($default=null) {
|
||||
if ($this->key === null) {
|
||||
return $this->access->get($default);
|
||||
}
|
||||
return $this->_get($default);
|
||||
}
|
||||
|
||||
function set($value): void {
|
||||
if ($this->key === null) {
|
||||
$this->access->set($value);
|
||||
return;
|
||||
}
|
||||
$dest = $this->access->get();
|
||||
$key = $this->key;
|
||||
$accessType = $this->_accessType($dest, $key);
|
||||
if ($accessType === self::ACCESS_KEY) {
|
||||
cl::pset($dest, $key, $value);
|
||||
$this->access->set($dest);
|
||||
} elseif ($accessType === self::ACCESS_PROPERTY) {
|
||||
$this->_pset($dest, $key, $value);
|
||||
} else {
|
||||
throw self::unexpected_access_type();
|
||||
}
|
||||
}
|
||||
|
||||
function del(): void {
|
||||
if ($this->key === null) {
|
||||
$this->access->del();
|
||||
return;
|
||||
}
|
||||
$dest = $this->access->get();
|
||||
$key = $this->key;
|
||||
$accessType = $this->_accessType($dest, $key);
|
||||
if ($accessType === self::ACCESS_KEY) {
|
||||
cl::pdel($dest, $key);
|
||||
$this->access->set($dest);
|
||||
} elseif ($accessType === self::ACCESS_PROPERTY) {
|
||||
$this->_pset($dest, $key, null);
|
||||
} else {
|
||||
throw self::unexpected_access_type();
|
||||
}
|
||||
}
|
||||
|
||||
function addKey($key, ?array $params=null): IAccess {
|
||||
if ($key === null) return $this;
|
||||
$accessType = $params["access_type"] ?? $this->accessType;
|
||||
if ($accessType === self::ACCESS_KEY && $accessType === $this->accessType) {
|
||||
if ($this->key !== null) $key = cl::merge($this->key, $key);
|
||||
return new ChainAccess($this->access, $key);
|
||||
} else {
|
||||
return new ChainAccess($this, $key);
|
||||
}
|
||||
}
|
||||
|
||||
function ensureAssoc(array $keys, ?array $params=null): void {
|
||||
#XXX fonction de $accessType?
|
||||
#$this->access->ensureAssoc($keys, $params);
|
||||
}
|
||||
|
||||
function ensureKeys(array $defaults, ?array $params=null): void {
|
||||
#XXX fonction de $accessType?
|
||||
#$this->access->ensureKeys($defaults, $params);
|
||||
}
|
||||
|
||||
function ensureOrder(array $keys, ?array $params=null): void {
|
||||
#XXX fonction de $accessType?
|
||||
#$this->access->ensureOrder($keys, $params);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\php\access;
|
||||
namespace nulib\php\access;
|
||||
|
||||
use nulib\cl;
|
||||
|
||||
@ -7,67 +7,99 @@ use nulib\cl;
|
||||
* Class FormAccess: accès à une valeur de $_POST puis $_GET, dans cet ordre
|
||||
*/
|
||||
class FormAccess 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 int|string */
|
||||
/** @var null|int|string|array */
|
||||
protected $key;
|
||||
|
||||
protected bool $allowEmpty;
|
||||
|
||||
function exists(): bool {
|
||||
protected function _exists(array $first, ?array $second=null): bool {
|
||||
$key = $this->key;
|
||||
if ($key === null) return false;
|
||||
return array_key_exists($key, $_POST) || array_key_exists($key, $_GET);
|
||||
if ($key === null) return true;
|
||||
if (cl::phas($first, $key)) return true;
|
||||
return $second !== null && cl::phas($second, $key);
|
||||
}
|
||||
|
||||
public function available(): bool {
|
||||
function exists(): bool {
|
||||
return $this->_exists($_POST, $_GET);
|
||||
}
|
||||
|
||||
protected function _available(array $first, ?array $second=null): bool {
|
||||
$key = $this->key;
|
||||
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] !== "";
|
||||
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) !== "";
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function get($default=null) {
|
||||
public function available(): bool {
|
||||
return $this->_available($_POST, $_GET);
|
||||
}
|
||||
|
||||
protected function _get($default, array $first, ?array $second=null) {
|
||||
$key = $this->key;
|
||||
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;
|
||||
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);
|
||||
} else {
|
||||
return $default;
|
||||
cl::pset($first, $key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
function set($value): void {
|
||||
$this->_set($value, $_POST, $_GET);
|
||||
}
|
||||
|
||||
function _del(array &$first, ?array &$second=null): void {
|
||||
$key = $this->key;
|
||||
if ($key === null) return;
|
||||
if (!array_key_exists($key, $_POST) && array_key_exists($key, $_GET)) {
|
||||
cl::set($_GET, $key, $value);
|
||||
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);
|
||||
} else {
|
||||
cl::set($_POST, $key, $value);
|
||||
cl::pdel($first, $key);
|
||||
}
|
||||
}
|
||||
|
||||
function del(): void {
|
||||
$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);
|
||||
}
|
||||
$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
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\php\access;
|
||||
namespace nulib\php\access;
|
||||
|
||||
use nulib\cl;
|
||||
|
||||
@ -8,42 +8,22 @@ use nulib\cl;
|
||||
*/
|
||||
class GetAccess extends FormAccess {
|
||||
function exists(): bool {
|
||||
$key = $this->key;
|
||||
if ($key === null) return false;
|
||||
return array_key_exists($key, $_GET);
|
||||
return $this->_exists($_GET);
|
||||
}
|
||||
|
||||
public function available(): bool {
|
||||
$key = $this->key;
|
||||
if ($key === null) return false;
|
||||
if (array_key_exists($key, $_GET)) {
|
||||
return $this->allowEmpty || $_GET[$key] !== "";
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return $this->_available($_GET);
|
||||
}
|
||||
|
||||
function get($default=null) {
|
||||
$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;
|
||||
}
|
||||
return $this->_get($default, $_GET);
|
||||
}
|
||||
|
||||
function set($value): void {
|
||||
$key = $this->key;
|
||||
if ($key === null) return;
|
||||
cl::set($_GET, $key, $value);
|
||||
$this->_set($value, $_GET);
|
||||
}
|
||||
|
||||
function del(): void {
|
||||
$key = $this->key;
|
||||
if ($key === null) return;
|
||||
cl::del($_GET, $key);
|
||||
$this->_del($_GET);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\php\access;
|
||||
namespace nulib\php\access;
|
||||
|
||||
use ReflectionClass;
|
||||
|
||||
/**
|
||||
* Interface IAccess: abstraction d'un accès complet à une valeur
|
||||
@ -25,4 +27,26 @@ 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;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\php\access;
|
||||
namespace nulib\php\access;
|
||||
|
||||
/**
|
||||
* Class IDeleter: une abstraction d'un objet qui permet de supprimer une valeur
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\php\access;
|
||||
namespace nulib\php\access;
|
||||
|
||||
/**
|
||||
* Class IGetter: une abstraction d'un objet qui permet d'obtenir une valeur
|
||||
@ -11,6 +11,12 @@ 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;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\php\access;
|
||||
namespace nulib\php\access;
|
||||
|
||||
/**
|
||||
* Class ISetter: une abstraction d'un objet qui permet de modifier une valeur
|
||||
|
@ -1,69 +1,188 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\php\access;
|
||||
namespace nulib\php\access;
|
||||
|
||||
use ArrayAccess;
|
||||
use nulib\cl;
|
||||
use nulib\ref\schema\ref_schema;
|
||||
|
||||
/**
|
||||
* Class KeyAccess: accès à une valeur d'une clé dans un tableau
|
||||
* Class KeyAccess: accès
|
||||
* - soit à une valeur d'un chemin de clé dans un tableau (si $key !== null)
|
||||
* - soit à une valeur scalaire (si $key === null)
|
||||
*/
|
||||
class KeyAccess extends AbstractAccess {
|
||||
function __construct(&$array, $key, ?array $params=null) {
|
||||
$this->array =& $array;
|
||||
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;
|
||||
$this->key = $key;
|
||||
$this->allowNull = $params["allow_null"] ?? true;
|
||||
$this->allowFalse = $params["allow_false"] ?? false;
|
||||
$this->allowEmpty = $params["allow_empty"] ?? true;
|
||||
$this->allowNull = $params["allow_null"] ?? static::ALLOW_NULL;
|
||||
$this->allowFalse = $params["allow_false"] ?? static::ALLOW_FALSE;
|
||||
}
|
||||
|
||||
/** @var array|ArrayAccess */
|
||||
protected $array;
|
||||
protected bool $protectDest;
|
||||
|
||||
function reset(&$array): self {
|
||||
$this->array =& $array;
|
||||
/** @var mixed|array|ArrayAccess */
|
||||
protected $dest;
|
||||
|
||||
/** @var null|int|string|array */
|
||||
protected $key;
|
||||
|
||||
function reset(&$dest, $key=null): self {
|
||||
$this->dest =& $dest;
|
||||
$this->key = $key;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @var int|string */
|
||||
protected $key;
|
||||
function resetKey($key=null): self {
|
||||
$this->key = $key;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected bool $allowNull;
|
||||
protected ?bool $allowNull;
|
||||
|
||||
protected bool $allowFalse;
|
||||
protected function isAllowNull(): bool {
|
||||
$allowNull = $this->allowNull;
|
||||
if ($allowNull !== null) return $allowNull;
|
||||
return $this->key !== null;
|
||||
}
|
||||
|
||||
protected bool $allowEmpty;
|
||||
protected ?bool $allowFalse;
|
||||
|
||||
protected function isAllowFalse(): bool {
|
||||
$allowFalse = $this->allowFalse;
|
||||
if ($allowFalse !== null) return $allowFalse;
|
||||
return $this->key === null;
|
||||
}
|
||||
|
||||
function exists(): bool {
|
||||
$key = $this->key;
|
||||
if ($key === null) return false;
|
||||
return cl::has($this->array, $key);
|
||||
if ($key === null) {
|
||||
return $this->isAllowNull() || $this->dest !== null;
|
||||
} else {
|
||||
return cl::phas($this->dest, $key);
|
||||
}
|
||||
}
|
||||
|
||||
function available(): bool {
|
||||
if (!$this->exists()) return false;
|
||||
$value = cl::get($this->array, $this->key);
|
||||
if ($value === null) return $this->allowNull;
|
||||
if ($value === false) return $this->allowFalse;
|
||||
$key = $this->key;
|
||||
if ($key === null) $value = $this->dest;
|
||||
else $value = cl::pget($this->dest, $key);
|
||||
if ($value === "") return $this->allowEmpty;
|
||||
if ($value === null) return $this->isAllowNull();
|
||||
if ($value === false) return $this->isAllowFalse();
|
||||
return true;
|
||||
}
|
||||
|
||||
function get($default=null) {
|
||||
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;
|
||||
$key = $this->key;
|
||||
if ($key === null) $value = $this->dest;
|
||||
else $value = cl::pget($this->dest, $key, $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 {
|
||||
if ($this->key === null) return;
|
||||
cl::set($this->array, $this->key, $value);
|
||||
$key = $this->key;
|
||||
if ($key === null) {
|
||||
if (!$this->protectDest) $this->dest = $value;
|
||||
} else {
|
||||
cl::pset($this->dest, $key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
function del(): void {
|
||||
if ($this->key === null) return;
|
||||
cl::del($this->array, $this->key);
|
||||
$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);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\php\access;
|
||||
namespace nulib\php\access;
|
||||
|
||||
use nulib\cl;
|
||||
|
||||
@ -8,42 +8,22 @@ use nulib\cl;
|
||||
*/
|
||||
class PostAccess extends FormAccess {
|
||||
function exists(): bool {
|
||||
$key = $this->key;
|
||||
if ($key === null) return false;
|
||||
return array_key_exists($key, $_POST);
|
||||
return $this->_exists($_POST);
|
||||
}
|
||||
|
||||
public function available(): bool {
|
||||
$key = $this->key;
|
||||
if ($key === null) return false;
|
||||
if (array_key_exists($key, $_POST)) {
|
||||
return $this->allowEmpty || $_POST[$key] !== "";
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return $this->_available($_POST);
|
||||
}
|
||||
|
||||
function get($default=null) {
|
||||
$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;
|
||||
}
|
||||
return $this->_get($default, $_POST);
|
||||
}
|
||||
|
||||
function set($value): void {
|
||||
$key = $this->key;
|
||||
if ($key === null) return;
|
||||
cl::set($_POST, $key, $value);
|
||||
$this->_set($value, $_POST);
|
||||
}
|
||||
|
||||
function del(): void {
|
||||
$key = $this->key;
|
||||
if ($key === null) return;
|
||||
cl::del($_POST, $key);
|
||||
$this->_del($_POST);
|
||||
}
|
||||
}
|
||||
|
173
src/php/access/PropertyAccess.php
Normal file
173
src/php/access/PropertyAccess.php
Normal file
@ -0,0 +1,173 @@
|
||||
<?php
|
||||
namespace nulib\php\access;
|
||||
|
||||
use nulib\StateException;
|
||||
use nulib\str;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
use ReflectionProperty;
|
||||
|
||||
class PropertyAccess extends AbstractAccess {
|
||||
const PROTECT_DEST = true;
|
||||
const MAP_NAMES = true;
|
||||
const ALLOW_NULL = true;
|
||||
const ALLOW_FALSE = false;
|
||||
|
||||
function __construct(?object $dest, ?string $name=null, ?array $params=null) {
|
||||
parent::__construct($params);
|
||||
$this->protectDest = $params["protect_dest"] ?? static::PROTECT_DEST;
|
||||
$this->mapNames = $params["map_names"] ?? static::MAP_NAMES;
|
||||
$this->_setName($name);
|
||||
$this->_setDest($dest);
|
||||
$this->allowNull = $params["allow_null"] ?? static::ALLOW_NULL;
|
||||
$this->allowFalse = $params["allow_false"] ?? static::ALLOW_FALSE;
|
||||
}
|
||||
|
||||
protected bool $protectDest;
|
||||
|
||||
protected ?object $dest;
|
||||
protected bool $mapNames;
|
||||
|
||||
protected ?string $name;
|
||||
|
||||
protected ?ReflectionProperty $property;
|
||||
|
||||
private function _getName(string $key): string {
|
||||
return $this->mapNames? str::us2camel($key): $key;
|
||||
}
|
||||
private function _setName(?string $name): void {
|
||||
if ($name !== null) $name = $this->_getName($name);
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
private function _getProperty(?string $name, ?ReflectionClass $class, ?object $object=null): ?ReflectionProperty {
|
||||
$property = null;
|
||||
if ($class === null && $object !== null) {
|
||||
$class = new ReflectionClass($object);
|
||||
}
|
||||
if ($class !== null && $name !== null) {
|
||||
try {
|
||||
$property = $class->getProperty($name);
|
||||
$property->setAccessible(true);
|
||||
} catch (ReflectionException $e) {
|
||||
}
|
||||
}
|
||||
return $property;
|
||||
}
|
||||
|
||||
private function _setDest(?object $dest): void {
|
||||
$this->dest = $dest;
|
||||
$this->property = $this->_getProperty($this->name, null, $dest);
|
||||
}
|
||||
|
||||
function reset(?object $dest, ?string $name=null): self {
|
||||
$this->_setName($name);
|
||||
$this->_setDest($dest);
|
||||
return $this;
|
||||
}
|
||||
|
||||
function resetKey($name=null): self {
|
||||
$this->_setName($name);
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected bool $allowNull;
|
||||
|
||||
protected bool $allowFalse;
|
||||
|
||||
function exists(): bool {
|
||||
$name = $this->name;
|
||||
if ($this->dest === null) return false;
|
||||
return $name === null
|
||||
|| $this->property !== null
|
||||
|| property_exists($this->dest, $name);
|
||||
}
|
||||
|
||||
protected function _get($default=null) {
|
||||
$name = $this->name;
|
||||
$property = $this->property;
|
||||
if ($this->dest === null) {
|
||||
return $default;
|
||||
} elseif ($name === null) {
|
||||
return $this->dest;
|
||||
} elseif ($property !== null) {
|
||||
return $property->getValue($this->dest);
|
||||
} elseif (property_exists($this->dest, $name)) {
|
||||
return $this->dest->$name;
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
|
||||
function available(): bool {
|
||||
if (!$this->exists()) return false;
|
||||
$value = $this->_get();
|
||||
if ($value === "") return $this->allowEmpty;
|
||||
if ($value === null) return $this->allowNull;
|
||||
if ($value === false) return $this->allowFalse;
|
||||
return true;
|
||||
}
|
||||
|
||||
function get($default=null) {
|
||||
if (!$this->exists()) return $default;
|
||||
$value = $this->_get();
|
||||
if ($value === "" && !$this->allowEmpty) return $default;
|
||||
if ($value === null && !$this->allowNull) return $default;
|
||||
if ($value === false && !$this->allowFalse) return $default;
|
||||
return $value;
|
||||
}
|
||||
|
||||
protected function _set($value): void {
|
||||
$name = $this->name;
|
||||
$property = $this->property;
|
||||
if ($this->dest === null) {
|
||||
throw StateException::unexpected_state("dest is null");
|
||||
} elseif ($name === null) {
|
||||
if (!$this->protectDest) $this->_setDest($value);
|
||||
} elseif ($property !== null) {
|
||||
$property->setValue($this->dest, $value);
|
||||
} else {
|
||||
$this->dest->$name = $value;
|
||||
}
|
||||
}
|
||||
|
||||
function set($value): void {
|
||||
$this->_set($value);
|
||||
}
|
||||
|
||||
function del(): void {
|
||||
$this->_set(null);
|
||||
}
|
||||
|
||||
function addKey($key): IAccess {
|
||||
if ($key === null) return $this;
|
||||
return new ChainAccess($this, $key);
|
||||
}
|
||||
|
||||
function ensureKeys(array $defaults, ?array $params=null): void {
|
||||
$dest = $this->dest;
|
||||
if ($dest === null) {
|
||||
# comme ne connait pas la classe de l'objet destination, on n'essaie pas
|
||||
# de le créer
|
||||
return;
|
||||
}
|
||||
$class = new ReflectionClass($dest);
|
||||
$keys = array_keys($defaults);
|
||||
$prefix = $params["key_prefix"] ?? null;
|
||||
$suffix = $params["key_suffix"] ?? null;
|
||||
foreach ($keys as $key) {
|
||||
$name = $this->_getName("$prefix$key$suffix");
|
||||
$property = $this->_getProperty($name, $class);
|
||||
if ($property !== null) {
|
||||
$type = $property->getType();
|
||||
if ($type !== null && !$property->isInitialized($dest) && $type->allowsNull()) {
|
||||
# initialiser avec null au lieu de $defaults[$key] pour respecter le
|
||||
# type de la propriété
|
||||
$property->setValue($dest, null);
|
||||
}
|
||||
} elseif (!property_exists($dest, $name)) {
|
||||
$dest->$name = $defaults[$key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\php\access;
|
||||
namespace nulib\php\access;
|
||||
|
||||
/**
|
||||
* Class ShadowAccess: accès en lecture depuis une instance de {@link IAccess}
|
||||
@ -16,6 +16,7 @@ namespace nur\sery\wip\php\access;
|
||||
*/
|
||||
class ShadowAccess extends AbstractAccess {
|
||||
function __construct(IAccess $reader, IAccess $writer) {
|
||||
parent::__construct();
|
||||
$this->reader = $reader;
|
||||
$this->writer = $writer;
|
||||
$this->getter = $reader;
|
||||
@ -27,6 +28,10 @@ class ShadowAccess extends AbstractAccess {
|
||||
|
||||
protected IGetter $getter;
|
||||
|
||||
public function isAllowEmpty(): bool {
|
||||
return $this->getter->isAllowEmpty();
|
||||
}
|
||||
|
||||
function exists(): bool {
|
||||
return $this->getter->exists();
|
||||
}
|
||||
@ -48,4 +53,20 @@ 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);
|
||||
}
|
||||
}
|
||||
|
@ -1,56 +1,8 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\php\access;
|
||||
namespace nulib\php\access;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
class ValueAccess extends KeyAccess {
|
||||
const ALLOW_NULL = false;
|
||||
const ALLOW_FALSE = true;
|
||||
const PROTECT_DEST = false;
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\php\coll;
|
||||
namespace nulib\php\coll;
|
||||
|
||||
use Iterator;
|
||||
use IteratorAggregate;
|
||||
use nulib\cl;
|
||||
use nulib\php\func;
|
||||
use nur\sery\wip\php\iter;
|
||||
use nulib\php\iter;
|
||||
use Traversable;
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php # -*- coding: utf-8 mode: php -*- vim:sw=2:sts=2:et:ai:si:sta:fenc=utf-8
|
||||
namespace nur\sery\wip\php;
|
||||
namespace nulib\php;
|
||||
|
||||
use Exception;
|
||||
use Generator;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema;
|
||||
namespace nulib\schema;
|
||||
|
||||
class OldSchema {
|
||||
/**
|
||||
|
@ -1,10 +1,8 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema;
|
||||
namespace nulib\schema;
|
||||
|
||||
use IteratorAggregate;
|
||||
use nur\sery\wip\schema\_assoc\AssocResult;
|
||||
use nur\sery\wip\schema\_list\ListResult;
|
||||
use nur\sery\wip\schema\_scalar\ScalarResult;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Class Result: résultat de l'analyse ou de la normalisation d'une valeur
|
||||
@ -17,6 +15,8 @@ use nur\sery\wip\schema\_scalar\ScalarResult;
|
||||
* @property bool $normalized si la valeur est valide, est-elle normalisée?
|
||||
* @property 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",
|
||||
"messageKey", "message", "exception",
|
||||
"origValue", "normalizedValue",
|
||||
];
|
||||
|
||||
@ -34,10 +34,6 @@ 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
|
||||
|
@ -1,22 +1,45 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema;
|
||||
namespace nulib\schema;
|
||||
|
||||
use ArrayAccess;
|
||||
use nulib\AccessException;
|
||||
use nulib\cl;
|
||||
use nulib\ref\schema\ref_schema;
|
||||
use nulib\ref\schema\ref_types;
|
||||
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;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -27,7 +50,7 @@ abstract class Schema implements ArrayAccess {
|
||||
* l'instance de Schema nouvelle créée
|
||||
* - sinon, prendre $definition comme définition
|
||||
*/
|
||||
static function ns(&$schema, $definition=null, $definitionKey=null, bool $normalize=true): self {
|
||||
static function ns($definition=null, $definitionKey=null, &$schema=null, bool $normalize=true): self {
|
||||
if (is_array($schema)) {
|
||||
$definition = $schema;
|
||||
$schema = null;
|
||||
@ -51,13 +74,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, &$schema=null, $definition=null, ?Wrapper &$wrapper=null): Wrapper {
|
||||
static function nw(&$value=null, $valueKey=null, $definition=null, &$schema=null, ?Wrapper &$wrapper=null): Wrapper {
|
||||
if ($definition === null) {
|
||||
# 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($schema, $definition)->getWrapper($value, $valueKey, $wrapper);
|
||||
return self::ns($definition, null, $schema)->getWrapper($value, $valueKey, null, $wrapper);
|
||||
}
|
||||
|
||||
protected static function have_nature(array $definition, ?string &$nature=null): bool {
|
||||
@ -75,18 +98,18 @@ abstract class Schema implements ArrayAccess {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected static function _normalize(&$definition, $definitionKey=null): void {
|
||||
protected static function _normalize_definition(&$definition, $definitionKey=null, ?array $natureMetaschema=null): void {
|
||||
if (!is_array($definition)) $definition = [$definition];
|
||||
# s'assurer que toutes les clés existent avec leur valeur par défaut
|
||||
$index = 0;
|
||||
foreach (array_keys(ref_schema::SCALAR_METASCHEMA) as $key) {
|
||||
foreach (array_keys(ref_schema::VALUE_METASCHEMA) as $key) {
|
||||
if (!array_key_exists($key, $definition)) {
|
||||
if (array_key_exists($index, $definition)) {
|
||||
$definition[$key] = $definition[$index];
|
||||
unset($definition[$index]);
|
||||
$index++;
|
||||
} else {
|
||||
$definition[$key] = ref_schema::SCALAR_METASCHEMA[$key][1];
|
||||
$definition[$key] = ref_schema::VALUE_METASCHEMA[$key][1];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -138,6 +161,12 @@ abstract class Schema implements ArrayAccess {
|
||||
# nature
|
||||
$nature = $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"];
|
||||
@ -158,22 +187,22 @@ abstract class Schema implements ArrayAccess {
|
||||
tbool::ensure_bool($definition["required"]);
|
||||
tbool::ensure_bool($definition["nullable"]);
|
||||
tcontent::ensure_ncontent($definition["desc"]);
|
||||
tcallable::ensure_ncallable($definition["analyzer_func"]);
|
||||
tcallable::ensure_ncallable($definition["extractor_func"]);
|
||||
tcallable::ensure_ncallable($definition["parser_func"]);
|
||||
tcallable::ensure_ncallable($definition["normalizer_func"]);
|
||||
tfunc::ensure_nfunc($definition["analyzer_func"]);
|
||||
tfunc::ensure_nfunc($definition["extractor_func"]);
|
||||
tfunc::ensure_nfunc($definition["parser_func"]);
|
||||
tfunc::ensure_nfunc($definition["normalizer_func"]);
|
||||
tarray::ensure_narray($definition["messages"]);
|
||||
tcallable::ensure_ncallable($definition["formatter_func"]);
|
||||
tfunc::ensure_nfunc($definition["formatter_func"]);
|
||||
tbool::ensure_nbool($definition["computed"]);
|
||||
|
||||
switch ($nature[0] ?? null) {
|
||||
case "assoc":
|
||||
foreach ($definition["schema"] as $key => &$keydef) {
|
||||
self::_normalize($keydef, $key);
|
||||
self::_normalize_definition($keydef, $key);
|
||||
}; unset($keydef);
|
||||
break;
|
||||
case "list":
|
||||
self::_normalize($definition["schema"]);
|
||||
self::_normalize_definition($definition["schema"]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -223,11 +252,11 @@ abstract class Schema implements ArrayAccess {
|
||||
case "assoc":
|
||||
foreach ($definition["schema"] as &$keydef) {
|
||||
self::_ensure_schema_instances($keydef);
|
||||
Schema::ns($keydef, null, null, false);
|
||||
Schema::ns(null, null, $keydef, false);
|
||||
}; unset($keydef);
|
||||
break;
|
||||
case "list":
|
||||
Schema::ns($definition["schema"], null, null, false);
|
||||
Schema::ns(null, null, $definition["schema"], false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -246,14 +275,16 @@ abstract class Schema implements ArrayAccess {
|
||||
return $this->_definition;
|
||||
}
|
||||
|
||||
/** 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; }
|
||||
/**
|
||||
* retourner la liste des clés valides pour l'accès aux valeurs et résultats
|
||||
*/
|
||||
abstract function getKeys(): array;
|
||||
|
||||
abstract function getWrapper(&$value=null, $valueKey=null, ?Wrapper &$wrapper=null): Wrapper;
|
||||
abstract function getSchema($key=false): Schema;
|
||||
|
||||
abstract protected function newWrapper(): Wrapper;
|
||||
|
||||
abstract function getWrapper(&$value=null, $valueKey=null, ?array $params=null, ?Wrapper &$wrapper=null): Wrapper;
|
||||
|
||||
#############################################################################
|
||||
# key & properties
|
||||
@ -272,7 +303,15 @@ abstract class Schema implements ArrayAccess {
|
||||
throw AccessException::read_only(null, $offset);
|
||||
}
|
||||
|
||||
const _PROPERTY_PKEYS = [];
|
||||
const _PROPERTY_PKEYS = [
|
||||
"analyzerFunc" => "analyzer_func",
|
||||
"extractorFunc" => "extractor_func",
|
||||
"parserFunc" => "parser_func",
|
||||
"normalizerFunc" => "normalizer_func",
|
||||
"formatterFunc" => "formatter_func",
|
||||
"nature" => ["", 0],
|
||||
];
|
||||
|
||||
function __get($name) {
|
||||
$pkey = cl::get(static::_PROPERTY_PKEYS, $name, $name);
|
||||
return cl::pget($this->definition, $pkey);
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema;
|
||||
namespace nulib\schema;
|
||||
|
||||
use Exception;
|
||||
|
||||
|
@ -1,20 +1,38 @@
|
||||
# nulib\schema
|
||||
|
||||
* 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
|
||||
* 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
|
||||
|
||||
* 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.)
|
||||
* possibilité de spécifier le format de la date à analyser
|
||||
* parse_format pour spécifier le format d'analyse au lieu de l'auto-détecter
|
||||
|
||||
* ScalarSchema::from_property()
|
||||
|
||||
* 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
|
||||
@ -58,6 +76,8 @@
|
||||
|
||||
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"
|
||||
valeurs séquentielles sont des clés du schéma", soit un mode automatique
|
||||
activé par un paramètre où une valeur "val" devient "val"=>true si la clé
|
||||
"val" existe dans le schéma
|
||||
|
||||
-*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary
|
@ -1,20 +1,107 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema;
|
||||
namespace nulib\schema;
|
||||
|
||||
use ArrayAccess;
|
||||
use IteratorAggregate;
|
||||
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;
|
||||
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;
|
||||
|
||||
abstract class Wrapper implements ArrayAccess, IteratorAggregate {
|
||||
function isAssoc(?AssocWrapper &$wrapper=null): bool { return false; }
|
||||
function isList(?ListWrapper &$wrapper=null): bool { return false; }
|
||||
function isScalar(?ScalarWrapper &$wrapper=null): bool { return false; }
|
||||
protected WrapperContext $context;
|
||||
|
||||
/** spécifier la valeur destination gérée par cet objet */
|
||||
abstract function reset(&$value, $valueKey=null, ?bool $verifix=null): self;
|
||||
/** 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtenir la liste des clés valides pour les valeurs accessibles via cet
|
||||
@ -38,37 +125,80 @@ abstract class Wrapper implements ArrayAccess, IteratorAggregate {
|
||||
}
|
||||
|
||||
/**
|
||||
* obtenir le résultat de l'appel d'une des fonctions {@link set()} ou
|
||||
* {@link unset()}
|
||||
* 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()}
|
||||
*/
|
||||
abstract function getResult(): Result;
|
||||
function getResult($key=false): Result {
|
||||
return $this->context->result;
|
||||
}
|
||||
|
||||
/** retourner true si la valeur existe */
|
||||
abstract function isPresent(): bool;
|
||||
function isPresent($key=false): bool {
|
||||
return $this->getResult($key)->present;
|
||||
}
|
||||
|
||||
/** retourner le type associé à la valeur */
|
||||
abstract function getType(): IType;
|
||||
function getType($key=false): IType {
|
||||
return $this->context->type;
|
||||
}
|
||||
|
||||
/** retourner true si la valeur est disponible */
|
||||
abstract function isAvailable(): bool;
|
||||
function isAvailable($key=false): bool {
|
||||
return $this->getResult($key)->available;
|
||||
}
|
||||
|
||||
/** retourner true si la valeur est valide */
|
||||
abstract function isValid(): bool;
|
||||
function isValid($key=false): bool {
|
||||
return $this->getResult($key)->valid;
|
||||
}
|
||||
|
||||
/** retourner true si la valeur est dans sa forme normalisée */
|
||||
abstract function isNormalized(): bool;
|
||||
function isNormalized($key=false): bool {
|
||||
return $this->getResult($key)->normalized;
|
||||
}
|
||||
|
||||
/** obtenir la valeur */
|
||||
abstract function get($default=null);
|
||||
function get($default=null, $key=false) {
|
||||
$context = $this->context;
|
||||
if (!$context->result->available) return $default;
|
||||
return $context->input->get($context->valueKey);
|
||||
}
|
||||
|
||||
/** remplacer la valeur */
|
||||
abstract function set($value): self;
|
||||
function set($value, ?array $params=null, $key=false): self {
|
||||
$context = $this->context;
|
||||
$context->input->set($value, $context->valueKey);
|
||||
$this->afterModify($params);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** supprimer la valeur */
|
||||
abstract function unset(): 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);
|
||||
}
|
||||
}
|
||||
|
||||
/** formatter la valeur pour affichage */
|
||||
abstract function format($format=null): string;
|
||||
function format($format=null, $key=false): string {
|
||||
return $this->_format($this->context, $format);
|
||||
}
|
||||
|
||||
#############################################################################
|
||||
# key & properties
|
||||
@ -78,14 +208,14 @@ abstract class Wrapper implements ArrayAccess, IteratorAggregate {
|
||||
}
|
||||
|
||||
function offsetGet($offset) {
|
||||
return $this->select($offset);
|
||||
return $this->get(null, $offset);
|
||||
}
|
||||
|
||||
function offsetSet($offset, $value): void {
|
||||
$this->select($offset)->set($value);
|
||||
$this->set($value, null, $offset);
|
||||
}
|
||||
|
||||
function offsetUnset($offset): void {
|
||||
$this->select($offset)->unset();
|
||||
$this->unset(null, $offset);
|
||||
}
|
||||
}
|
||||
|
@ -1,30 +1,46 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema;
|
||||
namespace nulib\schema;
|
||||
|
||||
use nur\sery\wip\schema\input\Input;
|
||||
use nur\sery\wip\schema\types\IType;
|
||||
use nulib\ref\schema\ref_schema;
|
||||
use nulib\schema\input\Input;
|
||||
use nulib\schema\types\IType;
|
||||
|
||||
class WrapperContext {
|
||||
function __construct(Schema $schema, Wrapper $wrapper, Input $input, $valueKey, Result $result) {
|
||||
|
||||
function __construct(Schema $schema, ?Input $input, $valueKey, ?array $params) {
|
||||
$this->resetParams($params);
|
||||
$this->schema = $schema;
|
||||
$this->wrapper = $wrapper;
|
||||
$this->input = $input;
|
||||
$this->result = $result;
|
||||
$this->type = null;
|
||||
$this->origValue = null;
|
||||
$this->value = null;
|
||||
if ($input !== null) $this->input = $input;
|
||||
$this->valueKey = $valueKey;
|
||||
}
|
||||
|
||||
public ?array $params;
|
||||
public bool $analyze, $analyzed = false;
|
||||
public bool $normalize, $normalized = false;
|
||||
public ?bool $throw;
|
||||
|
||||
function resetParams(?array $params): void {
|
||||
$this->params = $params;
|
||||
$this->analyze = $params["analyze"] ?? ref_schema::PARAMS_SCHEMA["analyze"][1];
|
||||
$this->normalize = $params["normalize"] ?? ref_schema::PARAMS_SCHEMA["normalize"][1];
|
||||
$this->throw = $params["throw"] ?? ref_schema::PARAMS_SCHEMA["throw"][1];
|
||||
}
|
||||
|
||||
/** schéma de la valeur */
|
||||
public Schema $schema;
|
||||
public Wrapper $wrapper;
|
||||
/** source et destination de la valeur */
|
||||
public Input $input;
|
||||
public Result $result;
|
||||
public ?IType $type;
|
||||
/** @var mixed */
|
||||
public $origValue;
|
||||
/** @var mixed */
|
||||
public $value;
|
||||
/** @var int|string|null */
|
||||
/** @var string|int|null clé de la valeur dans le tableau destination */
|
||||
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;
|
||||
}
|
||||
|
@ -1,53 +0,0 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\_assoc;
|
||||
|
||||
use nulib\ValueException;
|
||||
use nur\sery\wip\schema\Result;
|
||||
|
||||
class AssocResult extends Result {
|
||||
function __construct(Result $arrayResult, array &$keyResults) {
|
||||
$this->arrayResult = $arrayResult;
|
||||
$this->keyResults =& $keyResults;
|
||||
$this->result =& $this->arrayResult;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
function isAssoc(?AssocResult &$result=null): bool { $result = $this; return true;}
|
||||
|
||||
protected Result $arrayResult;
|
||||
|
||||
/** @var Result[] */
|
||||
protected array $keyResults;
|
||||
|
||||
function getKeys(): array {
|
||||
return array_keys($this->keyResults);
|
||||
}
|
||||
|
||||
protected Result $result;
|
||||
|
||||
function select($key): Result {
|
||||
if ($key === null) {
|
||||
$this->result =& $this->arrayResult;
|
||||
} elseif (array_key_exists($key, $this->keyResults)) {
|
||||
$this->result =& $this->keyResults[$key];
|
||||
} else {
|
||||
throw ValueException::invalid_key($key);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
function reset(): void {
|
||||
$this->arrayResult->reset();
|
||||
foreach ($this->keyResults as $result) {
|
||||
$result->reset();
|
||||
}
|
||||
}
|
||||
|
||||
function __get(string $name) {
|
||||
return $this->result[$name];
|
||||
}
|
||||
|
||||
function __set(string $name, $value): void {
|
||||
$this->result[$name] = $value;
|
||||
}
|
||||
}
|
@ -1,21 +1,19 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\_assoc;
|
||||
namespace nulib\schema\_assoc;
|
||||
|
||||
use nulib\cl;
|
||||
use nulib\ref\schema\ref_schema;
|
||||
use nur\sery\wip\schema\Schema;
|
||||
use nur\sery\wip\schema\Wrapper;
|
||||
use nulib\ValueException;
|
||||
use nulib\schema\Schema;
|
||||
use nulib\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()} pourrait normaliser
|
||||
* associatif que {@link normalize_definition()} pourrait normaliser
|
||||
*/
|
||||
static function isa_definition($definition): bool {
|
||||
if (!is_array($definition)) return false;
|
||||
@ -27,7 +25,7 @@ class AssocSchema extends Schema {
|
||||
return !cl::have_num_keys($definition);
|
||||
}
|
||||
|
||||
static function normalize($definition, $definitionKey=null): array {
|
||||
static function normalize_definition($definition, $definitionKey=null): array {
|
||||
if (!is_array($definition)) $definition = [$definition];
|
||||
if (!self::have_nature($definition)) {
|
||||
$definition = [
|
||||
@ -36,7 +34,8 @@ class AssocSchema extends Schema {
|
||||
"schema" => $definition,
|
||||
];
|
||||
}
|
||||
self::_normalize($definition, $definitionKey);
|
||||
$natureMetaschema = array_merge(ref_schema::NATURE_METASCHEMA, ref_schema::ASSOC_NATURE_METASCHEMA);
|
||||
self::_normalize_definition($definition, $definitionKey, $natureMetaschema);
|
||||
self::_ensure_nature($definition, "assoc", "array");
|
||||
return $definition;
|
||||
}
|
||||
@ -44,25 +43,54 @@ 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, $definitionKey);
|
||||
$definition = self::normalize_definition($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;
|
||||
}
|
||||
|
||||
function isAssoc(?AssocSchema &$schema=null): bool {
|
||||
$schema = $this;
|
||||
return true;
|
||||
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;
|
||||
}
|
||||
|
||||
protected function newWrapper(): AssocWrapper {
|
||||
return new AssocWrapper($this);
|
||||
}
|
||||
|
||||
function getWrapper(&$array=null, $arrayKey=null, ?Wrapper &$wrapper=null): AssocWrapper {
|
||||
function getWrapper(&$value=null, $valueKey=null, ?array $params=null, ?Wrapper &$wrapper=null): AssocWrapper {
|
||||
# si pas de valeur ni de wrapper, pas d'analyse et donc pas d'exception
|
||||
# cf le code similaire dans AssocWrapper::__construct()
|
||||
$dontAnalyze = $value === null && $wrapper === null;
|
||||
if (!($wrapper instanceof AssocWrapper)) $wrapper = $this->newWrapper();
|
||||
return $wrapper->reset($array, $arrayKey);
|
||||
|
||||
# la nature du schéma peut contenir des paramètres par défaut
|
||||
$nature = $this->definition[""];
|
||||
foreach (array_keys(ref_schema::ASSOC_PARAMS_SCHEMA) as $paramKey) {
|
||||
$paramValue = $nature[$paramKey] ?? null;
|
||||
if ($paramValue !== null) $params[$paramKey] = $paramValue;
|
||||
}
|
||||
if ($params !== null) $wrapper->resetParams($params);
|
||||
|
||||
return $wrapper->reset($value, $valueKey, $dontAnalyze? ["analyze" => false]: null);
|
||||
}
|
||||
}
|
||||
|
@ -1,140 +1,185 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\_assoc;
|
||||
namespace nulib\schema\_assoc;
|
||||
|
||||
use nulib\cl;
|
||||
use nulib\ref\schema\ref_analyze;
|
||||
use nulib\ValueException;
|
||||
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;
|
||||
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;
|
||||
|
||||
class AssocWrapper extends Wrapper {
|
||||
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;
|
||||
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);
|
||||
}
|
||||
$this->schema = $schema;
|
||||
$this->verifix = $verifix;
|
||||
$this->throw = $throw ?? false;
|
||||
$this->result = new AssocResult();
|
||||
$this->reset($array, $arrayKey);
|
||||
$this->throw = $throw ?? true;
|
||||
}
|
||||
|
||||
function isAssoc(?AssocWrapper &$wrapper=null): bool { $wrapper = $this; return true; }
|
||||
/** @var AssocWrapperContext */
|
||||
protected WrapperContext $context;
|
||||
|
||||
protected bool $verifix;
|
||||
|
||||
protected 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);
|
||||
protected function resetContext($resetSelectedKey): void {
|
||||
parent::resetContext($resetSelectedKey);
|
||||
$context = $this->context;
|
||||
$context->arrayWrapper->getResult()->reset();
|
||||
foreach ($context->keyWrappers as $wrapper) {
|
||||
$wrapper->getResult()->reset();
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
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);
|
||||
return $this;
|
||||
}
|
||||
|
||||
function getKeys(): array {
|
||||
return $this->keys;
|
||||
return $this->context->keys;
|
||||
}
|
||||
|
||||
function select($key=null): ScalarWrapper {
|
||||
$wrapper = $this->wrappers[$key] ?? null;
|
||||
if ($key !== null) return $wrapper;
|
||||
throw ValueException::invalid_key($key);
|
||||
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;
|
||||
}
|
||||
|
||||
/** @param Result[] $results */
|
||||
function verifix(?bool $throw=null, ?array &$results=null): bool {
|
||||
/** @param string|int|null $key */
|
||||
function select($key=null): Wrapper {
|
||||
$wrapper = $this->_getWrapper($key);
|
||||
$this->context->selectedKey = $key;
|
||||
return $wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AssocWrapperContext $context
|
||||
* @param AssocWrapper $wrapper
|
||||
*/
|
||||
static function _analyze(WrapperContext $context, Wrapper $wrapper, ?array $params): int {
|
||||
if ($params["ensure_array"] ?? $context->ensureArray) {
|
||||
$valueKey = $context->valueKey;
|
||||
$array = $context->input->get($valueKey);
|
||||
if ($array === null) $context->input->set([], $valueKey);
|
||||
}
|
||||
|
||||
function getResult(): AssocResult {
|
||||
return $this->result;
|
||||
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 isPresent(): bool {
|
||||
return $this->result->present;
|
||||
/**
|
||||
* @param AssocWrapperContext $context
|
||||
* @param AssocWrapper $wrapper
|
||||
*/
|
||||
static function _normalize(WrapperContext $context, Wrapper $wrapper, ?array $params): bool {
|
||||
$ensureKeys = $params["ensure_keys"] ?? $context->ensureKeys;
|
||||
$ensureOrder = $params["ensure_order"] ?? $context->ensureOrder;
|
||||
if ($ensureKeys || $ensureOrder) {
|
||||
$schema = $context->schema;
|
||||
$keys = $schema->getKeys();
|
||||
if ($ensureKeys) {
|
||||
$defaults = [];
|
||||
foreach ($keys as $key) {
|
||||
$default = $schema->getSchema($key)->default;
|
||||
if ($default === null) {
|
||||
$default = $wrapper->getType($key)->getNullValue();
|
||||
}
|
||||
$defaults[$key] = $default;
|
||||
}
|
||||
}
|
||||
if ($ensureKeys) $context->input->ensureKeys($defaults, $params);
|
||||
if ($ensureOrder) $context->input->ensureOrder($keys, $params);
|
||||
}
|
||||
|
||||
$modified = ScalarWrapper::_normalize($context, $wrapper, $params);
|
||||
foreach ($context->keyWrappers as $keyWrapper) {
|
||||
if ($keyWrapper->normalize($params)) $modified = true;
|
||||
}
|
||||
return $modified;
|
||||
}
|
||||
|
||||
function getType(): IType {
|
||||
return $this->arrayType;
|
||||
function getResult($key=false): Result {
|
||||
if ($key === false) $key = $this->context->selectedKey;
|
||||
return $this->_getWrapper($key)->getResult();
|
||||
}
|
||||
|
||||
function isAvailable(): bool {
|
||||
return $this->result->available;
|
||||
function getType($key=false): IType {
|
||||
if ($key === false) $key = $this->context->selectedKey;
|
||||
return $this->_getWrapper($key)->getType();
|
||||
}
|
||||
|
||||
function isValid(): bool {
|
||||
return $this->result->valid;
|
||||
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 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();
|
||||
function set($value, ?array $params=null, $key=false): Wrapper {
|
||||
$context = $this->context;
|
||||
if ($key === false) $key = $context->selectedKey;
|
||||
$this->_getWrapper($key)->set($value);
|
||||
return $this;
|
||||
}
|
||||
|
||||
function unset(?bool $verifix=null): AssocWrapper {
|
||||
$this->input->unset($this->arrayKey);
|
||||
$this->analyze();
|
||||
if ($verifix ?? $this->verifix) $this->verifix();
|
||||
function unset(?array $params=null, $key=false): Wrapper {
|
||||
$context = $this->context;
|
||||
if ($key === false) $key = $context->selectedKey;
|
||||
$this->_getWrapper($key)->unset();
|
||||
return $this;
|
||||
}
|
||||
|
||||
function format($format = null): string {
|
||||
// TODO: Implement format() method.
|
||||
}
|
||||
|
||||
function ensureKeys(): bool {
|
||||
}
|
||||
function orderKeys(): bool {
|
||||
function format($format=null, $key=false): string {
|
||||
$context = $this->context;
|
||||
if ($key === false) $key = $context->selectedKey;
|
||||
return $this->_getWrapper($key)->format($format);
|
||||
}
|
||||
}
|
||||
|
31
src/schema/_assoc/AssocWrapperContext.php
Normal file
31
src/schema/_assoc/AssocWrapperContext.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
namespace nulib\schema\_assoc;
|
||||
|
||||
use nulib\ref\schema\ref_schema;
|
||||
use nulib\schema\_scalar\ScalarWrapper;
|
||||
use nulib\schema\Wrapper;
|
||||
use nulib\schema\WrapperContext;
|
||||
|
||||
class AssocWrapperContext extends WrapperContext {
|
||||
|
||||
public bool $ensureArray;
|
||||
public bool $ensureAssoc;
|
||||
public bool $ensureKeys;
|
||||
public bool $ensureOrder;
|
||||
|
||||
public function resetParams(?array $params): void {
|
||||
parent::resetParams($params);
|
||||
$this->ensureArray = $params["ensure_array"] ?? ref_schema::ASSOC_PARAMS_SCHEMA["ensure_array"][1];
|
||||
$this->ensureAssoc = $params["ensure_assoc"] ?? ref_schema::ASSOC_PARAMS_SCHEMA["ensure_assoc"][1];
|
||||
$this->ensureKeys = $params["ensure_keys"] ?? ref_schema::ASSOC_PARAMS_SCHEMA["ensure_keys"][1];
|
||||
$this->ensureOrder = $params["ensure_order"] ?? ref_schema::ASSOC_PARAMS_SCHEMA["ensure_order"][1];
|
||||
}
|
||||
|
||||
public ?ScalarWrapper $arrayWrapper = null;
|
||||
|
||||
/** liste des clés valides */
|
||||
public array $keys;
|
||||
|
||||
/** @var Wrapper[] */
|
||||
public array $keyWrappers;
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\_list;
|
||||
namespace nulib\schema\_list;
|
||||
|
||||
use nulib\ValueException;
|
||||
use nur\sery\wip\schema\Result;
|
||||
use nulib\schema\Result;
|
||||
|
||||
class ListResult extends Result {
|
||||
function __construct(Result $arrayResult, array &$keyResults) {
|
||||
@ -12,8 +12,6 @@ class ListResult extends Result {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
function isList(?ListResult &$result=null): bool { $result = $this; return true;}
|
||||
|
||||
protected Result $arrayResult;
|
||||
|
||||
/** @var Result[] */
|
||||
|
@ -1,9 +1,10 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\_list;
|
||||
namespace nulib\schema\_list;
|
||||
|
||||
use nulib\ref\schema\ref_schema;
|
||||
use nur\sery\wip\schema\Schema;
|
||||
use nur\sery\wip\schema\Wrapper;
|
||||
use nulib\ValueException;
|
||||
use nulib\schema\Schema;
|
||||
use nulib\schema\Wrapper;
|
||||
|
||||
class ListSchema extends Schema {
|
||||
/** @var array meta-schema d'un schéma de nature liste */
|
||||
@ -34,7 +35,7 @@ class ListSchema extends Schema {
|
||||
"schema" => $definition[0],
|
||||
];
|
||||
}
|
||||
self::_normalize($definition, $definitionKey);
|
||||
self::_normalize_definition($definition, $definitionKey);
|
||||
self::_ensure_nature($definition, "list", "array");
|
||||
return $definition;
|
||||
}
|
||||
@ -50,17 +51,26 @@ class ListSchema extends Schema {
|
||||
$this->definition = $definition;
|
||||
}
|
||||
|
||||
function isList(?ListSchema &$schema=null): bool {
|
||||
$schema = $this;
|
||||
return true;
|
||||
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;
|
||||
}
|
||||
|
||||
protected function newWrapper(): ListWrapper {
|
||||
return new ListWrapper($this);
|
||||
}
|
||||
|
||||
function getWrapper(&$value=null, $valueKey=null, ?Wrapper &$wrapper=null): ListWrapper {
|
||||
function getWrapper(&$value=null, $valueKey=null, ?array $params = null, ?Wrapper &$wrapper=null): ListWrapper {
|
||||
# si pas de valeur ni de wrapper, pas de vérification et donc pas d'exception
|
||||
# cf le code similaire dans ScalarWrapper::__construct()
|
||||
$verifix = $value !== null || $wrapper !== null;
|
||||
if (!($wrapper instanceof ListWrapper)) $wrapper = $this->newWrapper();
|
||||
return $wrapper->reset($value, $valueKey);
|
||||
return $wrapper->reset($value, $valueKey, $verifix);
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,10 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\_list;
|
||||
namespace nulib\schema\_list;
|
||||
|
||||
use nur\sery\wip\schema\Result;
|
||||
use nur\sery\wip\schema\Wrapper;
|
||||
use nulib\schema\Result;
|
||||
use nulib\schema\Wrapper;
|
||||
|
||||
abstract/*XXX*/ class ListWrapper extends Wrapper {
|
||||
function isList(?ListWrapper &$wrapper=null): bool { $wrapper = $this; return true; }
|
||||
|
||||
function ensureKeys(): bool {
|
||||
}
|
||||
|
||||
|
@ -1,21 +1,21 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\_scalar;
|
||||
namespace nulib\schema\_scalar;
|
||||
|
||||
use nulib\cl;
|
||||
use nulib\ref\schema\ref_analyze;
|
||||
use nulib\ref\schema\ref_schema;
|
||||
use nulib\ValueException;
|
||||
use nur\sery\wip\schema\Result;
|
||||
use nulib\schema\Result;
|
||||
use nulib\schema\Schema;
|
||||
use nulib\schema\Wrapper;
|
||||
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 [null];
|
||||
return ScalarSchema::KEYS;
|
||||
}
|
||||
|
||||
function select($key): Result {
|
||||
@ -23,8 +23,7 @@ class ScalarResult extends Result {
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @var array */
|
||||
protected $result;
|
||||
protected array $result;
|
||||
|
||||
function reset(): void {
|
||||
$this->result = array_merge(
|
||||
@ -46,26 +45,13 @@ class ScalarResult extends Result {
|
||||
$this->result[$name] = $value;
|
||||
}
|
||||
|
||||
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 {
|
||||
protected function getMessage(string $key, Schema $schema): string {
|
||||
$message = cl::get($schema->messages, $key);
|
||||
if ($message !== null) return $message;
|
||||
return cl::get(ref_schema::MESSAGES, $key);
|
||||
}
|
||||
|
||||
function setMissing(ScalarSchema $schema): int {
|
||||
function setMissing( Schema $schema): int {
|
||||
$this->resultAvailable = true;
|
||||
$this->present = false;
|
||||
$this->available = false;
|
||||
@ -75,15 +61,13 @@ class ScalarResult extends Result {
|
||||
$this->normalized = true;
|
||||
return ref_analyze::NORMALIZED;
|
||||
} else {
|
||||
$messageKey = $this->messageKey = "missing";
|
||||
$message = $this->getMessage($messageKey, $schema);
|
||||
self::replace_key($message, $schema->name);
|
||||
$this->message = $message;
|
||||
$this->messageKey = $messageKey = "missing";
|
||||
$this->message = $this->getMessage($messageKey, $schema);
|
||||
return ref_analyze::MISSING;
|
||||
}
|
||||
}
|
||||
|
||||
function setUnavailable(ScalarSchema $schema): int {
|
||||
function setUnavailable( Schema $schema): int {
|
||||
$this->resultAvailable = true;
|
||||
$this->present = true;
|
||||
$this->available = false;
|
||||
@ -93,15 +77,13 @@ class ScalarResult extends Result {
|
||||
$this->normalized = true;
|
||||
return ref_analyze::NORMALIZED;
|
||||
} else {
|
||||
$messageKey = $this->messageKey = "unavailable";
|
||||
$message = $this->getMessage($messageKey, $schema);
|
||||
self::replace_key($message, $schema->name);
|
||||
$this->message = $message;
|
||||
$this->messageKey = $messageKey = "unavailable";
|
||||
$this->message = $this->getMessage($messageKey, $schema);
|
||||
return ref_analyze::UNAVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
function setNull(ScalarSchema $schema): int {
|
||||
function setNull( Schema $schema): int {
|
||||
$this->resultAvailable = true;
|
||||
$this->present = true;
|
||||
$this->available = true;
|
||||
@ -111,33 +93,53 @@ class ScalarResult extends Result {
|
||||
$this->normalized = true;
|
||||
return ref_analyze::NORMALIZED;
|
||||
} else {
|
||||
$messageKey = $this->messageKey = "null";
|
||||
$message = $this->getMessage($messageKey, $schema);
|
||||
self::replace_key($message, $schema->name);
|
||||
$this->message = $message;
|
||||
$this->messageKey = $messageKey = "null";
|
||||
$this->message = $this->getMessage($messageKey, $schema);
|
||||
return ref_analyze::NULL;
|
||||
}
|
||||
}
|
||||
|
||||
function setInvalid($value, ScalarSchema $schema, ?Throwable $t=null): int {
|
||||
function setInvalid($value, Schema $schema, ?Throwable $exception=null): int {
|
||||
$this->resultAvailable = true;
|
||||
$this->present = true;
|
||||
$this->available = true;
|
||||
$this->null = false;
|
||||
$this->valid = false;
|
||||
$this->origValue = $value;
|
||||
$messageKey = $this->messageKey = "invalid";
|
||||
$this->messageKey = $messageKey = "invalid";
|
||||
$message = $this->getMessage($messageKey, $schema);
|
||||
self::replace_key($message, $schema->name);
|
||||
self::replace_orig($message, $schema->orig);
|
||||
if ($t !== null) {
|
||||
$tmessage = ValueException::get_message($t);
|
||||
if ($tmessage) $message .= ": $tmessage";
|
||||
if ($exception !== null) {
|
||||
$tmessage = ValueException::get_message($exception);
|
||||
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;
|
||||
@ -159,6 +161,10 @@ class ScalarResult extends Result {
|
||||
}
|
||||
|
||||
function throw(bool $throw): void {
|
||||
if ($throw) throw new ValueException($this->message);
|
||||
if ($throw) {
|
||||
$exception = $this->exception;
|
||||
if ($exception !== null) throw $exception;
|
||||
else throw new ValueException($this->message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,41 +1,19 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\_scalar;
|
||||
namespace nulib\schema\_scalar;
|
||||
|
||||
use nulib\cl;
|
||||
use nulib\ref\schema\ref_schema;
|
||||
use nur\sery\wip\schema\Schema;
|
||||
use nur\sery\wip\schema\types\IType;
|
||||
use nur\sery\wip\schema\Wrapper;
|
||||
use nulib\ValueException;
|
||||
use nulib\schema\Schema;
|
||||
use nulib\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()} pourrait normaliser
|
||||
* {@link normalize_definition()} pourrait normaliser
|
||||
*/
|
||||
static function isa_definition($definition): bool {
|
||||
# chaine ou null
|
||||
@ -64,8 +42,9 @@ class ScalarSchema extends Schema {
|
||||
return $haveIndex0 && $count > 1;
|
||||
}
|
||||
|
||||
static function normalize($definition, $definitionKey=null): array {
|
||||
self::_normalize($definition, $definitionKey);
|
||||
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);
|
||||
self::_ensure_nature($definition, "scalar");
|
||||
return $definition;
|
||||
}
|
||||
@ -73,40 +52,47 @@ 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, $definitionKey);
|
||||
$definition = self::normalize_definition($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;
|
||||
}
|
||||
|
||||
function isScalar(?ScalarSchema &$schema=null): bool {
|
||||
$schema = $this;
|
||||
return true;
|
||||
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);
|
||||
}
|
||||
|
||||
protected function newWrapper(): ScalarWrapper {
|
||||
return new ScalarWrapper($this);
|
||||
}
|
||||
|
||||
function getWrapper(&$value=null, $valueKey=null, ?Wrapper &$wrapper=null): ScalarWrapper {
|
||||
function getWrapper(&$value=null, $valueKey=null, ?array $params=null, ?Wrapper &$wrapper=null): ScalarWrapper {
|
||||
# si pas de valeur ni de wrapper, pas de vérification et donc pas d'exception
|
||||
# cf le code similaire dans ScalarWrapper::__construct()
|
||||
$verifix = $value !== null || $wrapper !== null;
|
||||
$dontAnalyze = $value === null && $wrapper === null;
|
||||
if (!($wrapper instanceof ScalarWrapper)) $wrapper = $this->newWrapper();
|
||||
return $wrapper->reset($value, $valueKey, $verifix);
|
||||
|
||||
# la nature du schéma peut contenir des paramètres par défaut
|
||||
$nature = $this->definition[""];
|
||||
foreach (array_keys(ref_schema::SCALAR_PARAMS_SCHEMA) as $paramKey) {
|
||||
$paramValue = $nature[$paramKey] ?? null;
|
||||
if ($paramValue !== null) $params[$paramKey] = $paramValue;
|
||||
}
|
||||
if ($params !== null) $wrapper->resetParams($params);
|
||||
|
||||
return $wrapper->reset($value, $valueKey, $dontAnalyze? ["analyze" => false]: null);
|
||||
}
|
||||
|
||||
#############################################################################
|
||||
# key & properties
|
||||
|
||||
const _PROPERTY_PKEYS = [
|
||||
"analyzerFunc" => "analyzer_func",
|
||||
"extractorFunc" => "extractor_func",
|
||||
"parserFunc" => "parser_func",
|
||||
"normalizerFunc" => "normalizer_func",
|
||||
"formatterFunc" => "formatter_func",
|
||||
"nature" => ["", 0],
|
||||
];
|
||||
}
|
||||
|
@ -1,70 +1,42 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\_scalar;
|
||||
namespace nulib\schema\_scalar;
|
||||
|
||||
use nulib\php\func;
|
||||
use nulib\ref\schema\ref_analyze;
|
||||
use nulib\ValueException;
|
||||
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;
|
||||
use nulib\schema\Schema;
|
||||
use nulib\schema\types;
|
||||
use nulib\schema\types\IType;
|
||||
use nulib\schema\Wrapper;
|
||||
use nulib\schema\WrapperContext;
|
||||
|
||||
/**
|
||||
* Class ScalarWrapper
|
||||
*
|
||||
* @method ScalarWrapper reset(&$value, $valueKey=null, ?array $params=null)
|
||||
* @method ScalarResult getResult($key=false)
|
||||
* @method self set($value, ?array $params=null, $key=false)
|
||||
* @method self unset(?array $params=null, $key=false)
|
||||
*/
|
||||
class ScalarWrapper extends Wrapper {
|
||||
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;
|
||||
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);
|
||||
}
|
||||
$this->verifix = $verifix;
|
||||
$this->throw = $throw ?? false;
|
||||
$this->schema = $schema;
|
||||
$this->result = new ScalarResult();
|
||||
$this->reset($value, $valueKey);
|
||||
$this->throw = $throw ?? true;
|
||||
}
|
||||
|
||||
function isScalar(?ScalarWrapper &$wrapper=null): bool { $wrapper = $this; return true; }
|
||||
|
||||
protected 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;
|
||||
}
|
||||
protected WrapperContext $context;
|
||||
|
||||
function getKeys(): array {
|
||||
return [null];
|
||||
return ScalarSchema::KEYS;
|
||||
}
|
||||
|
||||
/** @param string|int|null $key */
|
||||
@ -74,7 +46,7 @@ class ScalarWrapper extends Wrapper {
|
||||
}
|
||||
|
||||
/** analyser la valeur et résoudre son type */
|
||||
protected function analyze0(WrapperContext $context): int {
|
||||
protected static function _analyze0(WrapperContext $context): int {
|
||||
/** @var ScalarSchema $schema */
|
||||
$schema = $context->schema;
|
||||
$input = $context->input;
|
||||
@ -112,7 +84,7 @@ class ScalarWrapper extends Wrapper {
|
||||
$args = $name;
|
||||
$name = $key;
|
||||
}
|
||||
$type = types::get($schema->nullable, $name, $args, $this->schema->getDefinition());
|
||||
$type = types::get($schema->nullable, $name, $args, $schema->getDefinition());
|
||||
if ($firstType === null) $firstType = $type;
|
||||
$types[] = $type;
|
||||
if ($type->isAvailable($input, $valueKey)) {
|
||||
@ -140,7 +112,7 @@ class ScalarWrapper extends Wrapper {
|
||||
$type = $firstType;
|
||||
}
|
||||
}
|
||||
$context->type = $this->type = $type;
|
||||
$context->type = $type;
|
||||
|
||||
if (!$type->isAvailable($input, $valueKey)) {
|
||||
if ($default !== null) {
|
||||
@ -165,25 +137,28 @@ class ScalarWrapper extends Wrapper {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
/**
|
||||
* @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;
|
||||
|
||||
/** @var func $analyzerFunc */
|
||||
$analyzerFunc = $schema->analyzerFunc;
|
||||
if ($analyzerFunc !== null) $what = $analyzerFunc->invoke([$context]);
|
||||
else $what = $this->analyze0($context);
|
||||
if ($analyzerFunc !== null) $what = $analyzerFunc->invoke([$context, $wrapper]);
|
||||
else $what = self::_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]);
|
||||
if ($extractorFunc !== null) $extracted = $extractorFunc->invoke([$value, $context, $wrapper]);
|
||||
else $extracted = $context->type->extract($value);
|
||||
$context->value = $extracted;
|
||||
} catch (ValueException $e) {
|
||||
@ -194,7 +169,7 @@ class ScalarWrapper extends Wrapper {
|
||||
try {
|
||||
/** @var func $parserFunc */
|
||||
$parserFunc = $schema->parserFunc;
|
||||
if ($parserFunc !== null) $parsed = $parserFunc->invoke([$extracted, $context]);
|
||||
if ($parserFunc !== null) $parsed = $parserFunc->invoke([$extracted, $context, $wrapper]);
|
||||
else $parsed = $context->type->parse($extracted);
|
||||
$context->value = $parsed;
|
||||
} catch (ValueException $e) {
|
||||
@ -211,107 +186,53 @@ class ScalarWrapper extends Wrapper {
|
||||
}
|
||||
}
|
||||
|
||||
function verifix(?bool $throw=null): bool {
|
||||
$result = $this->result;
|
||||
$valueKey = $this->valueKey;
|
||||
$verifix = false;
|
||||
/**
|
||||
* @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;
|
||||
$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
|
||||
$this->input->set(null, $valueKey);
|
||||
$input->set(null, $valueKey);
|
||||
} elseif ($result->valid && !$result->normalized) {
|
||||
$normalizedValue = $result->normalizedValue;
|
||||
if ($normalizedValue !== null) {
|
||||
# la valeur normalisée est disponible
|
||||
$this->input->set($normalizedValue);
|
||||
$input->set($normalizedValue, $valueKey);
|
||||
$result->normalizedValue = null;
|
||||
$modified = true;
|
||||
} else {
|
||||
# normaliser la valeur
|
||||
$verifix = true;
|
||||
$normalize = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$verifix = true;
|
||||
$normalize = true;
|
||||
}
|
||||
|
||||
if ($verifix) {
|
||||
$value = $this->input->get($valueKey);
|
||||
$schema = $this->schema;
|
||||
if ($normalize) {
|
||||
$value = $input->get($valueKey);
|
||||
/** @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]);
|
||||
$value = $normalizerFunc->invoke([$orig, $context, $wrapper]);
|
||||
$modified = $value !== $orig;
|
||||
} else {
|
||||
$modified = $this->type->verifix($value, $result, $this->schema);
|
||||
$modified = $context->type->normalize($value, $result, $schema);
|
||||
}
|
||||
if ($result->valid) $this->input->set($value, $valueKey);
|
||||
if ($result->valid) $input->set($value, $valueKey);
|
||||
}
|
||||
if (!$result->valid) $result->throw($throw ?? $this->throw);
|
||||
return $modified;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,11 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\input;
|
||||
namespace nulib\schema\input;
|
||||
|
||||
#XXX implémenter le renommage de paramètres et faire des méthodes pour
|
||||
# construire des querystring et paramètres de formulaires
|
||||
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;
|
||||
use nulib\php\access\FormAccess;
|
||||
use nulib\php\access\IAccess;
|
||||
use nulib\php\access\ShadowAccess;
|
||||
|
||||
/**
|
||||
* Class FormInput: accès à des paramètres de formulaire (POST ou GET, dans cet
|
||||
@ -18,15 +17,14 @@ use nur\sery\wip\php\access\ShadowAccess;
|
||||
class FormInput extends Input {
|
||||
const ALLOW_EMPTY = false;
|
||||
|
||||
protected function formAccess($key): IAccess {
|
||||
return new FormAccess($key, [
|
||||
"allow_empty" => $this->allowEmpty,
|
||||
]);
|
||||
function __construct(&$dest=null, ?array $params=null) {
|
||||
parent::__construct($dest, $params);
|
||||
$this->access = new ShadowAccess($this->formAccess($this->access), $this->access);
|
||||
}
|
||||
|
||||
protected function access($key): IAccess {
|
||||
return $this->keyAccess[$key] ??= new ShadowAccess($this->formAccess($key), new KeyAccess($this->value, $key, [
|
||||
"allow_empty" => $this->allowEmpty,
|
||||
]));
|
||||
protected function formAccess(IAccess $access): IAccess {
|
||||
return new FormAccess(null, [
|
||||
"allow_empty" => $access->isAllowEmpty(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\input;
|
||||
namespace nulib\schema\input;
|
||||
|
||||
use nur\sery\wip\php\access\GetAccess;
|
||||
use nur\sery\wip\php\access\IAccess;
|
||||
use nulib\php\access\GetAccess;
|
||||
use nulib\php\access\IAccess;
|
||||
|
||||
/**
|
||||
* Class GetInput: accès à des paramètres de formulaire de type GET uniquement
|
||||
@ -11,9 +11,9 @@ use nur\sery\wip\php\access\IAccess;
|
||||
* une référence
|
||||
*/
|
||||
class GetInput extends FormInput {
|
||||
protected function formAccess($key): IAccess {
|
||||
return new GetAccess($key, [
|
||||
"allow_empty" => $this->allowEmpty,
|
||||
protected function formAccess(IAccess $access): IAccess {
|
||||
return new GetAccess(null, [
|
||||
"allow_empty" => $access->isAllowEmpty(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\input;
|
||||
namespace nulib\schema\input;
|
||||
|
||||
use nur\sery\wip\php\access\IAccess;
|
||||
use nur\sery\wip\php\access\KeyAccess;
|
||||
use nur\sery\wip\php\access\ValueAccess;
|
||||
use nulib\ref\schema\ref_input;
|
||||
use nulib\StateException;
|
||||
use nulib\php\access\IAccess;
|
||||
use nulib\php\access\KeyAccess;
|
||||
use nulib\php\access\PropertyAccess;
|
||||
|
||||
/**
|
||||
* Class Input: accès à une valeur
|
||||
@ -13,54 +15,72 @@ use nur\sery\wip\php\access\ValueAccess;
|
||||
class Input {
|
||||
const ALLOW_EMPTY = true;
|
||||
|
||||
function __construct(&$value=null, ?array $params=null) {
|
||||
$this->value =& $value;
|
||||
$this->allowEmpty = $params["allow_empty"] ?? static::ALLOW_EMPTY;
|
||||
private static function unexpected_access_type(): StateException {
|
||||
return StateException::unexpected_state("access_type");
|
||||
}
|
||||
|
||||
/** @var mixed */
|
||||
protected $value;
|
||||
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 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, [
|
||||
$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,
|
||||
"allow_null" => true,
|
||||
"allow_empty" => $this->allowEmpty,
|
||||
]);
|
||||
} else {
|
||||
return $this->keyAccess[$key] ??= new KeyAccess($this->value, $key, [
|
||||
"allow_empty" => $this->allowEmpty,
|
||||
]);
|
||||
throw self::unexpected_access_type();
|
||||
}
|
||||
}
|
||||
|
||||
protected IAccess $access;
|
||||
|
||||
/** tester si la valeur existe sans tenir compte de $allowEmpty */
|
||||
function isPresent($key=null): bool {
|
||||
return $this->access($key)->exists();
|
||||
return $this->access->resetKey($key)->exists();
|
||||
}
|
||||
|
||||
/** tester si la valeur est disponible en tenant compte de $allowEmpty */
|
||||
function isAvailable($key=null): bool {
|
||||
return $this->access($key)->available();
|
||||
return $this->access->resetKey($key)->available();
|
||||
}
|
||||
|
||||
function get($key=null) {
|
||||
return $this->access($key)->get();
|
||||
return $this->access->resetKey($key)->get();
|
||||
}
|
||||
|
||||
function set($value, $key=null): void {
|
||||
$this->access($key)->set($value);
|
||||
$this->access->resetKey($key)->set($value);
|
||||
}
|
||||
|
||||
function unset($key=null): void {
|
||||
$this->access($key)->del();
|
||||
$this->access->resetKey($key)->del();
|
||||
}
|
||||
|
||||
function addKey($key): Input {
|
||||
if ($key === null) return $this;
|
||||
$input = clone $this;
|
||||
$input->access = $this->access->addKey($key);
|
||||
return $input;
|
||||
}
|
||||
|
||||
function ensureAssoc(array $keys, ?array $params=null): void {
|
||||
$this->access->ensureAssoc($keys, $params);
|
||||
}
|
||||
|
||||
function ensureKeys(array $defaults, ?array $params=null): void {
|
||||
$this->access->ensureKeys($defaults, $params);
|
||||
}
|
||||
|
||||
function ensureOrder(array $keys, ?array $params=null): void {
|
||||
$this->access->ensureOrder($keys, $params);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\input;
|
||||
namespace nulib\schema\input;
|
||||
|
||||
use nur\sery\wip\php\access\IAccess;
|
||||
use nur\sery\wip\php\access\PostAccess;
|
||||
use nulib\php\access\IAccess;
|
||||
use nulib\php\access\PostAccess;
|
||||
|
||||
/**
|
||||
* Class PostInput: accès à des paramètres de formulaire de type POST uniquement
|
||||
@ -11,9 +11,9 @@ use nur\sery\wip\php\access\PostAccess;
|
||||
* une référence
|
||||
*/
|
||||
class PostInput extends FormInput {
|
||||
protected function formAccess($key): IAccess {
|
||||
return new PostAccess($key, [
|
||||
"allow_empty" => $this->allowEmpty,
|
||||
protected function formAccess(IAccess $access): IAccess {
|
||||
return new PostAccess(null, [
|
||||
"allow_empty" => $access->isAllowEmpty(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,22 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema;
|
||||
namespace nulib\schema;
|
||||
|
||||
use nulib\ValueException;
|
||||
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;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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): tcallable { return self::get($nullable, "callable"); }
|
||||
static function callable(bool $nullable=true): tfunc { return self::get($nullable, "callable"); }
|
||||
static function raw(bool $nullable=true): traw { return self::get($nullable, "raw"); }
|
||||
static function mixed(bool $nullable=true): tmixed { return self::get($nullable, "mixed"); }
|
||||
static function key(bool $nullable=true): tkey { return self::get($nullable, "key"); }
|
||||
|
@ -1,10 +1,10 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
use nulib\ValueException;
|
||||
use nur\sery\wip\schema\input\Input;
|
||||
use nur\sery\wip\schema\Result;
|
||||
use nur\sery\wip\schema\Schema;
|
||||
use nulib\schema\input\Input;
|
||||
use nulib\schema\Result;
|
||||
use nulib\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 verifix()}
|
||||
* par {@link format()} et le type retourné par {@link normalize()}
|
||||
*
|
||||
* Les valeurs "mixed", "bool", "float", "int", "string" et "array" peuvent
|
||||
* aussi être retournées, bien qu'elles ne soient pas à proprement parler des
|
||||
@ -47,6 +47,9 @@ interface IType {
|
||||
*/
|
||||
function getPhpType(bool $allowNullable=true): ?string;
|
||||
|
||||
/** 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"
|
||||
@ -98,15 +101,18 @@ interface IType {
|
||||
function parse(string $value);
|
||||
|
||||
/**
|
||||
* analyser, corriger éventuellement et normaliser la valeur
|
||||
*
|
||||
* NB: si $value est un string. elle doit avoir déjà été traitée au préalable
|
||||
* 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
|
||||
* par extract() et parse()
|
||||
*
|
||||
* si la valeur était déjà normalisée, ou si une erreur s'est produite,
|
||||
* retourner false.
|
||||
* - 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é
|
||||
*/
|
||||
function verifix(&$value, Result $result, Schema $schema): bool;
|
||||
function normalize(&$value, Result $result, Schema $schema): bool;
|
||||
|
||||
/**
|
||||
* formatter la valeur pour affichage. si $value n'est pas null, elle est
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
use nulib\cl;
|
||||
use nulib\php\func;
|
||||
@ -12,10 +12,9 @@ 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,
|
||||
"callable" => tcallable::class,
|
||||
"func" => tfunc::class, "function" => tfunc::class, "callable" => tfunc::class,
|
||||
# types spéciaux
|
||||
"raw" => traw::class,
|
||||
"mixed" => tmixed::class,
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
abstract class _tformatable extends _tsimple {
|
||||
const FORMAT = null;
|
||||
|
@ -1,9 +1,9 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
use nulib\StateException;
|
||||
use nur\prop;
|
||||
use nur\sery\wip\schema\input\Input;
|
||||
use nulib\schema\input\Input;
|
||||
use nur\str;
|
||||
|
||||
abstract class _tsimple implements IType {
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
use nulib\str;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
abstract class _tunion extends _tsimple {
|
||||
function getPhpType(bool $allowNullable=true): ?string {
|
||||
|
@ -1,12 +1,12 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
use nulib\cl;
|
||||
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;
|
||||
use nulib\schema\_scalar\ScalarResult;
|
||||
use nulib\schema\_scalar\ScalarSchema;
|
||||
use nulib\schema\Result;
|
||||
use nulib\schema\Schema;
|
||||
|
||||
class tarray extends _tstring {
|
||||
const NAME = "array";
|
||||
@ -35,9 +35,13 @@ class tarray extends _tstring {
|
||||
return "array";
|
||||
}
|
||||
|
||||
function getNullValue() {
|
||||
return $this->nullable? null: [];
|
||||
}
|
||||
|
||||
function isValid($value, ?bool &$normalized=null): bool {
|
||||
$normalized = is_array($value);
|
||||
return is_scalar($value) || is_array($value);
|
||||
return $normalized || is_scalar($value);
|
||||
}
|
||||
|
||||
function parse(string $value) {
|
||||
@ -49,23 +53,14 @@ class tarray extends _tstring {
|
||||
* @var ScalarResult $result
|
||||
* @var ScalarSchema $schema
|
||||
*/
|
||||
function verifix(&$value, Result $result, Schema $schema): bool {
|
||||
if (is_array($value)) {
|
||||
function normalize(&$value, Result $result, Schema $schema): bool {
|
||||
if ($result->normalized) {
|
||||
} elseif (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;
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
use nulib\cl;
|
||||
use nulib\ValueException;
|
||||
use nur\prop;
|
||||
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;
|
||||
use nulib\schema\_scalar\ScalarResult;
|
||||
use nulib\schema\_scalar\ScalarSchema;
|
||||
use nulib\schema\input\Input;
|
||||
use nulib\schema\Result;
|
||||
use nulib\schema\Schema;
|
||||
|
||||
class tbool extends _tformatable {
|
||||
const NAME = "bool";
|
||||
@ -76,6 +76,10 @@ 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);
|
||||
}
|
||||
@ -99,23 +103,14 @@ class tbool extends _tformatable {
|
||||
* @var ScalarResult $result
|
||||
* @var ScalarSchema $schema
|
||||
*/
|
||||
function verifix(&$value, Result $result, Schema $schema): bool {
|
||||
if (is_bool($value)) {
|
||||
function normalize(&$value, Result $result, Schema $schema): bool {
|
||||
if ($result->normalized) {
|
||||
} elseif (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;
|
||||
}
|
||||
|
||||
|
@ -1,68 +0,0 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
|
||||
use Exception;
|
||||
use nulib\php\func;
|
||||
use nulib\ValueException;
|
||||
use nur\sery\wip\schema\_scalar\ScalarResult;
|
||||
use nur\sery\wip\schema\_scalar\ScalarSchema;
|
||||
use nur\sery\wip\schema\Result;
|
||||
use nur\sery\wip\schema\Schema;
|
||||
|
||||
class tcallable extends _tsimple {
|
||||
const NAME = "callable";
|
||||
|
||||
const ALIASES = ["func", "function"];
|
||||
|
||||
static function ensure_callable(&$callable): void {
|
||||
$callable = func::ensure($callable);
|
||||
}
|
||||
|
||||
static function ensure_ncallable(&$callable): void {
|
||||
if ($callable !== null) self::ensure_callable($callable);
|
||||
}
|
||||
|
||||
function getClass(): string {
|
||||
return func::class;
|
||||
}
|
||||
|
||||
function isValid($value, ?bool &$normalized=null): bool {
|
||||
$normalized = is_callable($value);
|
||||
return func::check($value);
|
||||
}
|
||||
|
||||
function parse(string $value) {
|
||||
try {
|
||||
return func::ensure($value);
|
||||
} catch (Exception $e) {
|
||||
throw new ValueException(null, null, 0, $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @var ScalarResult $result
|
||||
* @var ScalarSchema $schema
|
||||
*/
|
||||
function verifix(&$value, Result $result, Schema $schema): bool {
|
||||
if ($value instanceof func) {
|
||||
$result->setNormalized();
|
||||
return false;
|
||||
} elseif (is_callable($value)) {
|
||||
$value = func::with($value);
|
||||
$result->setNormalized();
|
||||
return true;
|
||||
} elseif (is_string($value)) {
|
||||
try {
|
||||
$value = $this->parse($value);
|
||||
$result->setValid();
|
||||
return true;
|
||||
} catch (ValueException $e) {
|
||||
}
|
||||
}
|
||||
$result->setInvalid($value, $schema);
|
||||
return false;
|
||||
}
|
||||
|
||||
function format($value, $format=null): string {
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
use nulib\php\content\c;
|
||||
use nur\sery\wip\schema\_scalar\ScalarResult;
|
||||
use nur\sery\wip\schema\_scalar\ScalarSchema;
|
||||
use nur\sery\wip\schema\Result;
|
||||
use nur\sery\wip\schema\Schema;
|
||||
use nulib\schema\_scalar\ScalarResult;
|
||||
use nulib\schema\_scalar\ScalarSchema;
|
||||
use nulib\schema\Result;
|
||||
use nulib\schema\Schema;
|
||||
|
||||
abstract class tcontent extends _tunion {
|
||||
const NAME = "content";
|
||||
@ -23,9 +23,13 @@ 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 is_scalar($value) || is_array($value);
|
||||
return $normalized || is_scalar($value);
|
||||
}
|
||||
|
||||
function parse(string $value) {
|
||||
@ -36,18 +40,15 @@ abstract class tcontent extends _tunion {
|
||||
* @var ScalarResult $result
|
||||
* @var ScalarSchema $schema
|
||||
*/
|
||||
function verifix(&$value, Result $result, Schema $schema): bool {
|
||||
if (is_string($value) || is_array($value)) {
|
||||
function normalize(&$value, Result $result, Schema $schema): bool {
|
||||
if ($result->normalized) {
|
||||
} elseif (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 {
|
||||
|
@ -1,11 +1,11 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
use nulib\ValueException;
|
||||
use nur\sery\wip\schema\_scalar\ScalarResult;
|
||||
use nur\sery\wip\schema\_scalar\ScalarSchema;
|
||||
use nur\sery\wip\schema\Result;
|
||||
use nur\sery\wip\schema\Schema;
|
||||
use nulib\schema\_scalar\ScalarResult;
|
||||
use nulib\schema\_scalar\ScalarSchema;
|
||||
use nulib\schema\Result;
|
||||
use nulib\schema\Schema;
|
||||
|
||||
class tfloat extends _tformatable {
|
||||
const NAME = "float";
|
||||
@ -24,6 +24,10 @@ 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);
|
||||
@ -43,23 +47,14 @@ class tfloat extends _tformatable {
|
||||
* @var ScalarResult $result
|
||||
* @var ScalarSchema $schema
|
||||
*/
|
||||
function verifix(&$value, Result $result, Schema $schema): bool {
|
||||
if (is_float($value)) {
|
||||
function normalize(&$value, Result $result, Schema $schema): bool {
|
||||
if ($result->normalized) {
|
||||
} elseif (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;
|
||||
}
|
||||
}
|
||||
|
63
src/schema/types/tfunc.php
Normal file
63
src/schema/types/tfunc.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
namespace nulib\schema\types;
|
||||
|
||||
use Exception;
|
||||
use nulib\php\func;
|
||||
use nulib\ValueException;
|
||||
use nulib\schema\_scalar\ScalarResult;
|
||||
use nulib\schema\_scalar\ScalarSchema;
|
||||
use nulib\schema\Result;
|
||||
use nulib\schema\Schema;
|
||||
|
||||
class tfunc extends _tsimple {
|
||||
const NAME = "func";
|
||||
|
||||
const ALIASES = ["function", "callable"];
|
||||
|
||||
static function ensure_func(&$func): void {
|
||||
$func = func::ensure($func);
|
||||
}
|
||||
|
||||
static function ensure_nfunc(&$func): void {
|
||||
if ($func !== null) self::ensure_func($func);
|
||||
}
|
||||
|
||||
function getClass(): string {
|
||||
return func::class;
|
||||
}
|
||||
|
||||
function getNullValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
function isValid($value, ?bool &$normalized=null): bool {
|
||||
$normalized = $value instanceof func;
|
||||
return func::check($value);
|
||||
}
|
||||
|
||||
function parse(string $value) {
|
||||
try {
|
||||
return func::ensure($value);
|
||||
} catch (Exception $e) {
|
||||
throw new ValueException(null, null, 0, $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @var ScalarResult $result
|
||||
* @var ScalarSchema $schema
|
||||
*/
|
||||
function normalize(&$value, Result $result, Schema $schema): bool {
|
||||
if ($result->normalized) {
|
||||
} elseif ($value instanceof func) {
|
||||
$result->setNormalized();
|
||||
} elseif (is_callable($value)) {
|
||||
$value = func::with($value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function format($value, $format=null): string {
|
||||
}
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
use nulib\ValueException;
|
||||
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;
|
||||
use nulib\schema\_scalar\ScalarResult;
|
||||
use nulib\schema\_scalar\ScalarSchema;
|
||||
use nulib\schema\input\Input;
|
||||
use nulib\schema\Result;
|
||||
use nulib\schema\Schema;
|
||||
|
||||
class tgeneric extends _tsimple {
|
||||
function __construct(string $class, bool $nullable, ?array $params=null) {
|
||||
@ -20,6 +20,10 @@ class tgeneric extends _tsimple {
|
||||
return $this->class;
|
||||
}
|
||||
|
||||
function getNullValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
function isAvailable(Input $input, $valueKey): bool {
|
||||
return $input->isAvailable($valueKey);
|
||||
}
|
||||
@ -29,8 +33,8 @@ class tgeneric extends _tsimple {
|
||||
}
|
||||
|
||||
function isValid($value, ?bool &$normalized=null): bool {
|
||||
$normalized = true;
|
||||
return $value instanceof $this->class;
|
||||
$normalized = $value instanceof $this->class;
|
||||
return $normalized;
|
||||
}
|
||||
|
||||
function parse(string $value) {
|
||||
@ -41,8 +45,8 @@ class tgeneric extends _tsimple {
|
||||
* @var ScalarResult $result
|
||||
* @var ScalarSchema $schema
|
||||
*/
|
||||
function verifix(&$value, Result $result, Schema $schema): bool {
|
||||
$result->setNormalized();
|
||||
function normalize(&$value, Result $result, Schema $schema): bool {
|
||||
if (!$result->normalized) $result->setNormalized();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
use nulib\ValueException;
|
||||
use nur\sery\wip\schema\_scalar\ScalarResult;
|
||||
use nur\sery\wip\schema\_scalar\ScalarSchema;
|
||||
use nur\sery\wip\schema\Result;
|
||||
use nur\sery\wip\schema\Schema;
|
||||
use nulib\schema\_scalar\ScalarResult;
|
||||
use nulib\schema\_scalar\ScalarSchema;
|
||||
use nulib\schema\Result;
|
||||
use nulib\schema\Schema;
|
||||
|
||||
class tint extends _tformatable {
|
||||
const NAME = "int";
|
||||
@ -26,6 +26,10 @@ 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);
|
||||
@ -45,23 +49,14 @@ class tint extends _tformatable {
|
||||
* @var ScalarResult $result
|
||||
* @var ScalarSchema $schema
|
||||
*/
|
||||
function verifix(&$value, Result $result, Schema $schema): bool {
|
||||
if (is_int($value)) {
|
||||
function normalize(&$value, Result $result, Schema $schema): bool {
|
||||
if ($result->normalized) {
|
||||
} elseif (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;
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
use nur\sery\wip\schema\_scalar\ScalarResult;
|
||||
use nur\sery\wip\schema\_scalar\ScalarSchema;
|
||||
use nur\sery\wip\schema\Result;
|
||||
use nur\sery\wip\schema\Schema;
|
||||
use nulib\schema\_scalar\ScalarResult;
|
||||
use nulib\schema\_scalar\ScalarSchema;
|
||||
use nulib\schema\Result;
|
||||
use nulib\schema\Schema;
|
||||
|
||||
class tkey extends _tunion {
|
||||
const NAME = "key";
|
||||
@ -23,9 +23,13 @@ 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 is_scalar($value);
|
||||
return $normalized || is_scalar($value);
|
||||
}
|
||||
|
||||
function parse(string $value) {
|
||||
@ -36,18 +40,15 @@ class tkey extends _tunion {
|
||||
* @var ScalarResult $result
|
||||
* @var ScalarSchema $schema
|
||||
*/
|
||||
function verifix(&$value, Result $result, Schema $schema): bool {
|
||||
if (is_string($value) || is_int($value)) {
|
||||
function normalize(&$value, Result $result, Schema $schema): bool {
|
||||
if ($result->normalized) {
|
||||
} elseif (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 {
|
||||
|
@ -1,11 +1,11 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
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;
|
||||
use nulib\schema\_scalar\ScalarResult;
|
||||
use nulib\schema\_scalar\ScalarSchema;
|
||||
use nulib\schema\input\Input;
|
||||
use nulib\schema\Result;
|
||||
use nulib\schema\Schema;
|
||||
|
||||
class tmixed extends _tsimple {
|
||||
const NAME = "mixed";
|
||||
@ -14,6 +14,10 @@ class tmixed extends _tsimple {
|
||||
return "mixed";
|
||||
}
|
||||
|
||||
function getNullValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
function isAvailable(Input $input, $valueKey): bool {
|
||||
return $input->isAvailable($valueKey);
|
||||
}
|
||||
@ -35,8 +39,8 @@ class tmixed extends _tsimple {
|
||||
* @var ScalarResult $result
|
||||
* @var ScalarSchema $schema
|
||||
*/
|
||||
function verifix(&$value, Result $result, Schema $schema): bool {
|
||||
$result->setNormalized();
|
||||
function normalize(&$value, Result $result, Schema $schema): bool {
|
||||
if (!$result->normalized) $result->setNormalized();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
use nur\sery\wip\schema\_scalar\ScalarResult;
|
||||
use nur\sery\wip\schema\_scalar\ScalarSchema;
|
||||
use nur\sery\wip\schema\Result;
|
||||
use nur\sery\wip\schema\Schema;
|
||||
use nulib\schema\_scalar\ScalarResult;
|
||||
use nulib\schema\_scalar\ScalarSchema;
|
||||
use nulib\schema\Result;
|
||||
use nulib\schema\Schema;
|
||||
|
||||
class tpkey extends _tunion {
|
||||
const NAME = "pkey";
|
||||
@ -28,9 +28,13 @@ 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 is_scalar($value) || is_array($value);
|
||||
return $normalized || is_scalar($value);
|
||||
}
|
||||
|
||||
function parse(string $value) {
|
||||
@ -41,18 +45,15 @@ class tpkey extends _tunion {
|
||||
* @var ScalarResult $result
|
||||
* @var ScalarSchema $schema
|
||||
*/
|
||||
function verifix(&$value, Result $result, Schema $schema): bool {
|
||||
if (is_string($value) || is_int($value) || is_array($value)) {
|
||||
function normalize(&$value, Result $result, Schema $schema): bool {
|
||||
if ($result->normalized) {
|
||||
} elseif (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 {
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
use nur\sery\wip\schema\input\Input;
|
||||
use nulib\schema\input\Input;
|
||||
|
||||
class traw extends tmixed {
|
||||
const NAME = "raw";
|
||||
|
@ -1,11 +1,11 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
use nulib\str;
|
||||
use nur\sery\wip\schema\_scalar\ScalarResult;
|
||||
use nur\sery\wip\schema\_scalar\ScalarSchema;
|
||||
use nur\sery\wip\schema\Result;
|
||||
use nur\sery\wip\schema\Schema;
|
||||
use nulib\schema\_scalar\ScalarResult;
|
||||
use nulib\schema\_scalar\ScalarSchema;
|
||||
use nulib\schema\Result;
|
||||
use nulib\schema\Schema;
|
||||
|
||||
class trawstring extends _tstring {
|
||||
const NAME = "rawstring";
|
||||
@ -24,6 +24,10 @@ class trawstring extends _tstring {
|
||||
return "string";
|
||||
}
|
||||
|
||||
function getNullValue() {
|
||||
return $this->nullable? null: "";
|
||||
}
|
||||
|
||||
function isNull($value): bool {
|
||||
return $value === null;
|
||||
}
|
||||
@ -44,18 +48,15 @@ class trawstring extends _tstring {
|
||||
* @var ScalarResult $result
|
||||
* @var ScalarSchema $schema
|
||||
*/
|
||||
function verifix(&$value, Result $result, Schema $schema): bool {
|
||||
if (is_string($value)) {
|
||||
function normalize(&$value, Result $result, Schema $schema): bool {
|
||||
if ($result->normalized) {
|
||||
} elseif (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 {
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
class tstring extends trawstring {
|
||||
const NAME = "string";
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
class ttext extends trawstring {
|
||||
const NAME = "text";
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\web\content;
|
||||
namespace nulib\web\content;
|
||||
|
||||
|
||||
use nulib\A;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\web\content;
|
||||
namespace nulib\web\content;
|
||||
|
||||
/**
|
||||
* Class v: classe outil pour gérer du contenu pour le web
|
||||
|
@ -1,5 +0,0 @@
|
||||
<?php
|
||||
namespace nulib;
|
||||
|
||||
class app extends \nur\sery\app {
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
<?php
|
||||
namespace nulib\app\cli;
|
||||
|
||||
abstract class Application extends \nur\sery\app\cli\Application {
|
||||
}
|
132
tests/appTest.php
Normal file
132
tests/appTest.php
Normal file
@ -0,0 +1,132 @@
|
||||
<?php
|
||||
namespace nulib {
|
||||
use nulib\tests\TestCase;
|
||||
use nulib\impl\config;
|
||||
use nulib\impl\myapp;
|
||||
use nulib\impl\MyApplication1;
|
||||
use nulib\impl\MyApplication2;
|
||||
|
||||
class appTest extends TestCase {
|
||||
function testWith() {
|
||||
$projdir = config::get_projdir();
|
||||
$cwd = getcwd();
|
||||
|
||||
myapp::reset();
|
||||
$app1 = myapp::with(MyApplication1::class);
|
||||
self::assertSame([
|
||||
"projdir" => $projdir,
|
||||
"vendor" => [
|
||||
"bindir" => "$projdir/vendor/bin",
|
||||
"autoload" => "$projdir/vendor/autoload.php",
|
||||
],
|
||||
"appcode" => "nur-sery",
|
||||
"cwd" => $cwd,
|
||||
"datadir" => "$projdir/devel",
|
||||
"etcdir" => "$projdir/devel/etc",
|
||||
"vardir" => "$projdir/devel/var",
|
||||
"logdir" => "$projdir/devel/log",
|
||||
"profile" => "devel",
|
||||
"appgroup" => null,
|
||||
"name" => "my-application1",
|
||||
"title" => null,
|
||||
], $app1->getParams());
|
||||
|
||||
$app2 = myapp::with(MyApplication2::class, $app1);
|
||||
self::assertSame([
|
||||
"projdir" => $projdir,
|
||||
"vendor" => [
|
||||
"bindir" => "$projdir/vendor/bin",
|
||||
"autoload" => "$projdir/vendor/autoload.php",
|
||||
],
|
||||
"appcode" => "nur-sery",
|
||||
"cwd" => $cwd,
|
||||
"datadir" => "$projdir/devel",
|
||||
"etcdir" => "$projdir/devel/etc",
|
||||
"vardir" => "$projdir/devel/var",
|
||||
"logdir" => "$projdir/devel/log",
|
||||
"profile" => "devel",
|
||||
"appgroup" => null,
|
||||
"name" => "my-application2",
|
||||
"title" => null,
|
||||
], $app2->getParams());
|
||||
}
|
||||
|
||||
function testInit() {
|
||||
$projdir = config::get_projdir();
|
||||
$cwd = getcwd();
|
||||
|
||||
myapp::reset();
|
||||
myapp::init(MyApplication1::class);
|
||||
self::assertSame([
|
||||
"projdir" => $projdir,
|
||||
"vendor" => [
|
||||
"bindir" => "$projdir/vendor/bin",
|
||||
"autoload" => "$projdir/vendor/autoload.php",
|
||||
],
|
||||
"appcode" => "nur-sery",
|
||||
"cwd" => $cwd,
|
||||
"datadir" => "$projdir/devel",
|
||||
"etcdir" => "$projdir/devel/etc",
|
||||
"vardir" => "$projdir/devel/var",
|
||||
"logdir" => "$projdir/devel/log",
|
||||
"profile" => "devel",
|
||||
"appgroup" => null,
|
||||
"name" => "my-application1",
|
||||
"title" => null,
|
||||
], myapp::get()->getParams());
|
||||
|
||||
myapp::init(MyApplication2::class);
|
||||
self::assertSame([
|
||||
"projdir" => $projdir,
|
||||
"vendor" => [
|
||||
"bindir" => "$projdir/vendor/bin",
|
||||
"autoload" => "$projdir/vendor/autoload.php",
|
||||
],
|
||||
"appcode" => "nur-sery",
|
||||
"cwd" => $cwd,
|
||||
"datadir" => "$projdir/devel",
|
||||
"etcdir" => "$projdir/devel/etc",
|
||||
"vardir" => "$projdir/devel/var",
|
||||
"logdir" => "$projdir/devel/log",
|
||||
"profile" => "devel",
|
||||
"appgroup" => null,
|
||||
"name" => "my-application2",
|
||||
"title" => null,
|
||||
], myapp::get()->getParams());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace nulib\impl {
|
||||
|
||||
use nulib\app\cli\Application;
|
||||
use nulib\os\path;
|
||||
use nulib\app;
|
||||
|
||||
class config {
|
||||
const PROJDIR = __DIR__.'/..';
|
||||
|
||||
static function get_projdir(): string {
|
||||
return path::abspath(self::PROJDIR);
|
||||
}
|
||||
}
|
||||
|
||||
class myapp extends app {
|
||||
static function reset(): void {
|
||||
self::$app = null;
|
||||
}
|
||||
}
|
||||
|
||||
class MyApplication1 extends Application {
|
||||
const PROJDIR = config::PROJDIR;
|
||||
|
||||
function main() {
|
||||
}
|
||||
}
|
||||
class MyApplication2 extends Application {
|
||||
const PROJDIR = null;
|
||||
|
||||
function main() {
|
||||
}
|
||||
}
|
||||
}
|
215
tests/php/access/KeyAccessTest.php
Normal file
215
tests/php/access/KeyAccessTest.php
Normal file
@ -0,0 +1,215 @@
|
||||
<?php
|
||||
namespace nulib\php\access;
|
||||
|
||||
use nulib\tests\TestCase;
|
||||
use stdClass;
|
||||
|
||||
class KeyAccessTest extends TestCase {
|
||||
function testValueAccess() {
|
||||
$default = new stdClass();
|
||||
|
||||
#
|
||||
$i = null;
|
||||
$a = new KeyAccess($i);
|
||||
self::assertFalse($a->exists());
|
||||
self::assertFalse($a->available());
|
||||
self::assertSame($default, $a->get($default));
|
||||
|
||||
$i = false;
|
||||
$a = new KeyAccess($i);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertTrue($a->available());
|
||||
self::assertSame(false, $a->get($default));
|
||||
|
||||
$i = "";
|
||||
$a = new KeyAccess($i);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertTrue($a->available());
|
||||
self::assertSame("", $a->get($default));
|
||||
|
||||
#
|
||||
$i = null;
|
||||
$a = new KeyAccess($i, null, ["allow_null" => false]);
|
||||
self::assertFalse($a->exists());
|
||||
self::assertFalse($a->available());
|
||||
self::assertSame($default, $a->get($default));
|
||||
|
||||
$i = null;
|
||||
$a = new KeyAccess($i, null, ["allow_null" => true]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertTrue($a->available());
|
||||
self::assertSame(null, $a->get($default));
|
||||
|
||||
#
|
||||
$i = false;
|
||||
$a = new KeyAccess($i, null, ["allow_false" => false]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertFalse($a->available());
|
||||
self::assertSame($default, $a->get($default));
|
||||
|
||||
$i = false;
|
||||
$a = new KeyAccess($i, null, ["allow_false" => true]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertTrue($a->available());
|
||||
self::assertSame(false, $a->get($default));
|
||||
|
||||
#
|
||||
$i = "";
|
||||
$a = new KeyAccess($i, null, ["allow_empty" => false]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertFalse($a->available());
|
||||
self::assertSame($default, $a->get($default));
|
||||
|
||||
$i = "";
|
||||
$a = new KeyAccess($i, null, ["allow_empty" => true]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertTrue($a->available());
|
||||
self::assertSame("", $a->get($default));
|
||||
}
|
||||
|
||||
function testArrayAccess() {
|
||||
$default = new stdClass();
|
||||
$array = ["null" => null, "false" => false, "empty" => ""];
|
||||
|
||||
#
|
||||
$a = new KeyAccess($array, "inexistant");
|
||||
self::assertFalse($a->exists());
|
||||
self::assertFalse($a->available());
|
||||
self::assertSame($default, $a->get($default));
|
||||
|
||||
$a = new KeyAccess($array, "null");
|
||||
self::assertTrue($a->exists());
|
||||
self::assertTrue($a->available());
|
||||
self::assertSame(null, $a->get($default));
|
||||
|
||||
$a = new KeyAccess($array, "false");
|
||||
self::assertTrue($a->exists());
|
||||
self::assertFalse($a->available());
|
||||
self::assertSame($default, $a->get($default));
|
||||
|
||||
$a = new KeyAccess($array, "empty");
|
||||
self::assertTrue($a->exists());
|
||||
self::assertTrue($a->available());
|
||||
self::assertSame("", $a->get($default));
|
||||
|
||||
#
|
||||
$a = new KeyAccess($array, "null", ["allow_null" => false]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertFalse($a->available());
|
||||
self::assertSame($default, $a->get($default));
|
||||
|
||||
$a = new KeyAccess($array, "null", ["allow_null" => true]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertTrue($a->available());
|
||||
self::assertSame(null, $a->get($default));
|
||||
|
||||
#
|
||||
$a = new KeyAccess($array, "false", ["allow_false" => false]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertFalse($a->available());
|
||||
self::assertSame($default, $a->get($default));
|
||||
|
||||
$a = new KeyAccess($array, "false", ["allow_false" => true]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertTrue($a->available());
|
||||
self::assertSame(false, $a->get($default));
|
||||
|
||||
#
|
||||
$a = new KeyAccess($array, "empty", ["allow_empty" => false]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertFalse($a->available());
|
||||
self::assertSame($default, $a->get($default));
|
||||
|
||||
$a = new KeyAccess($array, "empty", ["allow_empty" => true]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertTrue($a->available());
|
||||
self::assertSame("", $a->get($default));
|
||||
}
|
||||
|
||||
private function _ensureAssoc(?array $orig, ?array $expected, array $keys, ?array $params=null) {
|
||||
$v = $orig; $a = new KeyAccess($v);
|
||||
$a->ensureAssoc($keys, $params);
|
||||
self::assertSame($expected, $v);
|
||||
}
|
||||
function testEnsureAssoc() {
|
||||
$keys = ["a", "b", "c"];
|
||||
|
||||
$this->_ensureAssoc(null, null, $keys);
|
||||
$this->_ensureAssoc([], [], $keys);
|
||||
$this->_ensureAssoc([1], ["a" => 1], $keys);
|
||||
$this->_ensureAssoc([1, 2, 3], ["a" => 1, "b" => 2, "c" => 3], $keys);
|
||||
$this->_ensureAssoc([1, 2, 3, 4], [3 => 4, "a" => 1, "b" => 2, "c" => 3], $keys);
|
||||
$this->_ensureAssoc(["c" => 3, 1], ["c" => 3, "a" => 1], $keys);
|
||||
$this->_ensureAssoc(["c" => 3, "b" => 2, 1], ["c" => 3, "b" => 2, "a" => 1], $keys);
|
||||
$this->_ensureAssoc(["c" => 3, "b" => 2, "a" => 1], ["c" => 3, "b" => 2, "a" => 1], $keys);
|
||||
$this->_ensureAssoc(["a" => 1, 2], ["a" => 1, "b" => 2], $keys);
|
||||
$this->_ensureAssoc([2, "a" => 1], ["a" => 1, "b" => 2], $keys);
|
||||
|
||||
$keys = [0, "a", "b"];
|
||||
$this->_ensureAssoc([1], [1], $keys);
|
||||
$this->_ensureAssoc([1, 2], [1, "a" => 2], $keys);
|
||||
}
|
||||
|
||||
private function _ensureKeys(?array $orig, ?array $expected, array $defaults, ?array $params=null) {
|
||||
$v = $orig; $a = new KeyAccess($v);
|
||||
$a->ensureKeys($defaults, $params);
|
||||
self::assertSame($expected, $v);
|
||||
}
|
||||
function testEnsureKeys() {
|
||||
$defaults = ["a" => false, "b" => false, "c" => false];
|
||||
|
||||
$this->_ensureKeys(null, ["a" => false, "b" => false, "c" => false], $defaults);
|
||||
$this->_ensureKeys([], ["a" => false, "b" => false, "c" => false], $defaults);
|
||||
$this->_ensureKeys(["a" => 1], ["a" => 1, "b" => false, "c" => false], $defaults);
|
||||
$this->_ensureKeys(["a" => 1, "b" => 2, "c" => 3], ["a" => 1, "b" => 2, "c" => 3], $defaults);
|
||||
$this->_ensureKeys(["x"], ["x", "a" => false, "b" => false, "c" => false], $defaults);
|
||||
$this->_ensureKeys(["x", "a" => 1], ["x", "a" => 1, "b" => false, "c" => false], $defaults);
|
||||
$this->_ensureKeys(["a" => 1, "x"], ["a" => 1, "x", "b" => false, "c" => false], $defaults);
|
||||
$this->_ensureKeys(["a" => 1, "b" => 2, "c" => 3, "x"], ["a" => 1, "b" => 2, "c" => 3, "x"], $defaults);
|
||||
}
|
||||
|
||||
private function _ensureOrder(?array $orig, ?array $expected, array $keys, ?array $params=null) {
|
||||
$v = $orig; $a = new KeyAccess($v);
|
||||
$a->ensureOrder($keys, $params);
|
||||
self::assertSame($expected, $v);
|
||||
}
|
||||
function testEnsureOrder() {
|
||||
$keys = ["a", "b", "c"];
|
||||
|
||||
$this->_ensureOrder(null, null, $keys);
|
||||
$this->_ensureOrder([], [], $keys);
|
||||
$this->_ensureOrder([1], [1], $keys);
|
||||
$this->_ensureOrder(["b" => 2, "a" => 1], ["a" => 1, "b" => 2], $keys);
|
||||
$this->_ensureOrder(["c" => 3, "a" => 1], ["a" => 1, "c" => 3], $keys);
|
||||
}
|
||||
|
||||
private function _ensureAssocKeysOrder(?array $orig, ?array $expected, array $defaults, ?array $params=null) {
|
||||
$v = $orig; $a = new KeyAccess($v);
|
||||
$keys = array_keys($defaults);
|
||||
$a->ensureAssoc($keys, $params);
|
||||
$a->ensureKeys($defaults, $params);
|
||||
$a->ensureOrder($keys, $params);
|
||||
self::assertSame($expected, $v);
|
||||
}
|
||||
function testEnsureAssocKeysOrder() {
|
||||
$defaults = ["a" => false, "b" => false, "c" => false];
|
||||
|
||||
$this->_ensureAssocKeysOrder(null, ["a" => false, "b" => false, "c" => false], $defaults);
|
||||
$this->_ensureAssocKeysOrder([], ["a" => false, "b" => false, "c" => false], $defaults);
|
||||
$this->_ensureAssocKeysOrder([1], ["a" => 1, "b" => false, "c" => false], $defaults);
|
||||
$this->_ensureAssocKeysOrder([1, 2, 3], ["a" => 1, "b" => 2, "c" => 3], $defaults);
|
||||
$this->_ensureAssocKeysOrder([1, 2, 3, 4], ["a" => 1, "b" => 2, "c" => 3, 4], $defaults);
|
||||
$this->_ensureAssocKeysOrder([1, 2, 3, 4], ["a" => 1, "b" => 2, "c" => 3, 3 => 4], $defaults, [
|
||||
"preserve_keys" => true,
|
||||
]);
|
||||
$this->_ensureAssocKeysOrder(["c" => 3, 1], ["a" => 1, "b" => false, "c" => 3], $defaults);
|
||||
$this->_ensureAssocKeysOrder(["c" => 3, "b" => 2, 1], ["a" => 1, "b" => 2, "c" => 3], $defaults);
|
||||
$this->_ensureAssocKeysOrder(["c" => 3, "b" => 2, "a" => 1], ["a" => 1, "b" => 2, "c" => 3], $defaults);
|
||||
$this->_ensureAssocKeysOrder(["a" => 1, 2], ["a" => 1, "b" => 2, "c" => false], $defaults);
|
||||
$this->_ensureAssocKeysOrder([2, "a" => 1], ["a" => 1, "b" => 2, "c" => false], $defaults);
|
||||
|
||||
$this->_ensureAssocKeysOrder([1], ["x_a" => 1, "x_b" => false, "x_c" => false], $defaults, [
|
||||
"key_prefix" => "x_",
|
||||
]);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\php\coll;
|
||||
namespace nulib\php\coll;
|
||||
|
||||
use Exception;
|
||||
use nulib\cl;
|
@ -1,9 +1,9 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\php\content;
|
||||
namespace nulib\php\content;
|
||||
|
||||
use nulib\php\content\c;
|
||||
use nur\sery\wip\php\content\impl\html;
|
||||
use nur\sery\wip\web\content\v;
|
||||
use nulib\php\content\impl\html;
|
||||
use nulib\web\content\v;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class cTest extends TestCase {
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\php\content\impl;
|
||||
namespace nulib\php\content\impl;
|
||||
|
||||
use nulib\php\content\IContent;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\php\content\impl;
|
||||
namespace nulib\php\content\impl;
|
||||
|
||||
use nulib\php\content\IPrintable;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\php\content\impl;
|
||||
namespace nulib\php\content\impl;
|
||||
|
||||
use nulib\php\content\c;
|
||||
use nulib\php\content\IContent;
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\php\content\impl;
|
||||
namespace nulib\php\content\impl;
|
||||
|
||||
class html {
|
||||
const H1 = [self::class, "h1"];
|
353
tests/schema/_assoc/AssocSchemaTest.php
Normal file
353
tests/schema/_assoc/AssocSchemaTest.php
Normal file
@ -0,0 +1,353 @@
|
||||
<?php
|
||||
namespace nulib\schema\_assoc;
|
||||
|
||||
use nulib\ext\yaml;
|
||||
use nulib\tests\TestCase;
|
||||
use nulib\ValueException;
|
||||
use nulib\schema\_scalar\ScalarSchemaTest;
|
||||
use nulib\schema\Schema;
|
||||
|
||||
class AssocSchemaTest extends TestCase {
|
||||
const NULL_SCHEMA = [
|
||||
"" => [
|
||||
"assoc",
|
||||
"compute_func" => null,
|
||||
"validate_func" => null,
|
||||
"ensure_array" => null,
|
||||
"ensure_assoc" => null,
|
||||
"ensure_keys" => null,
|
||||
"ensure_order" => null,
|
||||
],
|
||||
"schema" => null,
|
||||
"type" => [null],
|
||||
"default" => null,
|
||||
"title" => null,
|
||||
"required" => false,
|
||||
"nullable" => true,
|
||||
"desc" => null,
|
||||
"analyzer_func" => null,
|
||||
"extractor_func" => null,
|
||||
"parser_func" => null,
|
||||
"normalizer_func" => null,
|
||||
"messages" => null,
|
||||
"formatter_func" => null,
|
||||
"format" => null,
|
||||
"name" => null,
|
||||
"pkey" => null,
|
||||
"header" => null,
|
||||
"computed" => null,
|
||||
];
|
||||
|
||||
static function schema(array $definition, array $keyDefinitions): array {
|
||||
$definition = array_merge(self::NULL_SCHEMA, $definition, ["schema" => []]);
|
||||
foreach ($keyDefinitions as $key => $keydef) {
|
||||
$definition["schema"][$key] = array_merge(ScalarSchemaTest::NULL_SCHEMA, $keydef);
|
||||
}; unset($subdef);
|
||||
return $definition;
|
||||
}
|
||||
|
||||
function testNormalize() {
|
||||
self::assertSame(self::schema([
|
||||
"type" => ["array"], "nullable" => true,
|
||||
], [
|
||||
"a" => [
|
||||
"type" => ["string"], "nullable" => false,
|
||||
"name" => "a", "pkey" => "a", "header" => "a",
|
||||
],
|
||||
]), AssocSchema::normalize_definition(["a" => "string"]));
|
||||
|
||||
self::assertSame(self::schema([
|
||||
"type" => ["array"], "nullable" => true,
|
||||
], [
|
||||
"a" => [
|
||||
"type" => ["string"], "nullable" => false,
|
||||
"name" => "a", "pkey" => "a", "header" => "a",
|
||||
],
|
||||
"b" => [
|
||||
"type" => ["int"], "nullable" => false,
|
||||
"name" => "b", "pkey" => "b", "header" => "b",
|
||||
],
|
||||
"c" => [
|
||||
"type" => ["bool"], "nullable" => false,
|
||||
"name" => "c", "pkey" => "c", "header" => "c",
|
||||
],
|
||||
]), AssocSchema::normalize_definition([
|
||||
"a" => "string",
|
||||
"b" => "int",
|
||||
"c" => "bool",
|
||||
]));
|
||||
}
|
||||
|
||||
function testConstructor() {
|
||||
$schema = new AssocSchema([
|
||||
"a" => "string",
|
||||
"b" => "int",
|
||||
"c" => "bool",
|
||||
]);
|
||||
self::assertSame(self::schema([
|
||||
"type" => ["array"], "nullable" => true,
|
||||
], [
|
||||
"a" => [
|
||||
"type" => ["string"], "nullable" => false,
|
||||
"name" => "a", "pkey" => "a", "header" => "a",
|
||||
],
|
||||
"b" => [
|
||||
"type" => ["int"], "nullable" => false,
|
||||
"name" => "b", "pkey" => "b", "header" => "b",
|
||||
],
|
||||
"c" => [
|
||||
"type" => ["bool"], "nullable" => false,
|
||||
"name" => "c", "pkey" => "c", "header" => "c",
|
||||
],
|
||||
]), $schema->getDefinition());
|
||||
//yaml::dump($schema->getDefinition());
|
||||
}
|
||||
|
||||
function testWrapper() {
|
||||
$schema = new AssocSchema([
|
||||
"a" => "?string",
|
||||
"b" => "?int",
|
||||
"c" => "?bool",
|
||||
]);
|
||||
$array = ["a" => " string ", "b" => " 42 ", "c" => false];
|
||||
$schema->getWrapper($array);
|
||||
self::assertSame([
|
||||
"a" => "string",
|
||||
"b" => 42,
|
||||
"c" => false,
|
||||
], $array);
|
||||
|
||||
###########################################################################
|
||||
$schema = new AssocSchema([
|
||||
"a" => "string",
|
||||
"b" => "int",
|
||||
"c" => "bool",
|
||||
]);
|
||||
|
||||
$array = ["a" => " string "];
|
||||
$schema->getWrapper($array);
|
||||
self::assertSame([
|
||||
"a" => "string",
|
||||
"b" => 0,
|
||||
"c" => false,
|
||||
], $array);
|
||||
|
||||
$array = ["c" => false, "a" => " string "];
|
||||
$schema->getWrapper($array);
|
||||
self::assertSame([
|
||||
"a" => "string",
|
||||
"b" => 0,
|
||||
"c" => false,
|
||||
], $array);
|
||||
|
||||
$array = ["a" => " string "];
|
||||
$schema->getWrapper($array, null, ["ensure_order" => false]);
|
||||
self::assertSame([
|
||||
"a" => "string",
|
||||
"b" => 0,
|
||||
"c" => false,
|
||||
], $array);
|
||||
|
||||
$array = ["c" => false, "a" => " string "];
|
||||
$schema->getWrapper($array, null, ["ensure_order" => false]);
|
||||
self::assertSame([
|
||||
"c" => false,
|
||||
"a" => "string",
|
||||
"b" => 0,
|
||||
], $array);
|
||||
|
||||
$array = ["a" => " string "];
|
||||
$schema->getWrapper($array, null, ["ensure_keys" => false]);
|
||||
self::assertSame([
|
||||
"a" => "string",
|
||||
], $array);
|
||||
|
||||
$array = ["c" => false, "a" => " string "];
|
||||
$schema->getWrapper($array, null, ["ensure_keys" => false]);
|
||||
self::assertSame([
|
||||
"a" => "string",
|
||||
"c" => false,
|
||||
], $array);
|
||||
}
|
||||
|
||||
const STRING_SCHEMA = [
|
||||
"s" => "string",
|
||||
"f" => "string",
|
||||
"m" => "string",
|
||||
];
|
||||
|
||||
const NSTRING_SCHEMA = [
|
||||
"s" => "?string",
|
||||
"f" => "?string",
|
||||
"m" => "?string",
|
||||
];
|
||||
|
||||
const RSTRING_SCHEMA = [
|
||||
"s" => ["string", "required" => true],
|
||||
"f" => ["string", "required" => true],
|
||||
"m" => ["string", "required" => true],
|
||||
];
|
||||
|
||||
const RNSTRING_SCHEMA = [
|
||||
"s" => ["?string", "required" => true],
|
||||
"f" => ["?string", "required" => true],
|
||||
"m" => ["?string", "required" => true],
|
||||
];
|
||||
|
||||
const STRINGS = ["s" => "string", "f" => false];
|
||||
const NSTRINGS = ["s" => null, "f" => null];
|
||||
|
||||
function testString() {
|
||||
/** @var AssocSchema $schema */
|
||||
$schema = Schema::ns(self::STRING_SCHEMA);
|
||||
|
||||
$array = self::STRINGS;
|
||||
$wrapper = $schema->getWrapper($array, null, ["throw" => false]);
|
||||
self::assertSame(["s" => "string", "f" => false, "m" => ""], $array);
|
||||
$result = $wrapper->getResult("s");
|
||||
self::assertTrue($result->normalized);
|
||||
$result = $wrapper->getResult("f");
|
||||
self::assertTrue($result->present);
|
||||
self::assertFalse($result->available);
|
||||
$result = $wrapper->getResult("m");
|
||||
self::assertFalse($result->present);
|
||||
|
||||
self::assertNotException(function() use ($schema) {
|
||||
$array = self::STRINGS;
|
||||
$schema->getWrapper($array);
|
||||
});
|
||||
|
||||
$array = self::NSTRINGS;
|
||||
$wrapper = $schema->getWrapper($array, null, ["throw" => false]);
|
||||
self::assertSame(["s" => null, "f" => null, "m" => ""], $array);
|
||||
$result = $wrapper->getResult("s");
|
||||
self::assertFalse($result->valid);
|
||||
self::assertSame("null", $result->messageKey);
|
||||
$result = $wrapper->getResult("f");
|
||||
self::assertFalse($result->valid);
|
||||
self::assertSame("null", $result->messageKey);
|
||||
$result = $wrapper->getResult("m");
|
||||
self::assertFalse($result->present);
|
||||
|
||||
self::assertException(ValueException::class, function() use ($schema) {
|
||||
$array = self::NSTRINGS;
|
||||
$schema->getWrapper($array);
|
||||
});
|
||||
}
|
||||
|
||||
function testNstring() {
|
||||
/** @var AssocSchema $schema */
|
||||
$schema = Schema::ns(self::NSTRING_SCHEMA);
|
||||
|
||||
$array = self::STRINGS;
|
||||
$wrapper = $schema->getWrapper($array, null, ["throw" => false]);
|
||||
self::assertSame(["s" => "string", "f" => false, "m" => null], $array);
|
||||
$result = $wrapper->getResult("s");
|
||||
self::assertTrue($result->normalized);
|
||||
$result = $wrapper->getResult("f");
|
||||
self::assertTrue($result->present);
|
||||
self::assertFalse($result->available);
|
||||
$result = $wrapper->getResult("m");
|
||||
self::assertFalse($result->present);
|
||||
|
||||
self::assertNotException(function() use ($schema) {
|
||||
$array = self::STRINGS;
|
||||
$schema->getWrapper($array);
|
||||
});
|
||||
|
||||
$array = self::NSTRINGS;
|
||||
$wrapper = $schema->getWrapper($array, null, ["throw" => false]);
|
||||
self::assertSame(["s" => null, "f" => null, "m" => null], $array);
|
||||
$result = $wrapper->getResult("s");
|
||||
self::assertTrue($result->normalized);
|
||||
$result = $wrapper->getResult("f");
|
||||
self::assertTrue($result->normalized);
|
||||
$result = $wrapper->getResult("m");
|
||||
self::assertFalse($result->present);
|
||||
|
||||
self::assertNotException(function() use ($schema) {
|
||||
$array = self::NSTRINGS;
|
||||
$schema->getWrapper($array);
|
||||
});
|
||||
}
|
||||
|
||||
function testRstring() {
|
||||
/** @var AssocSchema $schema */
|
||||
$schema = Schema::ns(self::RSTRING_SCHEMA);
|
||||
|
||||
$array = self::STRINGS;
|
||||
$wrapper = $schema->getWrapper($array, null, ["throw" => false]);
|
||||
self::assertSame(["s" => "string", "f" => false, "m" => ""], $array);
|
||||
$result = $wrapper->getResult("s");
|
||||
self::assertTrue($result->normalized);
|
||||
$result = $wrapper->getResult("f");
|
||||
self::assertTrue($result->present);
|
||||
self::assertFalse($result->available);
|
||||
self::assertSame("unavailable", $result->messageKey);
|
||||
$result = $wrapper->getResult("m");
|
||||
self::assertFalse($result->present);
|
||||
self::assertSame("missing", $result->messageKey);
|
||||
|
||||
self::assertException(ValueException::class, function() use ($schema) {
|
||||
$array = self::STRINGS;
|
||||
$schema->getWrapper($array);
|
||||
});
|
||||
|
||||
$array = self::NSTRINGS;
|
||||
$wrapper = $schema->getWrapper($array, null, ["throw" => false]);
|
||||
self::assertSame(["s" => null, "f" => null, "m" => ""], $array);
|
||||
$result = $wrapper->getResult("s");
|
||||
self::assertFalse($result->valid);
|
||||
self::assertSame("null", $result->messageKey);
|
||||
$result = $wrapper->getResult("f");
|
||||
self::assertFalse($result->valid);
|
||||
self::assertSame("null", $result->messageKey);
|
||||
$result = $wrapper->getResult("m");
|
||||
self::assertFalse($result->present);
|
||||
self::assertSame("missing", $result->messageKey);
|
||||
|
||||
self::assertException(ValueException::class, function() use ($schema) {
|
||||
$array = self::NSTRINGS;
|
||||
$schema->getWrapper($array);
|
||||
});
|
||||
}
|
||||
|
||||
function testRnstring() {
|
||||
/** @var AssocSchema $schema */
|
||||
$schema = Schema::ns(self::RNSTRING_SCHEMA);
|
||||
|
||||
$array = self::STRINGS;
|
||||
$wrapper = $schema->getWrapper($array, null, ["throw" => false]);
|
||||
self::assertSame(["s" => "string", "f" => false, "m" => null], $array);
|
||||
$result = $wrapper->getResult("s");
|
||||
self::assertTrue($result->normalized);
|
||||
$result = $wrapper->getResult("f");
|
||||
self::assertTrue($result->present);
|
||||
self::assertFalse($result->available);
|
||||
self::assertSame("unavailable", $result->messageKey);
|
||||
$result = $wrapper->getResult("m");
|
||||
self::assertFalse($result->present);
|
||||
self::assertSame("missing", $result->messageKey);
|
||||
|
||||
self::assertException(ValueException::class, function() use ($schema) {
|
||||
$array = self::STRINGS;
|
||||
$schema->getWrapper($array);
|
||||
});
|
||||
|
||||
$array = self::NSTRINGS;
|
||||
$wrapper = $schema->getWrapper($array, null, ["throw" => false]);
|
||||
self::assertSame(["s" => null, "f" => null, "m" => null], $array);
|
||||
$result = $wrapper->getResult("s");
|
||||
self::assertTrue($result->normalized);
|
||||
$result = $wrapper->getResult("f");
|
||||
self::assertTrue($result->normalized);
|
||||
$result = $wrapper->getResult("m");
|
||||
self::assertFalse($result->present);
|
||||
self::assertSame("missing", $result->messageKey);
|
||||
|
||||
self::assertException(ValueException::class, function() use ($schema) {
|
||||
$array = self::NSTRINGS;
|
||||
$schema->getWrapper($array);
|
||||
});
|
||||
}
|
||||
}
|
68
tests/schema/_scalar/ScalarSchemaTest.php
Normal file
68
tests/schema/_scalar/ScalarSchemaTest.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
namespace nulib\schema\_scalar;
|
||||
|
||||
use nulib\tests\TestCase;
|
||||
use nulib\schema\SchemaException;
|
||||
|
||||
class ScalarSchemaTest extends TestCase {
|
||||
const NULL_SCHEMA = [
|
||||
"type" => [null],
|
||||
"default" => null,
|
||||
"title" => null,
|
||||
"required" => false,
|
||||
"nullable" => true,
|
||||
"desc" => null,
|
||||
"analyzer_func" => null,
|
||||
"extractor_func" => null,
|
||||
"parser_func" => null,
|
||||
"normalizer_func" => null,
|
||||
"messages" => null,
|
||||
"formatter_func" => null,
|
||||
"format" => null,
|
||||
"" => [
|
||||
"scalar",
|
||||
"compute_func" => null,
|
||||
"validate_func" => null,
|
||||
],
|
||||
"schema" => null,
|
||||
"name" => null,
|
||||
"pkey" => null,
|
||||
"header" => null,
|
||||
"computed" => null,
|
||||
];
|
||||
|
||||
static function schema(array $schema): array {
|
||||
return array_merge(self::NULL_SCHEMA, $schema);
|
||||
}
|
||||
|
||||
function testNormalize() {
|
||||
self::assertSame(self::NULL_SCHEMA, ScalarSchema::normalize_definition(null));
|
||||
self::assertSame(self::NULL_SCHEMA, ScalarSchema::normalize_definition([]));
|
||||
self::assertSame(self::NULL_SCHEMA, ScalarSchema::normalize_definition([null]));
|
||||
self::assertException(SchemaException::class, function () {
|
||||
ScalarSchema::normalize_definition([[]]);
|
||||
});
|
||||
self::assertException(SchemaException::class, function () {
|
||||
ScalarSchema::normalize_definition([[null]]);
|
||||
});
|
||||
|
||||
$string = self::schema(["type" => ["string"], "nullable" => false]);
|
||||
self::assertSame($string, ScalarSchema::normalize_definition("string"));
|
||||
self::assertSame($string, ScalarSchema::normalize_definition(["string"]));
|
||||
|
||||
$nstring = self::schema(["type" => ["string"]]);
|
||||
self::assertSame($nstring, ScalarSchema::normalize_definition(["?string"]));
|
||||
self::assertSame($nstring, ScalarSchema::normalize_definition(["?string|null"]));
|
||||
self::assertSame($nstring, ScalarSchema::normalize_definition(["string|null"]));
|
||||
self::assertSame($nstring, ScalarSchema::normalize_definition([["?string", "null"]]));
|
||||
self::assertSame($nstring, ScalarSchema::normalize_definition([["string", "null"]]));
|
||||
self::assertSame($nstring, ScalarSchema::normalize_definition([["string", null]]));
|
||||
|
||||
$key = self::schema(["type" => ["string", "int"], "nullable" => false]);
|
||||
self::assertSame($key, ScalarSchema::normalize_definition("string|int"));
|
||||
|
||||
$nkey = self::schema(["type" => ["string", "int"], "nullable" => true]);
|
||||
self::assertSame($nkey, ScalarSchema::normalize_definition("?string|int"));
|
||||
self::assertSame($nkey, ScalarSchema::normalize_definition("string|?int"));
|
||||
}
|
||||
}
|
296
tests/schema/_scalar/ScalarWrapperTest.php
Normal file
296
tests/schema/_scalar/ScalarWrapperTest.php
Normal file
@ -0,0 +1,296 @@
|
||||
<?php
|
||||
namespace nulib\schema\_scalar;
|
||||
|
||||
use nulib\tests\TestCase;
|
||||
use nulib\ValueException;
|
||||
use nulib\schema\input\Input;
|
||||
use stdClass;
|
||||
|
||||
class ScalarWrapperTest extends TestCase {
|
||||
function checkValue(ScalarWrapper $wrapper, $value, bool $present, bool $available, bool $valid, bool $normalized): void {
|
||||
self::assertSame($value, $wrapper->get(), "value");
|
||||
self::assertSame($present, $wrapper->isPresent(), "present");
|
||||
self::assertSame($available, $wrapper->isAvailable(), "available");
|
||||
self::assertSame($valid, $wrapper->isValid(), "valid");
|
||||
self::assertSame($normalized, $wrapper->isNormalized(), "normalized");
|
||||
}
|
||||
|
||||
function checkNormalize(ScalarSchema $schema, $orig, bool $normalize, $value, bool $present, bool $available, bool $valid, bool $normalized, ?array $inputParams=null): void {
|
||||
$wrapper = $schema->getWrapper();
|
||||
$wrapper->resetParams(["normalize" => $normalize]);
|
||||
if ($inputParams !== null) $input = new Input($orig, $inputParams);
|
||||
else $input = $orig;
|
||||
$wrapper->reset($input);
|
||||
$this->checkValue($wrapper, $value, $present, $available, $valid, $normalized);
|
||||
}
|
||||
|
||||
function checkException(ScalarSchema $schema, $orig, bool $normalize, string $exceptionClass, ?array $inputParams=null) {
|
||||
$wrapper = $schema->getWrapper();
|
||||
if ($inputParams !== null) $orig = new Input($orig, $inputParams);
|
||||
self::assertException($exceptionClass, function() use ($wrapper, &$orig, $normalize) {
|
||||
$wrapper->resetParams(["normalize" => $normalize]);
|
||||
$wrapper->reset($orig);
|
||||
});
|
||||
}
|
||||
|
||||
function testRaw() {
|
||||
$schema = new ScalarSchema();
|
||||
|
||||
$this->checkNormalize($schema, false, false, false, true, true, true, true);
|
||||
$this->checkNormalize($schema, false, true, false, true, true, true, true);
|
||||
|
||||
$this->checkNormalize($schema, null, false, null, true, true, true, true);
|
||||
$this->checkNormalize($schema, null, true, null, true, true, true, true);
|
||||
|
||||
$obj = new stdClass();
|
||||
$this->checkNormalize($schema, $obj, false, $obj, true, true, true, true);
|
||||
$this->checkNormalize($schema, $obj, true, $obj, true, true, true, true);
|
||||
|
||||
$schema = new ScalarSchema("raw");
|
||||
|
||||
$this->checkNormalize($schema, false, false, false, true, true, true, true);
|
||||
$this->checkNormalize($schema, false, true, false, true, true, true, true);
|
||||
|
||||
$this->checkNormalize($schema, null, false, null, true, true, true, true);
|
||||
$this->checkNormalize($schema, null, true, null, true, true, true, true);
|
||||
|
||||
$obj = new stdClass();
|
||||
$this->checkNormalize($schema, $obj, false, $obj, true, true, true, true);
|
||||
$this->checkNormalize($schema, $obj, true, $obj, true, true, true, true);
|
||||
}
|
||||
|
||||
function testMixed() {
|
||||
$schema = new ScalarSchema("mixed");
|
||||
|
||||
$this->checkNormalize($schema, false, false, false, true, true, true, true);
|
||||
$this->checkNormalize($schema, false, true, false, true, true, true, true);
|
||||
|
||||
$this->checkNormalize($schema, null, false, null, true, true, false, false);
|
||||
$this->checkException($schema, null, true, ValueException::class);
|
||||
|
||||
$obj = new stdClass();
|
||||
$this->checkNormalize($schema, $obj, false, $obj, true, true, true, true);
|
||||
$this->checkNormalize($schema, $obj, true, $obj, true, true, true, true);
|
||||
|
||||
$schema = new ScalarSchema("?mixed");
|
||||
|
||||
$this->checkNormalize($schema, false, false, false, true, true, true, true);
|
||||
$this->checkNormalize($schema, false, true, false, true, true, true, true);
|
||||
|
||||
$this->checkNormalize($schema, null, false, null, true, true, true, true);
|
||||
$this->checkNormalize($schema, null, true, null, true, true, true, true);
|
||||
|
||||
$obj = new stdClass();
|
||||
$this->checkNormalize($schema, $obj, false, $obj, true, true, true, true);
|
||||
$this->checkNormalize($schema, $obj, true, $obj, true, true, true, true);
|
||||
}
|
||||
|
||||
function testRawstring() {
|
||||
$schema = new ScalarSchema("rawstring");
|
||||
|
||||
$this->checkNormalize($schema, false, false, null, true, false, true, true);
|
||||
$this->checkNormalize($schema, false, true, null, true, false, true, true);
|
||||
|
||||
$this->checkNormalize($schema, null, false, null, true, true, false, false);
|
||||
$this->checkException($schema, null, true, ValueException::class);
|
||||
|
||||
$this->checkNormalize($schema, "", false, "", true, true, true, true);
|
||||
$this->checkNormalize($schema, "", true, "", true, true, true, true);
|
||||
|
||||
$this->checkNormalize($schema, " ", false, " ", true, true, true, true);
|
||||
$this->checkNormalize($schema, " ", true, " ", true, true, true, true);
|
||||
|
||||
$this->checkNormalize($schema, "text", false, "text", true, true, true, true);
|
||||
$this->checkNormalize($schema, "text", true, "text", true, true, true, true);
|
||||
|
||||
$this->checkNormalize($schema, " text ", false, " text ", true, true, true, true);
|
||||
$this->checkNormalize($schema, " text ", true, " text ", true, true, true, true);
|
||||
|
||||
$this->checkNormalize($schema, true, false, true, true, true, true, false);
|
||||
$this->checkNormalize($schema, true, true, "1", true, true, true, false);
|
||||
|
||||
$this->checkNormalize($schema, 42, false, 42, true, true, true, false);
|
||||
$this->checkNormalize($schema, 42, true, "42", true, true, true, false);
|
||||
|
||||
$this->checkNormalize($schema, [], false, [], true, true, false, false);
|
||||
$this->checkException($schema, [], true, ValueException::class);
|
||||
|
||||
## Tester valeur par défaut
|
||||
$schema = new ScalarSchema(["rawstring", null]);
|
||||
|
||||
$this->checkNormalize($schema, false, false, null, true, false, true, true);
|
||||
$this->checkNormalize($schema, false, true, null, true, false, true, true);
|
||||
|
||||
$this->checkNormalize($schema, null, false, null, true, true, false, false);
|
||||
$this->checkException($schema, null, true, ValueException::class);
|
||||
|
||||
$schema = new ScalarSchema(["rawstring", "default"]);
|
||||
|
||||
$this->checkNormalize($schema, false, false, "default", true, true, true, true);
|
||||
$this->checkNormalize($schema, false, true, "default", true, true, true, true);
|
||||
|
||||
$this->checkNormalize($schema, null, false, null, true, true, false, false);
|
||||
$this->checkException($schema, null, true, ValueException::class);
|
||||
|
||||
## Tester nullable
|
||||
$schema = new ScalarSchema("?rawstring");
|
||||
|
||||
$this->checkNormalize($schema, null, false, null, true, true, true, true);
|
||||
$this->checkNormalize($schema, null, true, null, true, true, true, true);
|
||||
|
||||
## Tester required
|
||||
$schema = new ScalarSchema(["rawstring", "required" => true]);
|
||||
|
||||
$this->checkNormalize($schema, false, false, null, true, false, false, false);
|
||||
$this->checkException($schema, false, true, ValueException::class);
|
||||
|
||||
## Tester allow_empty === false
|
||||
$inputParams = ["allow_empty" => false];
|
||||
$schema = new ScalarSchema("rawstring");
|
||||
|
||||
$this->checkNormalize($schema, null, false, null, true, true, false, false, $inputParams);
|
||||
$this->checkException($schema, null, true, ValueException::class, $inputParams);
|
||||
|
||||
$this->checkNormalize($schema, "", false, null, true, false, true, true, $inputParams);
|
||||
$this->checkNormalize($schema, "", true, null, true, false, true, true, $inputParams);
|
||||
|
||||
$schema = new ScalarSchema("?rawstring");
|
||||
|
||||
$this->checkNormalize($schema, null, false, null, true, true, true, true, $inputParams);
|
||||
$this->checkNormalize($schema, null, true, null, true, true, true, true, $inputParams);
|
||||
|
||||
$this->checkNormalize($schema, "", false, null, true, false, true, true, $inputParams);
|
||||
$this->checkNormalize($schema, "", true, null, true, false, true, true, $inputParams);
|
||||
}
|
||||
|
||||
function testString() {
|
||||
$schema = new ScalarSchema("string");
|
||||
|
||||
$this->checkNormalize($schema, false, false, null, true, false, true, true);
|
||||
$this->checkNormalize($schema, false, true, null, true, false, true, true);
|
||||
|
||||
$this->checkNormalize($schema, null, false, null, true, true, false, false);
|
||||
$this->checkException($schema, null, true, ValueException::class);
|
||||
|
||||
$this->checkNormalize($schema, "", false, "", true, true, true, true);
|
||||
$this->checkNormalize($schema, "", true, "", true, true, true, true);
|
||||
|
||||
$this->checkNormalize($schema, " ", false, "", true, true, true, false);
|
||||
$this->checkNormalize($schema, " ", true, "", true, true, true, false);
|
||||
|
||||
$this->checkNormalize($schema, "text", false, "text", true, true, true, true);
|
||||
$this->checkNormalize($schema, "text", true, "text", true, true, true, true);
|
||||
|
||||
$this->checkNormalize($schema, " text ", false, "text", true, true, true, false);
|
||||
$this->checkNormalize($schema, " text ", true, "text", true, true, true, false);
|
||||
|
||||
$this->checkNormalize($schema, true, false, true, true, true, true, false);
|
||||
$this->checkNormalize($schema, true, true, "1", true, true, true, false);
|
||||
|
||||
$this->checkNormalize($schema, 42, false, 42, true, true, true, false);
|
||||
$this->checkNormalize($schema, 42, true, "42", true, true, true, false);
|
||||
|
||||
$this->checkNormalize($schema, [], false, [], true, true, false, false);
|
||||
$this->checkException($schema, [], true, ValueException::class);
|
||||
|
||||
## Tester nullable
|
||||
$schema = new ScalarSchema("?string");
|
||||
|
||||
$this->checkNormalize($schema, null, false, null, true, true, true, true);
|
||||
$this->checkNormalize($schema, null, true, null, true, true, true, true);
|
||||
|
||||
## Tester required
|
||||
$schema = new ScalarSchema(["string", "required" => true]);
|
||||
|
||||
$this->checkNormalize($schema, false, false, null, true, false, false, false);
|
||||
$this->checkException($schema, false, true, ValueException::class);
|
||||
|
||||
## Tester allow_empty === false
|
||||
$inputParams = ["allow_empty" => false];
|
||||
$schema = new ScalarSchema("string");
|
||||
|
||||
$this->checkNormalize($schema, null, false, null, true, true, false, false, $inputParams);
|
||||
$this->checkException($schema, null, true, ValueException::class, $inputParams);
|
||||
|
||||
$this->checkNormalize($schema, "", false, null, true, false, true, true, $inputParams);
|
||||
$this->checkNormalize($schema, "", true, null, true, false, true, true, $inputParams);
|
||||
|
||||
$schema = new ScalarSchema("?string");
|
||||
|
||||
$this->checkNormalize($schema, null, false, null, true, true, true, true, $inputParams);
|
||||
$this->checkNormalize($schema, null, true, null, true, true, true, true, $inputParams);
|
||||
|
||||
$this->checkNormalize($schema, "", false, null, true, false, true, true, $inputParams);
|
||||
$this->checkNormalize($schema, "", true, null, true, false, true, true, $inputParams);
|
||||
}
|
||||
|
||||
function testInt() {
|
||||
$schema = new ScalarSchema("int");
|
||||
|
||||
$this->checkNormalize($schema, false, false, null, true, false, true, true);
|
||||
$this->checkNormalize($schema, false, true, null, true, false, true, true);
|
||||
|
||||
$this->checkNormalize($schema, null, false, null, true, true, false, false);
|
||||
$this->checkException($schema, null, true, ValueException::class);
|
||||
|
||||
$this->checkNormalize($schema, 42, false, 42, true, true, true, true);
|
||||
$this->checkNormalize($schema, 42, true, 42, true, true, true, true);
|
||||
|
||||
$this->checkNormalize($schema, "42", false, "42", true, true, true, false);
|
||||
$this->checkNormalize($schema, "42", true, 42, true, true, true, false);
|
||||
|
||||
$this->checkNormalize($schema, "42.5", false, "42.5", true, true, true, false);
|
||||
$this->checkNormalize($schema, "42.5", true, 42, true, true, true, false);
|
||||
|
||||
$this->checkNormalize($schema, "42,5", false, "42,5", true, true, true, false);
|
||||
$this->checkNormalize($schema, "42,5", true, 42, true, true, true, false);
|
||||
|
||||
$this->checkNormalize($schema, " 42 ", false, "42", true, true, true, false);
|
||||
$this->checkNormalize($schema, " 42 ", true, 42, true, true, true, false);
|
||||
|
||||
$this->checkNormalize($schema, "", false, "", true, true, false, false);
|
||||
$this->checkException($schema, "", true, ValueException::class);
|
||||
|
||||
$this->checkNormalize($schema, " ", false, " ", true, true, false, false);
|
||||
$this->checkException($schema, " ", true, ValueException::class);
|
||||
|
||||
$this->checkNormalize($schema, "text", false, "text", true, true, false, false);
|
||||
$this->checkException($schema, "text", true, ValueException::class);
|
||||
|
||||
$this->checkNormalize($schema, true, false, true, true, true, true, false);
|
||||
$this->checkNormalize($schema, true, true, 1, true, true, true, false);
|
||||
|
||||
$this->checkNormalize($schema, [], false, [], true, true, false, false);
|
||||
$this->checkException($schema, [], true, ValueException::class);
|
||||
|
||||
## Tester nullable
|
||||
$schema = new ScalarSchema("?int");
|
||||
|
||||
$this->checkNormalize($schema, null, false, null, true, true, true, true);
|
||||
$this->checkNormalize($schema, null, true, null, true, true, true, true);
|
||||
|
||||
## Tester required
|
||||
$schema = new ScalarSchema(["int", "required" => true]);
|
||||
|
||||
$this->checkNormalize($schema, false, false, null, true, false, false, false);
|
||||
$this->checkException($schema, false, true, ValueException::class);
|
||||
|
||||
## Tester allow_empty === false
|
||||
$inputParams = ["allow_empty" => false];
|
||||
$schema = new ScalarSchema("int");
|
||||
|
||||
$this->checkNormalize($schema, null, false, null, true, true, false, false, $inputParams);
|
||||
$this->checkException($schema, null, true, ValueException::class, $inputParams);
|
||||
|
||||
$this->checkNormalize($schema, "", false, null, true, false, true, true, $inputParams);
|
||||
$this->checkNormalize($schema, "", true, null, true, false, true, true, $inputParams);
|
||||
|
||||
$schema = new ScalarSchema("?int");
|
||||
|
||||
$this->checkNormalize($schema, null, false, null, true, true, true, true, $inputParams);
|
||||
$this->checkNormalize($schema, null, true, null, true, true, true, true, $inputParams);
|
||||
|
||||
$this->checkNormalize($schema, "", false, null, true, false, true, true, $inputParams);
|
||||
$this->checkNormalize($schema, "", true, null, true, false, true, true, $inputParams);
|
||||
}
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
use Exception;
|
||||
use nulib\tests\TestCase;
|
||||
use nur\sery\wip\schema\_scalar\ScalarWrapper;
|
||||
use nur\sery\wip\schema\Schema;
|
||||
use nulib\schema\_scalar\ScalarWrapper;
|
||||
use nulib\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, $schema, "bool", $wrapper);
|
||||
Schema::nw($value, null, "bool", $schema, $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, $schema, "?bool", $wrapper);
|
||||
Schema::nw($value, null, "?bool", $schema, $wrapper);
|
||||
$wrapperSetter = function($value) use($wrapper) {
|
||||
return function() use($wrapper, $value) {
|
||||
$wrapper->set($value);
|
@ -1,10 +1,10 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
use Exception;
|
||||
use nulib\tests\TestCase;
|
||||
use nur\sery\wip\schema\_scalar\ScalarWrapper;
|
||||
use nur\sery\wip\schema\Schema;
|
||||
use nulib\schema\_scalar\ScalarWrapper;
|
||||
use nulib\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, $schema, "float", $wrapper);
|
||||
Schema::nw($value, null, "float", $schema, $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, [
|
||||
Schema::nw($value, null, [
|
||||
"float", null,
|
||||
"required" => true,
|
||||
], $wrapper);
|
||||
], $schema, $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, $schema, "?float", $wrapper);
|
||||
Schema::nw($value, null, "?float", $schema, $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, [
|
||||
Schema::nw($value, null, [
|
||||
"?float", null,
|
||||
"required" => true,
|
||||
], $wrapper);
|
||||
], $schema, $wrapper);
|
||||
$wrapperSetter = function($value) use($wrapper) {
|
||||
return function() use($wrapper, $value) {
|
||||
$wrapper->set($value);
|
@ -1,10 +1,10 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
use Exception;
|
||||
use nulib\tests\TestCase;
|
||||
use nur\sery\wip\schema\_scalar\ScalarWrapper;
|
||||
use nur\sery\wip\schema\Schema;
|
||||
use nulib\schema\_scalar\ScalarWrapper;
|
||||
use nulib\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, $schema, "int", $wrapper);
|
||||
Schema::nw($value, null, "int", $schema, $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, [
|
||||
Schema::nw($value, null, [
|
||||
"int", null,
|
||||
"required" => true,
|
||||
], $wrapper);
|
||||
], $schema, $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, $schema, "?int", $wrapper);
|
||||
Schema::nw($value, null, "?int", $schema, $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, [
|
||||
Schema::nw($value, null, [
|
||||
"?int", null,
|
||||
"required" => true,
|
||||
], $wrapper);
|
||||
], $schema, $wrapper);
|
||||
$wrapperSetter = function($value) use($wrapper) {
|
||||
return function() use($wrapper, $value) {
|
||||
$wrapper->set($value);
|
@ -1,10 +1,10 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
use Exception;
|
||||
use nulib\tests\TestCase;
|
||||
use nur\sery\wip\schema\_scalar\ScalarWrapper;
|
||||
use nur\sery\wip\schema\Schema;
|
||||
use nulib\schema\_scalar\ScalarWrapper;
|
||||
use nulib\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, $schema, "string", $wrapper);
|
||||
Schema::nw($value, null, "string", $schema, $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, [
|
||||
Schema::nw($value, null, [
|
||||
"string", null,
|
||||
"required" => true,
|
||||
], $wrapper);
|
||||
], $schema, $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, $schema, "?string", $wrapper);
|
||||
Schema::nw($value, null, "?string", $schema, $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, [
|
||||
Schema::nw($value, null, [
|
||||
"?string", null,
|
||||
"required" => true,
|
||||
], $wrapper);
|
||||
], $schema, $wrapper);
|
||||
$wrapperSetter = function($value) use($wrapper) {
|
||||
return function() use($wrapper, $value) {
|
||||
$wrapper->set($value);
|
@ -1,9 +1,9 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\types;
|
||||
namespace nulib\schema\types;
|
||||
|
||||
use nulib\tests\TestCase;
|
||||
use nur\sery\wip\schema\_scalar\ScalarWrapper;
|
||||
use nur\sery\wip\schema\Schema;
|
||||
use nulib\schema\_scalar\ScalarWrapper;
|
||||
use nulib\schema\Schema;
|
||||
|
||||
class unionTest extends TestCase {
|
||||
function testUnionTypes() {
|
||||
@ -11,7 +11,7 @@ class unionTest extends TestCase {
|
||||
|
||||
# string puis int
|
||||
/** @var ScalarWrapper $siw */
|
||||
Schema::nw($si, null, $sis, "string|int", $siw);
|
||||
Schema::nw($si, null, "string|int", $sis, $siw);
|
||||
|
||||
$siw->set("12");
|
||||
self::assertSame("12", $si);
|
||||
@ -20,7 +20,7 @@ class unionTest extends TestCase {
|
||||
|
||||
# int puis string
|
||||
/** @var ScalarWrapper $isw */
|
||||
Schema::nw($is, null, $iss, "int|string", $isw);
|
||||
Schema::nw($is, null, "int|string", $iss, $isw);
|
||||
|
||||
$isw->set("12");
|
||||
self::assertSame("12", $is);
|
@ -1,66 +0,0 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\php\access;
|
||||
|
||||
use nulib\tests\TestCase;
|
||||
use stdClass;
|
||||
|
||||
class KeyAccessTest extends TestCase {
|
||||
function testAccess() {
|
||||
$default = new stdClass();
|
||||
$array = ["null" => null, "false" => false, "empty" => ""];
|
||||
|
||||
#
|
||||
$a = new KeyAccess($array, "inexistant");
|
||||
self::assertFalse($a->exists());
|
||||
self::assertFalse($a->available());
|
||||
self::assertSame($default, $a->get($default));
|
||||
|
||||
$a = new KeyAccess($array, "null");
|
||||
self::assertTrue($a->exists());
|
||||
self::assertTrue($a->available());
|
||||
self::assertSame(null, $a->get($default));
|
||||
|
||||
$a = new KeyAccess($array, "false");
|
||||
self::assertTrue($a->exists());
|
||||
self::assertFalse($a->available());
|
||||
self::assertSame($default, $a->get($default));
|
||||
|
||||
$a = new KeyAccess($array, "empty");
|
||||
self::assertTrue($a->exists());
|
||||
self::assertTrue($a->available());
|
||||
self::assertSame("", $a->get($default));
|
||||
|
||||
#
|
||||
$a = new KeyAccess($array, "null", ["allow_null" => false]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertFalse($a->available());
|
||||
self::assertSame($default, $a->get($default));
|
||||
|
||||
$a = new KeyAccess($array, "null", ["allow_null" => true]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertTrue($a->available());
|
||||
self::assertSame(null, $a->get($default));
|
||||
|
||||
#
|
||||
$a = new KeyAccess($array, "false", ["allow_false" => false]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertFalse($a->available());
|
||||
self::assertSame($default, $a->get($default));
|
||||
|
||||
$a = new KeyAccess($array, "false", ["allow_false" => true]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertTrue($a->available());
|
||||
self::assertSame(false, $a->get($default));
|
||||
|
||||
#
|
||||
$a = new KeyAccess($array, "empty", ["allow_empty" => false]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertFalse($a->available());
|
||||
self::assertSame($default, $a->get($default));
|
||||
|
||||
$a = new KeyAccess($array, "empty", ["allow_empty" => true]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertTrue($a->available());
|
||||
self::assertSame("", $a->get($default));
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\php\access;
|
||||
|
||||
use nulib\tests\TestCase;
|
||||
use stdClass;
|
||||
|
||||
class ValueAccessTest extends TestCase {
|
||||
function testAccess() {
|
||||
$default = new stdClass();
|
||||
|
||||
#
|
||||
$i = null;
|
||||
$a = new ValueAccess($i);
|
||||
self::assertFalse($a->exists());
|
||||
self::assertFalse($a->available());
|
||||
self::assertSame($default, $a->get($default));
|
||||
|
||||
$i = false;
|
||||
$a = new ValueAccess($i);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertTrue($a->available());
|
||||
self::assertSame(false, $a->get($default));
|
||||
|
||||
$i = "";
|
||||
$a = new ValueAccess($i);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertTrue($a->available());
|
||||
self::assertSame("", $a->get($default));
|
||||
|
||||
#
|
||||
$i = null;
|
||||
$a = new ValueAccess($i, ["allow_null" => false]);
|
||||
self::assertFalse($a->exists());
|
||||
self::assertFalse($a->available());
|
||||
self::assertSame($default, $a->get($default));
|
||||
|
||||
$i = null;
|
||||
$a = new ValueAccess($i, ["allow_null" => true]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertTrue($a->available());
|
||||
self::assertSame(null, $a->get($default));
|
||||
|
||||
#
|
||||
$i = false;
|
||||
$a = new ValueAccess($i, ["allow_false" => false]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertFalse($a->available());
|
||||
self::assertSame($default, $a->get($default));
|
||||
|
||||
$i = false;
|
||||
$a = new ValueAccess($i, ["allow_false" => true]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertTrue($a->available());
|
||||
self::assertSame(false, $a->get($default));
|
||||
|
||||
#
|
||||
$i = "";
|
||||
$a = new ValueAccess($i, ["allow_empty" => false]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertFalse($a->available());
|
||||
self::assertSame($default, $a->get($default));
|
||||
|
||||
$i = "";
|
||||
$a = new ValueAccess($i, ["allow_empty" => true]);
|
||||
self::assertTrue($a->exists());
|
||||
self::assertTrue($a->available());
|
||||
self::assertSame("", $a->get($default));
|
||||
}
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\_assoc;
|
||||
|
||||
use nulib\ext\yaml;
|
||||
use nulib\tests\TestCase;
|
||||
use nur\sery\wip\schema\_scalar\ScalarSchemaTest;
|
||||
|
||||
class AssocSchemaTest extends TestCase {
|
||||
const NULL_SCHEMA = [
|
||||
"" => ["assoc"],
|
||||
"schema" => null,
|
||||
"type" => [null],
|
||||
"default" => null,
|
||||
"title" => null,
|
||||
"required" => false,
|
||||
"nullable" => true,
|
||||
"desc" => null,
|
||||
"analyzer_func" => null,
|
||||
"extractor_func" => null,
|
||||
"parser_func" => null,
|
||||
"normalizer_func" => null,
|
||||
"messages" => null,
|
||||
"formatter_func" => null,
|
||||
"format" => null,
|
||||
"name" => null,
|
||||
"pkey" => null,
|
||||
"header" => null,
|
||||
"computed" => null,
|
||||
];
|
||||
|
||||
static function schema(array $definition, array $keyDefinitions): array {
|
||||
$definition = array_merge(self::NULL_SCHEMA, $definition, ["schema" => []]);
|
||||
foreach ($keyDefinitions as $key => $keydef) {
|
||||
$definition["schema"][$key] = array_merge(ScalarSchemaTest::NULL_SCHEMA, $keydef);
|
||||
}; unset($subdef);
|
||||
return $definition;
|
||||
}
|
||||
|
||||
function testNormalize() {
|
||||
self::assertSame(self::schema([
|
||||
"type" => ["array"], "nullable" => true,
|
||||
], [
|
||||
"a" => [
|
||||
"type" => ["string"], "nullable" => false,
|
||||
"name" => "a", "pkey" => "a", "header" => "a",
|
||||
],
|
||||
]), AssocSchema::normalize(["a" => "string"]));
|
||||
|
||||
self::assertSame(self::schema([
|
||||
"type" => ["array"], "nullable" => true,
|
||||
], [
|
||||
"a" => [
|
||||
"type" => ["string"], "nullable" => false,
|
||||
"name" => "a", "pkey" => "a", "header" => "a",
|
||||
],
|
||||
"b" => [
|
||||
"type" => ["int"], "nullable" => false,
|
||||
"name" => "b", "pkey" => "b", "header" => "b",
|
||||
],
|
||||
"c" => [
|
||||
"type" => ["bool"], "nullable" => false,
|
||||
"name" => "c", "pkey" => "c", "header" => "c",
|
||||
],
|
||||
]), AssocSchema::normalize([
|
||||
"a" => "string",
|
||||
"b" => "int",
|
||||
"c" => "bool",
|
||||
]));
|
||||
}
|
||||
|
||||
function testConstructor() {
|
||||
$schema = new AssocSchema([
|
||||
"a" => "string",
|
||||
"b" => "int",
|
||||
"c" => "bool",
|
||||
]);
|
||||
self::assertSame(self::schema([
|
||||
"type" => ["array"], "nullable" => true,
|
||||
], [
|
||||
"a" => [
|
||||
"type" => ["string"], "nullable" => false,
|
||||
"name" => "a", "pkey" => "a", "header" => "a",
|
||||
],
|
||||
"b" => [
|
||||
"type" => ["int"], "nullable" => false,
|
||||
"name" => "b", "pkey" => "b", "header" => "b",
|
||||
],
|
||||
"c" => [
|
||||
"type" => ["bool"], "nullable" => false,
|
||||
"name" => "c", "pkey" => "c", "header" => "c",
|
||||
],
|
||||
]), $schema->getDefinition());
|
||||
yaml::dump($schema->getDefinition());
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\_scalar;
|
||||
|
||||
use nulib\tests\TestCase;
|
||||
use nur\sery\wip\schema\SchemaException;
|
||||
|
||||
class ScalarSchemaTest extends TestCase {
|
||||
const NULL_SCHEMA = [
|
||||
"type" => [null],
|
||||
"default" => null,
|
||||
"title" => null,
|
||||
"required" => false,
|
||||
"nullable" => true,
|
||||
"desc" => null,
|
||||
"analyzer_func" => null,
|
||||
"extractor_func" => null,
|
||||
"parser_func" => null,
|
||||
"normalizer_func" => null,
|
||||
"messages" => null,
|
||||
"formatter_func" => null,
|
||||
"format" => null,
|
||||
"" => ["scalar"],
|
||||
"schema" => null,
|
||||
"name" => null,
|
||||
"pkey" => null,
|
||||
"header" => null,
|
||||
"computed" => null,
|
||||
];
|
||||
|
||||
static function schema(array $schema): array {
|
||||
return array_merge(self::NULL_SCHEMA, $schema);
|
||||
}
|
||||
|
||||
function testNormalize() {
|
||||
self::assertSame(self::NULL_SCHEMA, ScalarSchema::normalize(null));
|
||||
self::assertSame(self::NULL_SCHEMA, ScalarSchema::normalize([]));
|
||||
self::assertSame(self::NULL_SCHEMA, ScalarSchema::normalize([null]));
|
||||
self::assertException(SchemaException::class, function () {
|
||||
ScalarSchema::normalize([[]]);
|
||||
});
|
||||
self::assertException(SchemaException::class, function () {
|
||||
ScalarSchema::normalize([[null]]);
|
||||
});
|
||||
|
||||
$string = self::schema(["type" => ["string"], "nullable" => false]);
|
||||
self::assertSame($string, ScalarSchema::normalize("string"));
|
||||
self::assertSame($string, ScalarSchema::normalize(["string"]));
|
||||
|
||||
$nstring = self::schema(["type" => ["string"]]);
|
||||
self::assertSame($nstring, ScalarSchema::normalize(["?string"]));
|
||||
self::assertSame($nstring, ScalarSchema::normalize(["?string|null"]));
|
||||
self::assertSame($nstring, ScalarSchema::normalize(["string|null"]));
|
||||
self::assertSame($nstring, ScalarSchema::normalize([["?string", "null"]]));
|
||||
self::assertSame($nstring, ScalarSchema::normalize([["string", "null"]]));
|
||||
self::assertSame($nstring, ScalarSchema::normalize([["string", null]]));
|
||||
|
||||
$key = self::schema(["type" => ["string", "int"], "nullable" => false]);
|
||||
self::assertSame($key, ScalarSchema::normalize("string|int"));
|
||||
|
||||
$nkey = self::schema(["type" => ["string", "int"], "nullable" => true]);
|
||||
self::assertSame($nkey, ScalarSchema::normalize("?string|int"));
|
||||
self::assertSame($nkey, ScalarSchema::normalize("string|?int"));
|
||||
}
|
||||
}
|
@ -1,294 +0,0 @@
|
||||
<?php
|
||||
namespace nur\sery\wip\schema\_scalar;
|
||||
|
||||
use nulib\tests\TestCase;
|
||||
use nulib\ValueException;
|
||||
use nur\sery\wip\schema\input\Input;
|
||||
use stdClass;
|
||||
|
||||
class ScalarWrapperTest extends TestCase {
|
||||
function checkValue(ScalarWrapper $wrapper, $value, bool $present, bool $available, bool $valid, bool $normalized): void {
|
||||
self::assertSame($value, $wrapper->get(), "value");
|
||||
self::assertSame($present, $wrapper->isPresent(), "present");
|
||||
self::assertSame($available, $wrapper->isAvailable(), "available");
|
||||
self::assertSame($valid, $wrapper->isValid(), "valid");
|
||||
self::assertSame($normalized, $wrapper->isNormalized(), "normalized");
|
||||
}
|
||||
|
||||
function checkVerifix(ScalarSchema $schema, $orig, bool $verifix, $value, bool $present, bool $available, bool $valid, bool $normalized, ?array $inputParams=null): void {
|
||||
$wrapper = $schema->getWrapper();
|
||||
if ($inputParams !== null) $input = new Input($orig, $inputParams);
|
||||
else $input = $orig;
|
||||
$wrapper->reset($input, null, $verifix);
|
||||
$this->checkValue($wrapper, $value, $present, $available, $valid, $normalized);
|
||||
}
|
||||
|
||||
function checkException(ScalarSchema $schema, $orig, bool $verifix, string $exceptionClass, ?array $inputParams=null) {
|
||||
$wrapper = $schema->getWrapper();
|
||||
if ($inputParams !== null) $orig = new Input($orig, $inputParams);
|
||||
self::assertException($exceptionClass, function() use ($wrapper, &$orig, $verifix) {
|
||||
$wrapper->reset($orig, null, $verifix);
|
||||
});
|
||||
}
|
||||
|
||||
function testRaw() {
|
||||
$schema = new ScalarSchema();
|
||||
|
||||
$this->checkVerifix($schema, false, false, false, true, true, true, true);
|
||||
$this->checkVerifix($schema, false, true, false, true, true, true, true);
|
||||
|
||||
$this->checkVerifix($schema, null, false, null, true, true, true, true);
|
||||
$this->checkVerifix($schema, null, true, null, true, true, true, true);
|
||||
|
||||
$obj = new stdClass();
|
||||
$this->checkVerifix($schema, $obj, false, $obj, true, true, true, true);
|
||||
$this->checkVerifix($schema, $obj, true, $obj, true, true, true, true);
|
||||
|
||||
$schema = new ScalarSchema("raw");
|
||||
|
||||
$this->checkVerifix($schema, false, false, false, true, true, true, true);
|
||||
$this->checkVerifix($schema, false, true, false, true, true, true, true);
|
||||
|
||||
$this->checkVerifix($schema, null, false, null, true, true, true, true);
|
||||
$this->checkVerifix($schema, null, true, null, true, true, true, true);
|
||||
|
||||
$obj = new stdClass();
|
||||
$this->checkVerifix($schema, $obj, false, $obj, true, true, true, true);
|
||||
$this->checkVerifix($schema, $obj, true, $obj, true, true, true, true);
|
||||
}
|
||||
|
||||
function testMixed() {
|
||||
$schema = new ScalarSchema("mixed");
|
||||
|
||||
$this->checkVerifix($schema, false, false, false, true, true, true, true);
|
||||
$this->checkVerifix($schema, false, true, false, true, true, true, true);
|
||||
|
||||
$this->checkVerifix($schema, null, false, null, true, true, false, false);
|
||||
$this->checkException($schema, null, true, ValueException::class);
|
||||
|
||||
$obj = new stdClass();
|
||||
$this->checkVerifix($schema, $obj, false, $obj, true, true, true, true);
|
||||
$this->checkVerifix($schema, $obj, true, $obj, true, true, true, true);
|
||||
|
||||
$schema = new ScalarSchema("?mixed");
|
||||
|
||||
$this->checkVerifix($schema, false, false, false, true, true, true, true);
|
||||
$this->checkVerifix($schema, false, true, false, true, true, true, true);
|
||||
|
||||
$this->checkVerifix($schema, null, false, null, true, true, true, true);
|
||||
$this->checkVerifix($schema, null, true, null, true, true, true, true);
|
||||
|
||||
$obj = new stdClass();
|
||||
$this->checkVerifix($schema, $obj, false, $obj, true, true, true, true);
|
||||
$this->checkVerifix($schema, $obj, true, $obj, true, true, true, true);
|
||||
}
|
||||
|
||||
function testRawstring() {
|
||||
$schema = new ScalarSchema("rawstring");
|
||||
|
||||
$this->checkVerifix($schema, false, false, null, true, false, true, true);
|
||||
$this->checkVerifix($schema, false, true, null, true, false, true, true);
|
||||
|
||||
$this->checkVerifix($schema, null, false, null, true, true, false, false);
|
||||
$this->checkException($schema, null, true, ValueException::class);
|
||||
|
||||
$this->checkVerifix($schema, "", false, "", true, true, true, true);
|
||||
$this->checkVerifix($schema, "", true, "", true, true, true, true);
|
||||
|
||||
$this->checkVerifix($schema, " ", false, " ", true, true, true, true);
|
||||
$this->checkVerifix($schema, " ", true, " ", true, true, true, true);
|
||||
|
||||
$this->checkVerifix($schema, "text", false, "text", true, true, true, true);
|
||||
$this->checkVerifix($schema, "text", true, "text", true, true, true, true);
|
||||
|
||||
$this->checkVerifix($schema, " text ", false, " text ", true, true, true, true);
|
||||
$this->checkVerifix($schema, " text ", true, " text ", true, true, true, true);
|
||||
|
||||
$this->checkVerifix($schema, true, false, true, true, true, true, false);
|
||||
$this->checkVerifix($schema, true, true, "1", true, true, true, false);
|
||||
|
||||
$this->checkVerifix($schema, 42, false, 42, true, true, true, false);
|
||||
$this->checkVerifix($schema, 42, true, "42", true, true, true, false);
|
||||
|
||||
$this->checkVerifix($schema, [], false, [], true, true, false, false);
|
||||
$this->checkException($schema, [], true, ValueException::class);
|
||||
|
||||
## Tester valeur par défaut
|
||||
$schema = new ScalarSchema(["rawstring", null]);
|
||||
|
||||
$this->checkVerifix($schema, false, false, null, true, false, true, true);
|
||||
$this->checkVerifix($schema, false, true, null, true, false, true, true);
|
||||
|
||||
$this->checkVerifix($schema, null, false, null, true, true, false, false);
|
||||
$this->checkException($schema, null, true, ValueException::class);
|
||||
|
||||
$schema = new ScalarSchema(["rawstring", "default"]);
|
||||
|
||||
$this->checkVerifix($schema, false, false, "default", true, true, true, true);
|
||||
$this->checkVerifix($schema, false, true, "default", true, true, true, true);
|
||||
|
||||
$this->checkVerifix($schema, null, false, null, true, true, false, false);
|
||||
$this->checkException($schema, null, true, ValueException::class);
|
||||
|
||||
## Tester nullable
|
||||
$schema = new ScalarSchema("?rawstring");
|
||||
|
||||
$this->checkVerifix($schema, null, false, null, true, true, true, true);
|
||||
$this->checkVerifix($schema, null, true, null, true, true, true, true);
|
||||
|
||||
## Tester required
|
||||
$schema = new ScalarSchema(["rawstring", "required" => true]);
|
||||
|
||||
$this->checkVerifix($schema, false, false, null, true, false, false, false);
|
||||
$this->checkException($schema, false, true, ValueException::class);
|
||||
|
||||
## Tester allow_empty === false
|
||||
$inputParams = ["allow_empty" => false];
|
||||
$schema = new ScalarSchema("rawstring");
|
||||
|
||||
$this->checkVerifix($schema, null, false, null, true, true, false, false, $inputParams);
|
||||
$this->checkException($schema, null, true, ValueException::class, $inputParams);
|
||||
|
||||
$this->checkVerifix($schema, "", false, null, true, false, true, true, $inputParams);
|
||||
$this->checkVerifix($schema, "", true, null, true, false, true, true, $inputParams);
|
||||
|
||||
$schema = new ScalarSchema("?rawstring");
|
||||
|
||||
$this->checkVerifix($schema, null, false, null, true, true, true, true, $inputParams);
|
||||
$this->checkVerifix($schema, null, true, null, true, true, true, true, $inputParams);
|
||||
|
||||
$this->checkVerifix($schema, "", false, null, true, false, true, true, $inputParams);
|
||||
$this->checkVerifix($schema, "", true, null, true, false, true, true, $inputParams);
|
||||
}
|
||||
|
||||
function testString() {
|
||||
$schema = new ScalarSchema("string");
|
||||
|
||||
$this->checkVerifix($schema, false, false, null, true, false, true, true);
|
||||
$this->checkVerifix($schema, false, true, null, true, false, true, true);
|
||||
|
||||
$this->checkVerifix($schema, null, false, null, true, true, false, false);
|
||||
$this->checkException($schema, null, true, ValueException::class);
|
||||
|
||||
$this->checkVerifix($schema, "", false, "", true, true, true, true);
|
||||
$this->checkVerifix($schema, "", true, "", true, true, true, true);
|
||||
|
||||
$this->checkVerifix($schema, " ", false, "", true, true, true, false);
|
||||
$this->checkVerifix($schema, " ", true, "", true, true, true, false);
|
||||
|
||||
$this->checkVerifix($schema, "text", false, "text", true, true, true, true);
|
||||
$this->checkVerifix($schema, "text", true, "text", true, true, true, true);
|
||||
|
||||
$this->checkVerifix($schema, " text ", false, "text", true, true, true, false);
|
||||
$this->checkVerifix($schema, " text ", true, "text", true, true, true, false);
|
||||
|
||||
$this->checkVerifix($schema, true, false, true, true, true, true, false);
|
||||
$this->checkVerifix($schema, true, true, "1", true, true, true, false);
|
||||
|
||||
$this->checkVerifix($schema, 42, false, 42, true, true, true, false);
|
||||
$this->checkVerifix($schema, 42, true, "42", true, true, true, false);
|
||||
|
||||
$this->checkVerifix($schema, [], false, [], true, true, false, false);
|
||||
$this->checkException($schema, [], true, ValueException::class);
|
||||
|
||||
## Tester nullable
|
||||
$schema = new ScalarSchema("?string");
|
||||
|
||||
$this->checkVerifix($schema, null, false, null, true, true, true, true);
|
||||
$this->checkVerifix($schema, null, true, null, true, true, true, true);
|
||||
|
||||
## Tester required
|
||||
$schema = new ScalarSchema(["string", "required" => true]);
|
||||
|
||||
$this->checkVerifix($schema, false, false, null, true, false, false, false);
|
||||
$this->checkException($schema, false, true, ValueException::class);
|
||||
|
||||
## Tester allow_empty === false
|
||||
$inputParams = ["allow_empty" => false];
|
||||
$schema = new ScalarSchema("string");
|
||||
|
||||
$this->checkVerifix($schema, null, false, null, true, true, false, false, $inputParams);
|
||||
$this->checkException($schema, null, true, ValueException::class, $inputParams);
|
||||
|
||||
$this->checkVerifix($schema, "", false, null, true, false, true, true, $inputParams);
|
||||
$this->checkVerifix($schema, "", true, null, true, false, true, true, $inputParams);
|
||||
|
||||
$schema = new ScalarSchema("?string");
|
||||
|
||||
$this->checkVerifix($schema, null, false, null, true, true, true, true, $inputParams);
|
||||
$this->checkVerifix($schema, null, true, null, true, true, true, true, $inputParams);
|
||||
|
||||
$this->checkVerifix($schema, "", false, null, true, false, true, true, $inputParams);
|
||||
$this->checkVerifix($schema, "", true, null, true, false, true, true, $inputParams);
|
||||
}
|
||||
|
||||
function testInt() {
|
||||
$schema = new ScalarSchema("int");
|
||||
|
||||
$this->checkVerifix($schema, false, false, null, true, false, true, true);
|
||||
$this->checkVerifix($schema, false, true, null, true, false, true, true);
|
||||
|
||||
$this->checkVerifix($schema, null, false, null, true, true, false, false);
|
||||
$this->checkException($schema, null, true, ValueException::class);
|
||||
|
||||
$this->checkVerifix($schema, 42, false, 42, true, true, true, true);
|
||||
$this->checkVerifix($schema, 42, true, 42, true, true, true, true);
|
||||
|
||||
$this->checkVerifix($schema, "42", false, "42", true, true, true, false);
|
||||
$this->checkVerifix($schema, "42", true, 42, true, true, true, false);
|
||||
|
||||
$this->checkVerifix($schema, "42.5", false, "42.5", true, true, true, false);
|
||||
$this->checkVerifix($schema, "42.5", true, 42, true, true, true, false);
|
||||
|
||||
$this->checkVerifix($schema, "42,5", false, "42,5", true, true, true, false);
|
||||
$this->checkVerifix($schema, "42,5", true, 42, true, true, true, false);
|
||||
|
||||
$this->checkVerifix($schema, " 42 ", false, "42", true, true, true, false);
|
||||
$this->checkVerifix($schema, " 42 ", true, 42, true, true, true, false);
|
||||
|
||||
$this->checkVerifix($schema, "", false, "", true, true, false, false);
|
||||
$this->checkException($schema, "", true, ValueException::class);
|
||||
|
||||
$this->checkVerifix($schema, " ", false, " ", true, true, false, false);
|
||||
$this->checkException($schema, " ", true, ValueException::class);
|
||||
|
||||
$this->checkVerifix($schema, "text", false, "text", true, true, false, false);
|
||||
$this->checkException($schema, "text", true, ValueException::class);
|
||||
|
||||
$this->checkVerifix($schema, true, false, true, true, true, true, false);
|
||||
$this->checkVerifix($schema, true, true, 1, true, true, true, false);
|
||||
|
||||
$this->checkVerifix($schema, [], false, [], true, true, false, false);
|
||||
$this->checkException($schema, [], true, ValueException::class);
|
||||
|
||||
## Tester nullable
|
||||
$schema = new ScalarSchema("?int");
|
||||
|
||||
$this->checkVerifix($schema, null, false, null, true, true, true, true);
|
||||
$this->checkVerifix($schema, null, true, null, true, true, true, true);
|
||||
|
||||
## Tester required
|
||||
$schema = new ScalarSchema(["int", "required" => true]);
|
||||
|
||||
$this->checkVerifix($schema, false, false, null, true, false, false, false);
|
||||
$this->checkException($schema, false, true, ValueException::class);
|
||||
|
||||
## Tester allow_empty === false
|
||||
$inputParams = ["allow_empty" => false];
|
||||
$schema = new ScalarSchema("int");
|
||||
|
||||
$this->checkVerifix($schema, null, false, null, true, true, false, false, $inputParams);
|
||||
$this->checkException($schema, null, true, ValueException::class, $inputParams);
|
||||
|
||||
$this->checkVerifix($schema, "", false, null, true, false, true, true, $inputParams);
|
||||
$this->checkVerifix($schema, "", true, null, true, false, true, true, $inputParams);
|
||||
|
||||
$schema = new ScalarSchema("?int");
|
||||
|
||||
$this->checkVerifix($schema, null, false, null, true, true, true, true, $inputParams);
|
||||
$this->checkVerifix($schema, null, true, null, true, true, true, true, $inputParams);
|
||||
|
||||
$this->checkVerifix($schema, "", false, null, true, false, true, true, $inputParams);
|
||||
$this->checkVerifix($schema, "", true, null, true, false, true, true, $inputParams);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user