Вход Регистрация
Файл: vendor/nette/schema/src/Schema/Elements/Structure.php
Строк: 142
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

declare(strict_types=1);

namespace 
NetteSchemaElements;

use 
Nette;
use 
NetteSchemaContext;
use 
NetteSchemaHelpers;
use 
NetteSchemaSchema;


final class 
Structure implements Schema
{
    use 
Base;

    
/** @var Schema[] */
    
private array $items;

    
/** for array|list */
    
private ?Schema $otherItems null;

    
/** @var array{?int, ?int} */
    
private array $range = [nullnull];
    private 
bool $skipDefaults false;


    
/**
     * @param  Schema[]  $shape
     */
    
public function __construct(array $shape)
    {
        (function (
Schema ...$items) {})(...array_values($shape));
        
$this->items $shape;
        
$this->castTo('object');
        
$this->required true;
    }


    public function default(
mixed $value): self
    
{
        throw new 
NetteInvalidStateException('Structure cannot have default value.');
    }


    public function 
min(?int $min): self
    
{
        
$this->range[0] = $min;
        return 
$this;
    }


    public function 
max(?int $max): self
    
{
        
$this->range[1] = $max;
        return 
$this;
    }


    public function 
otherItems(string|Schema $type 'mixed'): self
    
{
        
$this->otherItems $type instanceof Schema $type : new Type($type);
        return 
$this;
    }


    public function 
skipDefaults(bool $state true): self
    
{
        
$this->skipDefaults $state;
        return 
$this;
    }


    public function 
extend(array|self $shape): self
    
{
        
$shape $shape instanceof self $shape->items $shape;
        return new 
self(array_merge($this->items$shape));
    }


    public function 
getShape(): array
    {
        return 
$this->items;
    }


    
/********************* processing ****************d*g**/


    
public function normalize(mixed $valueContext $context): mixed
    
{
        if (
$prevent = (is_array($value) && isset($value[Helpers::PreventMerging]))) {
            unset(
$value[Helpers::PreventMerging]);
        }

        
$value $this->doNormalize($value$context);
        if (
is_object($value)) {
            
$value = (array) $value;
        }

        if (
is_array($value)) {
            foreach (
$value as $key => $val) {
                
$itemSchema $this->items[$key] ?? $this->otherItems;
                if (
$itemSchema) {
                    
$context->path[] = $key;
                    
$value[$key] = $itemSchema->normalize($val$context);
                    
array_pop($context->path);
                }
            }

            if (
$prevent) {
                
$value[Helpers::PreventMerging] = true;
            }
        }

        return 
$value;
    }


    public function 
merge(mixed $valuemixed $base): mixed
    
{
        if (
is_array($value) && isset($value[Helpers::PreventMerging])) {
            unset(
$value[Helpers::PreventMerging]);
            
$base null;
        }

        if (
is_array($value) && is_array($base)) {
            
$index $this->otherItems === null null 0;
            foreach (
$value as $key => $val) {
                if (
$key === $index) {
                    
$base[] = $val;
                    
$index++;
                } else {
                    
$base[$key] = array_key_exists($key$base) && ($itemSchema $this->items[$key] ?? $this->otherItems)
                        ? 
$itemSchema->merge($val$base[$key])
                        : 
$val;
                }
            }

            return 
$base;
        }

        return 
$value ?? $base;
    }


    public function 
complete(mixed $valueContext $context): mixed
    
{
        if (
$value === null) {
            
$value = []; // is unable to distinguish null from array in NEON
        
}

        
$this->doDeprecation($context);

        
$isOk $context->createChecker();
        
Helpers::validateType($value'array'$context);
        
$isOk() && Helpers::validateRange($value$this->range$context);
        
$isOk() && $this->validateItems($value$context);
        
$isOk() && $value $this->doTransform($value$context);
        return 
$isOk() ? $value null;
    }


    private function 
validateItems(array &$valueContext $context): void
    
{
        
$items $this->items;
        if (
$extraKeys array_keys(array_diff_key($value$items))) {
            if (
$this->otherItems) {
                
$items += array_fill_keys($extraKeys$this->otherItems);
            } else {
                
$keys array_map('strval'array_keys($items));
                foreach (
$extraKeys as $key) {
                    
$hint NetteUtilsHelpers::getSuggestion($keys, (string) $key);
                    
$context->addError(
                        
'Unexpected item %path%' . ($hint ", did you mean '%hint%'?" '.'),
                        
NetteSchemaMessage::UnexpectedItem,
                        [
'hint' => $hint],
                    )->
path[] = $key;
                }
            }
        }

        foreach (
$items as $itemKey => $itemVal) {
            
$context->path[] = $itemKey;
            if (
array_key_exists($itemKey$value)) {
                
$value[$itemKey] = $itemVal->complete($value[$itemKey], $context);
            } else {
                
$default $itemVal->completeDefault($context); // checks required item
                
if (!$context->skipDefaults && !$this->skipDefaults) {
                    
$value[$itemKey] = $default;
                }
            }

            
array_pop($context->path);
        }
    }


    public function 
completeDefault(Context $context): mixed
    
{
        return 
$this->required
            
$this->complete([], $context)
            : 
null;
    }
}
Онлайн: 0
Реклама