| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 | <?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 Symfony\Component\VarExporter\Internal;use Symfony\Component\VarExporter\Hydrator as PublicHydrator;/** * Keeps the state of lazy objects. * * As a micro-optimization, this class uses no type declarations. * * @internal */class LazyObjectState{    public const STATUS_UNINITIALIZED_FULL = 1;    public const STATUS_UNINITIALIZED_PARTIAL = 2;    public const STATUS_INITIALIZED_FULL = 3;    public const STATUS_INITIALIZED_PARTIAL = 4;    /**     * @var array<string, true>     */    public readonly array $skippedProperties;    /**     * @var self::STATUS_*     */    public int $status = 0;    public object $realInstance;    public function __construct(public readonly \Closure|array $initializer, $skippedProperties = [])    {        $this->skippedProperties = $skippedProperties;        $this->status = \is_array($initializer) ? self::STATUS_UNINITIALIZED_PARTIAL : self::STATUS_UNINITIALIZED_FULL;    }    public function initialize($instance, $propertyName, $propertyScope)    {        if (self::STATUS_INITIALIZED_FULL === $this->status) {            return self::STATUS_INITIALIZED_FULL;        }        if (\is_array($this->initializer)) {            $class = $instance::class;            $propertyScope ??= $class;            $propertyScopes = Hydrator::$propertyScopes[$class];            $propertyScopes[$k = "\0$propertyScope\0$propertyName"] ?? $propertyScopes[$k = "\0*\0$propertyName"] ?? $k = $propertyName;            if ($initializer = $this->initializer[$k] ?? null) {                $value = $initializer(...[$instance, $propertyName, $propertyScope, LazyObjectRegistry::$defaultProperties[$class][$k] ?? null]);                $accessor = LazyObjectRegistry::$classAccessors[$propertyScope] ??= LazyObjectRegistry::getClassAccessors($propertyScope);                $accessor['set']($instance, $propertyName, $value);                return $this->status = self::STATUS_INITIALIZED_PARTIAL;            }            $status = self::STATUS_UNINITIALIZED_PARTIAL;            if ($initializer = $this->initializer["\0"] ?? null) {                if (!\is_array($values = $initializer($instance, LazyObjectRegistry::$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)));                }                $properties = (array) $instance;                foreach ($values as $key => $value) {                    if ($k === $key) {                        $status = self::STATUS_INITIALIZED_PARTIAL;                    }                    if (!\array_key_exists($key, $properties) && [$scope, $name, $readonlyScope] = $propertyScopes[$key] ?? null) {                        $scope = $readonlyScope ?? ('*' !== $scope ? $scope : $class);                        $accessor = LazyObjectRegistry::$classAccessors[$scope] ??= LazyObjectRegistry::getClassAccessors($scope);                        $accessor['set']($instance, $name, $value);                    }                }            }            return $status;        }        $this->status = self::STATUS_INITIALIZED_FULL;        try {            if ($defaultProperties = array_diff_key(LazyObjectRegistry::$defaultProperties[$instance::class], $this->skippedProperties)) {                PublicHydrator::hydrate($instance, $defaultProperties);            }            ($this->initializer)($instance);        } catch (\Throwable $e) {            $this->status = self::STATUS_UNINITIALIZED_FULL;            $this->reset($instance);            throw $e;        }        return self::STATUS_INITIALIZED_FULL;    }    public function reset($instance): void    {        $class = $instance::class;        $propertyScopes = Hydrator::$propertyScopes[$class] ??= Hydrator::getPropertyScopes($class);        $skippedProperties = $this->skippedProperties;        $properties = (array) $instance;        $onlyProperties = \is_array($this->initializer) ? $this->initializer : null;        foreach ($propertyScopes as $key => [$scope, $name, $readonlyScope]) {            $propertyScopes[$k = "\0$scope\0$name"] ?? $propertyScopes[$k = "\0*\0$name"] ?? $k = $name;            if ($k === $key && (null !== $readonlyScope || !\array_key_exists($k, $properties))) {                $skippedProperties[$k] = true;            }        }        foreach (LazyObjectRegistry::$classResetters[$class] as $reset) {            $reset($instance, $skippedProperties, $onlyProperties);        }        $this->status = self::STATUS_INITIALIZED_FULL === $this->status ? self::STATUS_UNINITIALIZED_FULL : self::STATUS_UNINITIALIZED_PARTIAL;    }}
 |