vendor/friendsofphp/proxy-manager-lts/src/ProxyManager/Factory/AbstractBaseFactory.php line 117

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace ProxyManager\Factory;
  4. use OutOfBoundsException;
  5. use ProxyManager\Configuration;
  6. use ProxyManager\Generator\ClassGenerator;
  7. use ProxyManager\ProxyGenerator\ProxyGeneratorInterface;
  8. use ProxyManager\Signature\Exception\InvalidSignatureException;
  9. use ProxyManager\Signature\Exception\MissingSignatureException;
  10. use ProxyManager\Version;
  11. use ReflectionClass;
  12. use function array_key_exists;
  13. use function assert;
  14. use function class_exists;
  15. use function is_a;
  16. use function serialize;
  17. use function sha1;
  18. /**
  19.  * Base factory common logic
  20.  */
  21. abstract class AbstractBaseFactory
  22. {
  23.     protected $configuration;
  24.     /**
  25.      * Cached checked class names
  26.      *
  27.      * @var array<string, string>
  28.      * @psalm-var array<string, class-string>
  29.      */
  30.     private $checkedClasses = [];
  31.     public function __construct(?Configuration $configuration null)
  32.     {
  33.         $this->configuration $configuration ?? new Configuration();
  34.     }
  35.     /**
  36.      * Generate a proxy from a class name
  37.      *
  38.      * @param array<string, mixed> $proxyOptions
  39.      * @psalm-param class-string<RealObjectType> $className
  40.      *
  41.      * @psalm-return class-string<RealObjectType>
  42.      *
  43.      * @throws InvalidSignatureException
  44.      * @throws MissingSignatureException
  45.      * @throws OutOfBoundsException
  46.      *
  47.      * @psalm-template RealObjectType of object
  48.      */
  49.     protected function generateProxy(string $className, array $proxyOptions = []): string
  50.     {
  51.         $cacheKey $proxyOptions sha1(serialize([$className$proxyOptions])) : $className;
  52.         if (array_key_exists($cacheKey$this->checkedClasses)) {
  53.             $generatedClassName $this->checkedClasses[$cacheKey];
  54.             assert(is_a($generatedClassName$classNametrue));
  55.             return $generatedClassName;
  56.         }
  57.         $proxyParameters = [
  58.             'className'           => $className,
  59.             'factory'             => static::class,
  60.             'proxyManagerVersion' => Version::getVersion(),
  61.             'proxyOptions'        => $proxyOptions,
  62.         ];
  63.         $proxyClassName  $this
  64.             ->configuration
  65.             ->getClassNameInflector()
  66.             ->getProxyClassName($className$proxyParameters);
  67.         if (! class_exists($proxyClassName)) {
  68.             $this->generateProxyClass(
  69.                 $proxyClassName,
  70.                 $className,
  71.                 $proxyParameters,
  72.                 $proxyOptions
  73.             );
  74.         }
  75.         $this
  76.             ->configuration
  77.             ->getSignatureChecker()
  78.             ->checkSignature(new ReflectionClass($proxyClassName), $proxyParameters);
  79.         return $this->checkedClasses[$cacheKey] = $proxyClassName;
  80.     }
  81.     abstract protected function getGenerator(): ProxyGeneratorInterface;
  82.     /**
  83.      * Generates the provided `$proxyClassName` from the given `$className` and `$proxyParameters`
  84.      *
  85.      * @param array<string, mixed> $proxyParameters
  86.      * @param array<string, mixed> $proxyOptions
  87.      * @psalm-param class-string $proxyClassName
  88.      * @psalm-param class-string $className
  89.      */
  90.     private function generateProxyClass(
  91.         string $proxyClassName,
  92.         string $className,
  93.         array $proxyParameters,
  94.         array $proxyOptions = []
  95.     ): void {
  96.         $className $this->configuration->getClassNameInflector()->getUserClassName($className);
  97.         $phpClass  = new ClassGenerator($proxyClassName);
  98.         /** @psalm-suppress TooManyArguments - generator interface was not updated due to BC compliance */
  99.         $this->getGenerator()->generate(new ReflectionClass($className), $phpClass$proxyOptions);
  100.         $phpClass $this->configuration->getClassSignatureGenerator()->addSignature($phpClass$proxyParameters);
  101.         /** @psalm-suppress TooManyArguments - generator interface was not updated due to BC compliance */
  102.         $this->configuration->getGeneratorStrategy()->generate($phpClass$proxyOptions);
  103.         $autoloader $this->configuration->getProxyAutoloader();
  104.         $autoloader($proxyClassName);
  105.     }
  106. }