Файл: vendor/symfony/var-exporter/LazyGhostTrait.php
Строк: 398
<?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 SymfonyComponentVarExporter;
use SymfonyComponentSerializerAttributeIgnore;
use SymfonyComponentVarExporterInternalHydrator;
use SymfonyComponentVarExporterInternalLazyObjectRegistry as Registry;
use SymfonyComponentVarExporterInternalLazyObjectState;
use SymfonyComponentVarExporterInternalLazyObjectTrait;
trait LazyGhostTrait
{
use LazyObjectTrait;
/**
* Creates a lazy-loading ghost instance.
*
* Skipped properties should be indexed by their array-cast identifier, see
* https://php.net/manual/language.types.array#language.types.array.casting
*
* @param (Closure(static):void $initializer The closure should initialize the object it receives as argument
* @param array<string, true>|null $skippedProperties An array indexed by the properties to skip, a.k.a. the ones
* that the initializer doesn't initialize, if any
* @param static|null $instance
*/
public static function createLazyGhost(Closure|array $initializer, ?array $skippedProperties = null, ?object $instance = null): static
{
if (is_array($initializer)) {
trigger_deprecation('symfony/var-exporter', '6.4', 'Per-property lazy-initializers are deprecated and won't be supported anymore in 7.0, use an object initializer instead.');
}
$onlyProperties = null === $skippedProperties && is_array($initializer) ? $initializer : null;
if (self::class !== $class = $instance ? $instance::class : static::class) {
$skippedProperties[" ".self::class." lazyObjectState"] = true;
} elseif (defined($class.'::LAZY_OBJECT_PROPERTY_SCOPES')) {
Hydrator::$propertyScopes[$class] ??= $class::LAZY_OBJECT_PROPERTY_SCOPES;
}
$instance ??= (Registry::$classReflectors[$class] ??= new ReflectionClass($class))->newInstanceWithoutConstructor();
Registry::$defaultProperties[$class] ??= (array) $instance;
$instance->lazyObjectState = new LazyObjectState($initializer, $skippedProperties ??= []);
foreach (Registry::$classResetters[$class] ??= Registry::getClassResetters($class) as $reset) {
$reset($instance, $skippedProperties, $onlyProperties);
}
return $instance;
}
/**
* Returns whether the object is initialized.
*
* @param $partial Whether partially initialized objects should be considered as initialized
*/
#[Ignore]
public function isLazyObjectInitialized(bool $partial = false): bool
{
if (!$state = $this->lazyObjectState ?? null) {
return true;
}
if (!is_array($state->initializer)) {
return LazyObjectState::STATUS_INITIALIZED_FULL === $state->status;
}
$class = $this::class;
$properties = (array) $this;
if ($partial) {
return (bool) array_intersect_key($state->initializer, $properties);
}
$propertyScopes = Hydrator::$propertyScopes[$class] ??= Hydrator::getPropertyScopes($class);
foreach ($state->initializer as $key => $initializer) {
if (!array_key_exists($key, $properties) && isset($propertyScopes[$key])) {
return false;
}
}
return true;
}
/**
* Forces initialization of a lazy object and returns it.
*/
public function initializeLazyObject(): static
{
if (!$state = $this->lazyObjectState ?? null) {
return $this;
}
if (!is_array($state->initializer)) {
if (LazyObjectState::STATUS_UNINITIALIZED_FULL === $state->status) {
$state->initialize($this, '', null);
}
return $this;
}
$values = isset($state->initializer[" "]) ? null : [];
$class = $this::class;
$properties = (array) $this;
$propertyScopes = Hydrator::$propertyScopes[$class] ??= Hydrator::getPropertyScopes($class);
foreach ($state->initializer as $key => $initializer) {
if (array_key_exists($key, $properties) || ![$scope, $name, $readonlyScope] = $propertyScopes[$key] ?? null) {
continue;
}
$scope = $readonlyScope ?? ('*' !== $scope ? $scope : $class);
if (null === $values) {
if (!is_array($values = ($state->initializer[" "])($this, Registry::$defaultProperties[$class]))) {
throw new TypeError(sprintf('The lazy-initializer defined for instance of "%s" must return an array, got "%s".', $class, get_debug_type($values)));
}
if (array_key_exists($key, $properties = (array) $this)) {
continue;
}
}
if (array_key_exists($key, $values)) {
$accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope);
$accessor['set']($this, $name, $properties[$key] = $values[$key]);
} else {
$state->initialize($this, $name, $scope);
$properties = (array) $this;
}
}
return $this;
}
/**
* @return bool Returns false when the object cannot be reset, ie when it's not a lazy object
*/
public function resetLazyObject(): bool
{
if (!$state = $this->lazyObjectState ?? null) {
return false;
}
if (LazyObjectState::STATUS_UNINITIALIZED_FULL !== $state->status) {
$state->reset($this);
}
return true;
}
public function &__get($name): mixed
{
$propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class);
$scope = null;
if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) {
$scope = Registry::getScope($propertyScopes, $class, $name);
$state = $this->lazyObjectState ?? null;
if ($state && (null === $scope || isset($propertyScopes[" $scope