Buckets:
| /** | |
| * This file is part of the Nette Framework (https://nette.org) | |
| * Copyright (c) 2004 David Grudl (https://davidgrudl.com) | |
| */ | |
| declare(strict_types=1); | |
| namespace Nette\Schema\Elements; | |
| use Nette; | |
| use Nette\Schema\Context; | |
| use Nette\Schema\Helpers; | |
| use Nette\Schema\Schema; | |
| 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 = [null, null]; | |
| 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 Nette\InvalidStateException('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 $value, Context $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 $value, mixed $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 $value, Context $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 &$value, Context $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 = Nette\Utils\Helpers::getSuggestion($keys, (string) $key); | |
| $context->addError( | |
| 'Unexpected item %path%' . ($hint ? ", did you mean '%hint%'?" : '.'), | |
| Nette\Schema\Message::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; | |
| } | |
| } | |
Xet Storage Details
- Size:
- 4.69 kB
- Xet hash:
- 48ce6f99fa714b7af6e8ca64efd4431745f9b0680883c375b9b31a7e1b902172
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.