vendor/doctrine/common/src/Proxy/AbstractProxyFactory.php line 111

Open in your IDE?
  1. <?php
  2. namespace Doctrine\Common\Proxy;
  3. use Doctrine\Common\Proxy\Exception\InvalidArgumentException;
  4. use Doctrine\Common\Proxy\Exception\OutOfBoundsException;
  5. use Doctrine\Common\Util\ClassUtils;
  6. use Doctrine\Persistence\Mapping\ClassMetadata;
  7. use Doctrine\Persistence\Mapping\ClassMetadataFactory;
  8. use function class_exists;
  9. use function file_exists;
  10. use function filemtime;
  11. use function in_array;
  12. /**
  13.  * Abstract factory for proxy objects.
  14.  *
  15.  * @deprecated The AbstractProxyFactory class is deprecated since doctrine/common 3.5.
  16.  */
  17. abstract class AbstractProxyFactory
  18. {
  19.     /**
  20.      * Never autogenerate a proxy and rely that it was generated by some
  21.      * process before deployment.
  22.      */
  23.     public const AUTOGENERATE_NEVER 0;
  24.     /**
  25.      * Always generates a new proxy in every request.
  26.      *
  27.      * This is only sane during development.
  28.      */
  29.     public const AUTOGENERATE_ALWAYS 1;
  30.     /**
  31.      * Autogenerate the proxy class when the proxy file does not exist.
  32.      *
  33.      * This strategy causes a file_exists() call whenever any proxy is used the
  34.      * first time in a request.
  35.      */
  36.     public const AUTOGENERATE_FILE_NOT_EXISTS 2;
  37.     /**
  38.      * Generate the proxy classes using eval().
  39.      *
  40.      * This strategy is only sane for development, and even then it gives me
  41.      * the creeps a little.
  42.      */
  43.     public const AUTOGENERATE_EVAL 3;
  44.     /**
  45.      * Autogenerate the proxy class when the proxy file does not exist or
  46.      * when the proxied file changed.
  47.      *
  48.      * This strategy causes a file_exists() call whenever any proxy is used the
  49.      * first time in a request. When the proxied file is changed, the proxy will
  50.      * be updated.
  51.      */
  52.     public const AUTOGENERATE_FILE_NOT_EXISTS_OR_CHANGED 4;
  53.     private const AUTOGENERATE_MODES = [
  54.         self::AUTOGENERATE_NEVER,
  55.         self::AUTOGENERATE_ALWAYS,
  56.         self::AUTOGENERATE_FILE_NOT_EXISTS,
  57.         self::AUTOGENERATE_EVAL,
  58.         self::AUTOGENERATE_FILE_NOT_EXISTS_OR_CHANGED,
  59.     ];
  60.     /** @var ClassMetadataFactory */
  61.     private $metadataFactory;
  62.     /** @var ProxyGenerator the proxy generator responsible for creating the proxy classes/files. */
  63.     private $proxyGenerator;
  64.     /** @var int Whether to automatically (re)generate proxy classes. */
  65.     private $autoGenerate;
  66.     /** @var ProxyDefinition[] */
  67.     private $definitions = [];
  68.     /**
  69.      * @param bool|int $autoGenerate
  70.      *
  71.      * @throws InvalidArgumentException When auto generate mode is not valid.
  72.      */
  73.     public function __construct(ProxyGenerator $proxyGeneratorClassMetadataFactory $metadataFactory$autoGenerate)
  74.     {
  75.         $this->proxyGenerator  $proxyGenerator;
  76.         $this->metadataFactory $metadataFactory;
  77.         $this->autoGenerate    = (int) $autoGenerate;
  78.         if (! in_array($this->autoGenerateself::AUTOGENERATE_MODEStrue)) {
  79.             throw InvalidArgumentException::invalidAutoGenerateMode($autoGenerate);
  80.         }
  81.     }
  82.     /**
  83.      * Gets a reference proxy instance for the entity of the given type and identified by
  84.      * the given identifier.
  85.      *
  86.      * @param  string       $className
  87.      * @param  array<mixed> $identifier
  88.      *
  89.      * @return Proxy
  90.      *
  91.      * @throws OutOfBoundsException
  92.      */
  93.     public function getProxy($className, array $identifier)
  94.     {
  95.         $definition $this->definitions[$className] ?? $this->getProxyDefinition($className);
  96.         $fqcn       $definition->proxyClassName;
  97.         $proxy      = new $fqcn($definition->initializer$definition->cloner);
  98.         foreach ($definition->identifierFields as $idField) {
  99.             if (! isset($identifier[$idField])) {
  100.                 throw OutOfBoundsException::missingPrimaryKeyValue($className$idField);
  101.             }
  102.             $definition->reflectionFields[$idField]->setValue($proxy$identifier[$idField]);
  103.         }
  104.         return $proxy;
  105.     }
  106.     /**
  107.      * Generates proxy classes for all given classes.
  108.      *
  109.      * @param ClassMetadata[] $classes  The classes (ClassMetadata instances)
  110.      *  for which to generate proxies.
  111.      * @param string          $proxyDir The target directory of the proxy classes. If not specified, the
  112.      *                                  directory configured on the Configuration of the EntityManager used
  113.      *                                  by this factory is used.
  114.      *
  115.      * @return int Number of generated proxies.
  116.      */
  117.     public function generateProxyClasses(array $classes$proxyDir null)
  118.     {
  119.         $generated 0;
  120.         foreach ($classes as $class) {
  121.             if ($this->skipClass($class)) {
  122.                 continue;
  123.             }
  124.             $proxyFileName $this->proxyGenerator->getProxyFileName($class->getName(), $proxyDir);
  125.             $this->proxyGenerator->generateProxyClass($class$proxyFileName);
  126.             $generated += 1;
  127.         }
  128.         return $generated;
  129.     }
  130.     /**
  131.      * Reset initialization/cloning logic for an un-initialized proxy
  132.      *
  133.      * @return Proxy
  134.      *
  135.      * @throws InvalidArgumentException
  136.      */
  137.     public function resetUninitializedProxy(Proxy $proxy)
  138.     {
  139.         if ($proxy->__isInitialized()) {
  140.             throw InvalidArgumentException::unitializedProxyExpected($proxy);
  141.         }
  142.         $className  ClassUtils::getClass($proxy);
  143.         $definition $this->definitions[$className] ?? $this->getProxyDefinition($className);
  144.         $proxy->__setInitializer($definition->initializer);
  145.         $proxy->__setCloner($definition->cloner);
  146.         return $proxy;
  147.     }
  148.     /**
  149.      * Get a proxy definition for the given class name.
  150.      *
  151.      * @param string $className
  152.      * @psalm-param class-string $className
  153.      *
  154.      * @return ProxyDefinition
  155.      */
  156.     private function getProxyDefinition($className)
  157.     {
  158.         $classMetadata $this->metadataFactory->getMetadataFor($className);
  159.         $className     $classMetadata->getName(); // aliases and case sensitivity
  160.         $this->definitions[$className] = $this->createProxyDefinition($className);
  161.         $proxyClassName                $this->definitions[$className]->proxyClassName;
  162.         if (! class_exists($proxyClassNamefalse)) {
  163.             $fileName $this->proxyGenerator->getProxyFileName($className);
  164.             switch ($this->autoGenerate) {
  165.                 case self::AUTOGENERATE_NEVER:
  166.                     require $fileName;
  167.                     break;
  168.                 case self::AUTOGENERATE_FILE_NOT_EXISTS:
  169.                     if (! file_exists($fileName)) {
  170.                         $this->proxyGenerator->generateProxyClass($classMetadata$fileName);
  171.                     }
  172.                     require $fileName;
  173.                     break;
  174.                 case self::AUTOGENERATE_ALWAYS:
  175.                     $this->proxyGenerator->generateProxyClass($classMetadata$fileName);
  176.                     require $fileName;
  177.                     break;
  178.                 case self::AUTOGENERATE_EVAL:
  179.                     $this->proxyGenerator->generateProxyClass($classMetadatafalse);
  180.                     break;
  181.                 case self::AUTOGENERATE_FILE_NOT_EXISTS_OR_CHANGED:
  182.                     if (! file_exists($fileName) || filemtime($fileName) < filemtime($classMetadata->getReflectionClass()->getFileName())) {
  183.                         $this->proxyGenerator->generateProxyClass($classMetadata$fileName);
  184.                     }
  185.                     require $fileName;
  186.                     break;
  187.             }
  188.         }
  189.         return $this->definitions[$className];
  190.     }
  191.     /**
  192.      * Determine if this class should be skipped during proxy generation.
  193.      *
  194.      * @return bool
  195.      */
  196.     abstract protected function skipClass(ClassMetadata $metadata);
  197.     /**
  198.      * @param string $className
  199.      * @psalm-param class-string $className
  200.      *
  201.      * @return ProxyDefinition
  202.      */
  203.     abstract protected function createProxyDefinition($className);
  204. }