vendor/symfony/var-exporter/Internal/LazyObjectState.php line 46

  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\VarExporter\Internal;
  11. use Symfony\Component\VarExporter\Hydrator as PublicHydrator;
  12. /**
  13.  * Keeps the state of lazy objects.
  14.  *
  15.  * As a micro-optimization, this class uses no type declarations.
  16.  *
  17.  * @internal
  18.  */
  19. class LazyObjectState
  20. {
  21.     public const STATUS_UNINITIALIZED_FULL 1;
  22.     public const STATUS_UNINITIALIZED_PARTIAL 2;
  23.     public const STATUS_INITIALIZED_FULL 3;
  24.     public const STATUS_INITIALIZED_PARTIAL 4;
  25.     /**
  26.      * @var array<string, true>
  27.      */
  28.     public readonly array $skippedProperties;
  29.     /**
  30.      * @var self::STATUS_*
  31.      */
  32.     public int $status 0;
  33.     public function __construct(public readonly \Closure|array $initializer$skippedProperties = [])
  34.     {
  35.         $this->skippedProperties $skippedProperties;
  36.         $this->status \is_array($initializer) ? self::STATUS_UNINITIALIZED_PARTIAL self::STATUS_UNINITIALIZED_FULL;
  37.     }
  38.     public function initialize($instance$propertyName$propertyScope)
  39.     {
  40.         if (self::STATUS_INITIALIZED_FULL === $this->status) {
  41.             return self::STATUS_INITIALIZED_FULL;
  42.         }
  43.         if (\is_array($this->initializer)) {
  44.             $class $instance::class;
  45.             $propertyScope ??= $class;
  46.             $propertyScopes Hydrator::$propertyScopes[$class];
  47.             $propertyScopes[$k "\0$propertyScope\0$propertyName"] ?? $propertyScopes[$k "\0*\0$propertyName"] ?? $k $propertyName;
  48.             if ($initializer $this->initializer[$k] ?? null) {
  49.                 $value $initializer(...[$instance$propertyName$propertyScopeLazyObjectRegistry::$defaultProperties[$class][$k] ?? null]);
  50.                 $accessor LazyObjectRegistry::$classAccessors[$propertyScope] ??= LazyObjectRegistry::getClassAccessors($propertyScope);
  51.                 $accessor['set']($instance$propertyName$value);
  52.                 return $this->status self::STATUS_INITIALIZED_PARTIAL;
  53.             }
  54.             $status self::STATUS_UNINITIALIZED_PARTIAL;
  55.             if ($initializer $this->initializer["\0"] ?? null) {
  56.                 if (!\is_array($values $initializer($instanceLazyObjectRegistry::$defaultProperties[$class]))) {
  57.                     throw new \TypeError(sprintf('The lazy-initializer defined for instance of "%s" must return an array, got "%s".'$classget_debug_type($values)));
  58.                 }
  59.                 $properties = (array) $instance;
  60.                 foreach ($values as $key => $value) {
  61.                     if ($k === $key) {
  62.                         $status self::STATUS_INITIALIZED_PARTIAL;
  63.                     }
  64.                     if (!\array_key_exists($key$properties) && [$scope$name$readonlyScope] = $propertyScopes[$key] ?? null) {
  65.                         $scope $readonlyScope ?? ('*' !== $scope $scope $class);
  66.                         $accessor LazyObjectRegistry::$classAccessors[$scope] ??= LazyObjectRegistry::getClassAccessors($scope);
  67.                         $accessor['set']($instance$name$value);
  68.                     }
  69.                 }
  70.             }
  71.             return $status;
  72.         }
  73.         $this->status self::STATUS_INITIALIZED_FULL;
  74.         try {
  75.             if ($defaultProperties array_diff_key(LazyObjectRegistry::$defaultProperties[$instance::class], $this->skippedProperties)) {
  76.                 PublicHydrator::hydrate($instance$defaultProperties);
  77.             }
  78.             ($this->initializer)($instance);
  79.         } catch (\Throwable $e) {
  80.             $this->status self::STATUS_UNINITIALIZED_FULL;
  81.             $this->reset($instance);
  82.             throw $e;
  83.         }
  84.         return self::STATUS_INITIALIZED_FULL;
  85.     }
  86.     public function reset($instance): void
  87.     {
  88.         $class $instance::class;
  89.         $propertyScopes Hydrator::$propertyScopes[$class] ??= Hydrator::getPropertyScopes($class);
  90.         $skippedProperties $this->skippedProperties;
  91.         $properties = (array) $instance;
  92.         $onlyProperties \is_array($this->initializer) ? $this->initializer null;
  93.         foreach ($propertyScopes as $key => [$scope$name$readonlyScope]) {
  94.             $propertyScopes[$k "\0$scope\0$name"] ?? $propertyScopes[$k "\0*\0$name"] ?? $k $name;
  95.             if ($k === $key && (null !== $readonlyScope || !\array_key_exists($k$properties))) {
  96.                 $skippedProperties[$k] = true;
  97.             }
  98.         }
  99.         foreach (LazyObjectRegistry::$classResetters[$class] as $reset) {
  100.             $reset($instance$skippedProperties$onlyProperties);
  101.         }
  102.         $this->status self::STATUS_INITIALIZED_FULL === $this->status self::STATUS_UNINITIALIZED_FULL self::STATUS_UNINITIALIZED_PARTIAL;
  103.     }
  104. }