vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php line 215

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