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); } }