nur-ture/src/schema/_assoc/AssocWrapper.php

145 lines
4.6 KiB
PHP

<?php
namespace nur\sery\wip\schema\_assoc;
use nulib\ValueException;
use nur\sery\wip\schema\_scalar\ScalarResult;
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 nur\sery\wip\schema\WrapperContext;
class AssocWrapper extends Wrapper {
function __construct(AssocSchema $schema, &$value=null, $valueKey=null, ?array $params=null) {
$keys = $schema->getKeys();
$keyTypes = [];
$keyWrappers = [];
foreach ($keys as $key) {
$keyTypes[$key] = null;
$keyWrappers[$key] = $schema->getSchema($key)->getWrapper();
}
$this->context = $context = new AssocWrapperContext($schema, null, null, $params);
$context->arrayResult = new ScalarResult();
$context->keys = $keys;
$context->keyTypes = $keyTypes;
$context->keyWrappers = $keyWrappers;
$context->result = $context->arrayResult;
# calculer manuellemet throw ici parce que WrapperContext le met à true par
# défaut. on veut pouvoir mettre temporairement throw à false si jamais il
# n'est pas spécifié par l'utilisateur
$throw = $params["throw"] ?? null;
# Si $value est null, ne pas lancer d'exception, parce qu'on considère que
# c'est une initialisation sans conséquences
if ($throw === null && $value !== null) $throw = true;
$context->throw = $throw ?? false;
$this->reset($value, $valueKey);
$context->throw = $throw ?? true;
}
function isAssoc(?AssocWrapper &$wrapper=null): bool { $wrapper = $this; return true; }
/** @var AssocWrapperContext */
protected WrapperContext $context;
protected function resetContext($resetSelectedKey): void {
$context = $this->context;
$context->arrayResult->reset();
foreach ($context->keyWrappers as $wrapper) {
$wrapper->getResult()->reset();
}
$context->analyzed = false;
$context->normalized = false;
if ($resetSelectedKey) {
$context->selectedKey = null;
$context->type = $context->arrayType;
$context->result = $context->arrayResult;
}
}
function getKeys(): array {
return $this->context->keys;
}
protected function _getWrapper($key): Wrapper {
$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 {
$context = $this->context;
if ($key === null) {
$context->selectedKey = null;
$context->type = $context->arrayType;
$context->result = $context->arrayResult;
return $this;
}
$wrapper = $this->_getWrapper($key);
$context->selectedKey = $key;
$context->type = $wrapper->getType();
$context->result = $wrapper->getResult();
return $wrapper;
}
protected function _analyze(?array $params): int {
return -1;
}
protected function _normalize(?array $params): bool {
return false;
}
function getResult($key=false): Result {
if ($key === false) return $this->context->result;
elseif ($key === null) return $this->context->arrayResult;
else return $this->_getWrapper($key)->getResult();
}
function getType($key=false): IType {
if ($key === false) return $this->context->type;
elseif ($key === null) return $this->context->arrayType;
else return $this->_getWrapper($key)->getType();
}
function get($default=null, $key=false) {
$context = $this->context;
if (!$context->arrayResult->available) return $default;
if ($key === false) $key = $context->selectedKey;
if ($key === null) return $context->input->get($context->valueKey);
else return $this->_getWrapper($key)->get($default);
}
function set($value, ?array $params=null, $key=false): Wrapper {
$context = $this->context;
if ($key === false) $key = $context->selectedKey;
if ($key === null) {
$context->input->set($value, $context->valueKey);
$this->afterModify($params);
} else {
$this->_getWrapper($key)->set($value);
}
return $this;
}
function unset(?array $params=null, $key=false): Wrapper {
$context = $this->context;
if ($key === false) $key = $context->selectedKey;
if ($key === null) {
$context->input->unset($context->valueKey);
$this->afterModify($params);
} else {
$this->_getWrapper($key)->unset();
}
return $this;
}
function format($format=null, $key=false): string {
$context = $this->context;
if ($key === false) $key = $context->selectedKey;
if ($key === null) return $this->_format($context, $format);
else return $this->_getWrapper($key)->format($format);
}
}