Файл: vendor/symfony/var-dumper/Cloner/Data.php
Строк: 347
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SymfonyComponentVarDumperCloner;
use SymfonyComponentVarDumperCasterCaster;
use SymfonyComponentVarDumperDumperContextProviderSourceContextProvider;
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
class Data implements ArrayAccess, Countable, IteratorAggregate, Stringable
{
private array $data;
private int $position = 0;
private int|string $key = 0;
private int $maxDepth = 20;
private int $maxItemsPerDepth = -1;
private int $useRefHandles = -1;
private array $context = [];
/**
* @param array $data An array as returned by ClonerInterface::cloneVar()
*/
public function __construct(array $data)
{
$this->data = $data;
}
public function getType(): ?string
{
$item = $this->data[$this->position][$this->key];
if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) {
$item = $item->value;
}
if (!$item instanceof Stub) {
return gettype($item);
}
if (Stub::TYPE_STRING === $item->type) {
return 'string';
}
if (Stub::TYPE_ARRAY === $item->type) {
return 'array';
}
if (Stub::TYPE_OBJECT === $item->type) {
return $item->class;
}
if (Stub::TYPE_RESOURCE === $item->type) {
return $item->class.' resource';
}
return null;
}
/**
* Returns a native representation of the original value.
*
* @param array|bool $recursive Whether values should be resolved recursively or not
*
* @return string|int|float|bool|array|Data[]|null
*/
public function getValue(array|bool $recursive = false): string|int|float|bool|array|null
{
$item = $this->data[$this->position][$this->key];
if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) {
$item = $item->value;
}
if (!($item = $this->getStub($item)) instanceof Stub) {
return $item;
}
if (Stub::TYPE_STRING === $item->type) {
return $item->value;
}
$children = $item->position ? $this->data[$item->position] : [];
foreach ($children as $k => $v) {
if ($recursive && !($v = $this->getStub($v)) instanceof Stub) {
continue;
}
$children[$k] = clone $this;
$children[$k]->key = $k;
$children[$k]->position = $item->position;
if ($recursive) {
if (Stub::TYPE_REF === $v->type && ($v = $this->getStub($v->value)) instanceof Stub) {
$recursive = (array) $recursive;
if (isset($recursive[$v->position])) {
continue;
}
$recursive[$v->position] = true;
}
$children[$k] = $children[$k]->getValue($recursive);
}
}
return $children;
}
public function count(): int
{
return count($this->getValue());
}
public function getIterator(): Traversable
{
if (!is_array($value = $this->getValue())) {
throw new LogicException(sprintf('"%s" object holds non-iterable type "%s".', self::class, get_debug_type($value)));
}
yield from $value;
}
/**
* @return mixed
*/
public function __get(string $key)
{
if (null !== $data = $this->seek($key)) {
$item = $this->getStub($data->data[$data->position][$data->key]);
return $item instanceof Stub || [] === $item ? $data : $item;
}
return null;
}
public function __isset(string $key): bool
{
return null !== $this->seek($key);
}
public function offsetExists(mixed $key): bool
{
return $this->__isset($key);
}
public function offsetGet(mixed $key): mixed
{
return $this->__get($key);
}
public function offsetSet(mixed $key, mixed $value): void
{
throw new BadMethodCallException(self::class.' objects are immutable.');
}
public function offsetUnset(mixed $key): void
{
throw new BadMethodCallException(self::class.' objects are immutable.');
}
public function __toString(): string
{
$value = $this->getValue();
if (!is_array($value)) {
return (string) $value;
}
return sprintf('%s (count=%d)', $this->getType(), count($value));
}
/**
* Returns a depth limited clone of $this.
*/
public function withMaxDepth(int $maxDepth): static
{
$data = clone $this;
$data->maxDepth = $maxDepth;
return $data;
}
/**
* Limits the number of elements per depth level.
*/
public function withMaxItemsPerDepth(int $maxItemsPerDepth): static
{
$data = clone $this;
$data->maxItemsPerDepth = $maxItemsPerDepth;
return $data;
}
/**
* Enables/disables objects' identifiers tracking.
*
* @param bool $useRefHandles False to hide global ref. handles
*/
public function withRefHandles(bool $useRefHandles): static
{
$data = clone $this;
$data->useRefHandles = $useRefHandles ? -1 : 0;
return $data;
}
public function withContext(array $context): static
{
$data = clone $this;
$data->context = $context;
return $data;
}
public function getContext(): array
{
return $this->context;
}
/**
* Seeks to a specific key in nested data structures.
*/
public function seek(string|int $key): ?static
{
$item = $this->data[$this->position][$this->key];
if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) {
$item = $item->value;
}
if (!($item = $this->getStub($item)) instanceof Stub || !$item->position) {
return null;
}
$keys = [$key];
switch ($item->type) {
case Stub::TYPE_OBJECT:
$keys[] = Caster::PREFIX_DYNAMIC.$key;
$keys[] = Caster::PREFIX_PROTECTED.$key;
$keys[] = Caster::PREFIX_VIRTUAL.$key;
$keys[] = " $item->class