207 lines
6.6 KiB
PHP
207 lines
6.6 KiB
PHP
<?php
|
|
namespace nulib\schema\_assoc;
|
|
|
|
use nulib\cl;
|
|
use nulib\ref\schema\ref_analyze;
|
|
use nulib\schema\_scalar\ScalarWrapper;
|
|
use nulib\schema\ConsolidatedResult;
|
|
use nulib\schema\input\Input;
|
|
use nulib\schema\Result;
|
|
use nulib\schema\types\IType;
|
|
use nulib\schema\Wrapper;
|
|
use nulib\schema\WrapperContext;
|
|
use nulib\ValueException;
|
|
|
|
class AssocWrapper extends Wrapper {
|
|
function __construct(AssocSchema $schema, &$value=null, $valueKey=null, ?array $params=null) {
|
|
$this->context = $context = new AssocWrapperContext($schema, null, null, $params);
|
|
$paramsNoThrow = cl::merge($params, [
|
|
"throw" => false,
|
|
]);
|
|
|
|
$keys = $schema->getKeys();
|
|
$keyWrappers = [];
|
|
foreach ($keys as $key) {
|
|
$keyDummy = null;
|
|
$keyWrappers[$key] = $schema->getSchema($key)->getWrapper($keyDummy, null, $paramsNoThrow);
|
|
}
|
|
$context->keys = $keys;
|
|
$context->keyWrappers = $keyWrappers;
|
|
|
|
$arrayDummy = null;
|
|
$context->arrayWrapper = new ScalarWrapper($schema, $arrayDummy, null, $paramsNoThrow, $context);
|
|
|
|
$context->consolidatedResult = new ConsolidatedResult();
|
|
|
|
if ($value !== null) {
|
|
# n'initialiser que si $value n'est pas null
|
|
$this->reset($value, $valueKey);
|
|
}
|
|
}
|
|
|
|
/** @var AssocWrapperContext */
|
|
protected WrapperContext $context;
|
|
|
|
protected function resetContext(bool $resetSelectedKey): void {
|
|
parent::resetContext($resetSelectedKey);
|
|
$context = $this->context;
|
|
$context->arrayWrapper->getResult()->reset();
|
|
foreach ($context->keyWrappers as $wrapper) {
|
|
$wrapper->getResult()->reset();
|
|
}
|
|
if ($resetSelectedKey) $context->selectedKey = null;
|
|
}
|
|
|
|
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->context->keys;
|
|
}
|
|
|
|
protected function _getWrapper($key): Wrapper {
|
|
$context = $this->context;
|
|
if ($key === null || $key === "") return $context->arrayWrapper;
|
|
$wrapper = $context->keyWrappers[$key] ?? null;
|
|
if ($wrapper === null) throw ValueException::invalid_key($key);
|
|
return $wrapper;
|
|
}
|
|
|
|
/** @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);
|
|
}
|
|
|
|
if ($params["ensure_assoc"] ?? $context->ensureAssoc) {
|
|
$context->input->ensureAssoc($context->schema->getKeys());
|
|
}
|
|
|
|
$what = ScalarWrapper::_analyze($context, $wrapper, $params);
|
|
if (!$context->result->valid) return $what;
|
|
|
|
$result = $context->consolidatedResult;
|
|
$result->setValid();
|
|
foreach ($context->keyWrappers as $key => $keyWrapper) {
|
|
$keyWrapper->analyze($params);
|
|
if ($keyWrapper->isValid()) continue;
|
|
$what = ref_analyze::INVALID;
|
|
#XXX pour $prefix, utiliser si possible la description ou une autre valeur
|
|
# "user-friendly". possibilité de sélectionner la valeur à utiliser avec
|
|
# $params?
|
|
$prefix = $key;
|
|
if (!$keyWrapper->isPresent()) {
|
|
$result->addMissingMessage($keyWrapper, $prefix);
|
|
} elseif (!$keyWrapper->isAvailable()) {
|
|
$result->addUnavailableMessage($keyWrapper, $prefix);
|
|
} elseif ($keyWrapper->isNull()) {
|
|
$result->addNullMessage($keyWrapper, $prefix);
|
|
} else {
|
|
$result->addInvalidMessage($keyWrapper, $prefix);
|
|
}
|
|
}
|
|
|
|
return $what;
|
|
}
|
|
|
|
/**
|
|
* @param AssocWrapperContext $context
|
|
* @param AssocWrapper $wrapper
|
|
*/
|
|
static function _normalize(WrapperContext $context, Wrapper $wrapper, ?array $params): bool {
|
|
$schema = $context->schema;
|
|
$keys = $schema->getKeys();
|
|
|
|
$defaults = [];
|
|
$missings = null;
|
|
foreach ($keys as $key) {
|
|
$type = $wrapper->getType($key);
|
|
$default = $schema->getSchema($key)->default;
|
|
if ($default === null) $default = $type->getNullValue();
|
|
$defaults[$key] = $default;
|
|
$missing = $type->getMissingValue($valid);
|
|
if ($valid) $missings[$key] = $missing;
|
|
}
|
|
if ($params["ensure_keys"] ?? $context->ensureKeys) {
|
|
$context->input->ensureKeys($defaults, $missings, $params);
|
|
} else {
|
|
$context->input->deleteMissings($missings, $params);
|
|
}
|
|
|
|
if ($params["ensure_order"] ?? $context->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;
|
|
}
|
|
|
|
protected function getConsolidatedResult(): Result {
|
|
return $this->context->consolidatedResult;
|
|
}
|
|
|
|
function getResult($key=false): Result {
|
|
if ($key === null) return $this->getConsolidatedResult();
|
|
if ($key === false) $key = $this->context->selectedKey;
|
|
return $this->_getWrapper($key)->getResult();
|
|
}
|
|
|
|
function getType($key=false): IType {
|
|
if ($key === false) $key = $this->context->selectedKey;
|
|
return $this->_getWrapper($key)->getType();
|
|
}
|
|
|
|
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 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(?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, $key=false): string {
|
|
$context = $this->context;
|
|
if ($key === false) $key = $context->selectedKey;
|
|
return $this->_getWrapper($key)->format($format);
|
|
}
|
|
}
|