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