vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php line 129

Open in your IDE?
  1. <?php
  2. /*
  3.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  4.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  5.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  6.  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  7.  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  8.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  9.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  10.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  11.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  12.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  13.  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14.  *
  15.  * This software consists of voluntary contributions made by many individuals
  16.  * and is licensed under the MIT license. For more information, see
  17.  * <http://www.doctrine-project.org>.
  18.  */
  19. namespace Doctrine\ORM\Mapping;
  20. use Doctrine\Common\EventManager;
  21. use Doctrine\DBAL\Platforms;
  22. use Doctrine\DBAL\Platforms\AbstractPlatform;
  23. use Doctrine\Deprecations\Deprecation;
  24. use Doctrine\ORM\EntityManagerInterface;
  25. use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
  26. use Doctrine\ORM\Event\OnClassMetadataNotFoundEventArgs;
  27. use Doctrine\ORM\Events;
  28. use Doctrine\ORM\Id\AssignedGenerator;
  29. use Doctrine\ORM\Id\BigIntegerIdentityGenerator;
  30. use Doctrine\ORM\Id\IdentityGenerator;
  31. use Doctrine\ORM\Id\SequenceGenerator;
  32. use Doctrine\ORM\Id\UuidGenerator;
  33. use Doctrine\ORM\ORMException;
  34. use Doctrine\Persistence\Mapping\AbstractClassMetadataFactory;
  35. use Doctrine\Persistence\Mapping\ClassMetadata as ClassMetadataInterface;
  36. use Doctrine\Persistence\Mapping\Driver\MappingDriver;
  37. use Doctrine\Persistence\Mapping\ReflectionService;
  38. use ReflectionClass;
  39. use ReflectionException;
  40. use function array_map;
  41. use function assert;
  42. use function class_exists;
  43. use function count;
  44. use function end;
  45. use function explode;
  46. use function is_subclass_of;
  47. use function strpos;
  48. use function strtolower;
  49. /**
  50.  * The ClassMetadataFactory is used to create ClassMetadata objects that contain all the
  51.  * metadata mapping information of a class which describes how a class should be mapped
  52.  * to a relational database.
  53.  *
  54.  * @method ClassMetadata[] getAllMetadata()
  55.  * @method ClassMetadata[] getLoadedMetadata()
  56.  * @method ClassMetadata getMetadataFor($className)
  57.  */
  58. class ClassMetadataFactory extends AbstractClassMetadataFactory
  59. {
  60.     /** @var EntityManagerInterface|null */
  61.     private $em;
  62.     /** @var AbstractPlatform|null */
  63.     private $targetPlatform;
  64.     /** @var MappingDriver */
  65.     private $driver;
  66.     /** @var EventManager */
  67.     private $evm;
  68.     /** @var mixed[] */
  69.     private $embeddablesActiveNesting = [];
  70.     /**
  71.      * {@inheritDoc}
  72.      */
  73.     protected function loadMetadata($name)
  74.     {
  75.         $loaded parent::loadMetadata($name);
  76.         array_map([$this'resolveDiscriminatorValue'], array_map([$this'getMetadataFor'], $loaded));
  77.         return $loaded;
  78.     }
  79.     /**
  80.      * @return void
  81.      */
  82.     public function setEntityManager(EntityManagerInterface $em)
  83.     {
  84.         $this->em $em;
  85.     }
  86.     /**
  87.      * {@inheritDoc}
  88.      */
  89.     protected function initialize()
  90.     {
  91.         $this->driver      $this->em->getConfiguration()->getMetadataDriverImpl();
  92.         $this->evm         $this->em->getEventManager();
  93.         $this->initialized true;
  94.     }
  95.     /**
  96.      * {@inheritDoc}
  97.      */
  98.     protected function onNotFoundMetadata($className)
  99.     {
  100.         if (! $this->evm->hasListeners(Events::onClassMetadataNotFound)) {
  101.             return;
  102.         }
  103.         $eventArgs = new OnClassMetadataNotFoundEventArgs($className$this->em);
  104.         $this->evm->dispatchEvent(Events::onClassMetadataNotFound$eventArgs);
  105.         return $eventArgs->getFoundMetadata();
  106.     }
  107.     /**
  108.      * {@inheritDoc}
  109.      */
  110.     protected function doLoadMetadata($class$parent$rootEntityFound, array $nonSuperclassParents)
  111.     {
  112.         if ($parent) {
  113.             $class->setInheritanceType($parent->inheritanceType);
  114.             $class->setDiscriminatorColumn($parent->discriminatorColumn);
  115.             $class->setIdGeneratorType($parent->generatorType);
  116.             $this->addInheritedFields($class$parent);
  117.             $this->addInheritedRelations($class$parent);
  118.             $this->addInheritedEmbeddedClasses($class$parent);
  119.             $class->setIdentifier($parent->identifier);
  120.             $class->setVersioned($parent->isVersioned);
  121.             $class->setVersionField($parent->versionField);
  122.             $class->setDiscriminatorMap($parent->discriminatorMap);
  123.             $class->setLifecycleCallbacks($parent->lifecycleCallbacks);
  124.             $class->setChangeTrackingPolicy($parent->changeTrackingPolicy);
  125.             if (! empty($parent->customGeneratorDefinition)) {
  126.                 $class->setCustomGeneratorDefinition($parent->customGeneratorDefinition);
  127.             }
  128.             if ($parent->isMappedSuperclass) {
  129.                 $class->setCustomRepositoryClass($parent->customRepositoryClassName);
  130.             }
  131.         }
  132.         // Invoke driver
  133.         try {
  134.             $this->driver->loadMetadataForClass($class->getName(), $class);
  135.         } catch (ReflectionException $e) {
  136.             throw MappingException::reflectionFailure($class->getName(), $e);
  137.         }
  138.         // If this class has a parent the id generator strategy is inherited.
  139.         // However this is only true if the hierarchy of parents contains the root entity,
  140.         // if it consists of mapped superclasses these don't necessarily include the id field.
  141.         if ($parent && $rootEntityFound) {
  142.             $this->inheritIdGeneratorMapping($class$parent);
  143.         } else {
  144.             $this->completeIdGeneratorMapping($class);
  145.         }
  146.         if (! $class->isMappedSuperclass) {
  147.             foreach ($class->embeddedClasses as $property => $embeddableClass) {
  148.                 if (isset($embeddableClass['inherited'])) {
  149.                     continue;
  150.                 }
  151.                 if (! (isset($embeddableClass['class']) && $embeddableClass['class'])) {
  152.                     throw MappingException::missingEmbeddedClass($property);
  153.                 }
  154.                 if (isset($this->embeddablesActiveNesting[$embeddableClass['class']])) {
  155.                     throw MappingException::infiniteEmbeddableNesting($class->name$property);
  156.                 }
  157.                 $this->embeddablesActiveNesting[$class->name] = true;
  158.                 $embeddableMetadata $this->getMetadataFor($embeddableClass['class']);
  159.                 if ($embeddableMetadata->isEmbeddedClass) {
  160.                     $this->addNestedEmbeddedClasses($embeddableMetadata$class$property);
  161.                 }
  162.                 $identifier $embeddableMetadata->getIdentifier();
  163.                 if (! empty($identifier)) {
  164.                     $this->inheritIdGeneratorMapping($class$embeddableMetadata);
  165.                 }
  166.                 $class->inlineEmbeddable($property$embeddableMetadata);
  167.                 unset($this->embeddablesActiveNesting[$class->name]);
  168.             }
  169.         }
  170.         if ($parent) {
  171.             if ($parent->isInheritanceTypeSingleTable()) {
  172.                 $class->setPrimaryTable($parent->table);
  173.             }
  174.             if ($parent) {
  175.                 $this->addInheritedIndexes($class$parent);
  176.             }
  177.             if ($parent->cache) {
  178.                 $class->cache $parent->cache;
  179.             }
  180.             if ($parent->containsForeignIdentifier) {
  181.                 $class->containsForeignIdentifier true;
  182.             }
  183.             if (! empty($parent->namedQueries)) {
  184.                 $this->addInheritedNamedQueries($class$parent);
  185.             }
  186.             if (! empty($parent->namedNativeQueries)) {
  187.                 $this->addInheritedNamedNativeQueries($class$parent);
  188.             }
  189.             if (! empty($parent->sqlResultSetMappings)) {
  190.                 $this->addInheritedSqlResultSetMappings($class$parent);
  191.             }
  192.             if (! empty($parent->entityListeners) && empty($class->entityListeners)) {
  193.                 $class->entityListeners $parent->entityListeners;
  194.             }
  195.         }
  196.         $class->setParentClasses($nonSuperclassParents);
  197.         if ($class->isRootEntity() && ! $class->isInheritanceTypeNone() && ! $class->discriminatorMap) {
  198.             $this->addDefaultDiscriminatorMap($class);
  199.         }
  200.         if ($this->evm->hasListeners(Events::loadClassMetadata)) {
  201.             $eventArgs = new LoadClassMetadataEventArgs($class$this->em);
  202.             $this->evm->dispatchEvent(Events::loadClassMetadata$eventArgs);
  203.         }
  204.         if ($class->changeTrackingPolicy === ClassMetadataInfo::CHANGETRACKING_NOTIFY) {
  205.             Deprecation::trigger(
  206.                 'doctrine/orm',
  207.                 'https://github.com/doctrine/orm/issues/8383',
  208.                 'NOTIFY Change Tracking policy used in "%s" is deprecated, use deferred explicit instead.',
  209.                 $class->name
  210.             );
  211.         }
  212.         $this->validateRuntimeMetadata($class$parent);
  213.     }
  214.     /**
  215.      * Validate runtime metadata is correctly defined.
  216.      *
  217.      * @param ClassMetadata               $class
  218.      * @param ClassMetadataInterface|null $parent
  219.      *
  220.      * @return void
  221.      *
  222.      * @throws MappingException
  223.      */
  224.     protected function validateRuntimeMetadata($class$parent)
  225.     {
  226.         if (! $class->reflClass) {
  227.             // only validate if there is a reflection class instance
  228.             return;
  229.         }
  230.         $class->validateIdentifier();
  231.         $class->validateAssociations();
  232.         $class->validateLifecycleCallbacks($this->getReflectionService());
  233.         // verify inheritance
  234.         if (! $class->isMappedSuperclass && ! $class->isInheritanceTypeNone()) {
  235.             if (! $parent) {
  236.                 if (count($class->discriminatorMap) === 0) {
  237.                     throw MappingException::missingDiscriminatorMap($class->name);
  238.                 }
  239.                 if (! $class->discriminatorColumn) {
  240.                     throw MappingException::missingDiscriminatorColumn($class->name);
  241.                 }
  242.                 foreach ($class->subClasses as $subClass) {
  243.                     if ((new ReflectionClass($subClass))->name !== $subClass) {
  244.                         throw MappingException::invalidClassInDiscriminatorMap($subClass$class->name);
  245.                     }
  246.                 }
  247.             }
  248.         } elseif ($class->isMappedSuperclass && $class->name === $class->rootEntityName && (count($class->discriminatorMap) || $class->discriminatorColumn)) {
  249.             // second condition is necessary for mapped superclasses in the middle of an inheritance hierarchy
  250.             throw MappingException::noInheritanceOnMappedSuperClass($class->name);
  251.         }
  252.     }
  253.     /**
  254.      * {@inheritDoc}
  255.      */
  256.     protected function newClassMetadataInstance($className)
  257.     {
  258.         return new ClassMetadata($className$this->em->getConfiguration()->getNamingStrategy());
  259.     }
  260.     /**
  261.      * Populates the discriminator value of the given metadata (if not set) by iterating over discriminator
  262.      * map classes and looking for a fitting one.
  263.      *
  264.      * @throws MappingException
  265.      */
  266.     private function resolveDiscriminatorValue(ClassMetadata $metadata): void
  267.     {
  268.         if (
  269.             $metadata->discriminatorValue
  270.             || ! $metadata->discriminatorMap
  271.             || $metadata->isMappedSuperclass
  272.             || ! $metadata->reflClass
  273.             || $metadata->reflClass->isAbstract()
  274.         ) {
  275.             return;
  276.         }
  277.         // minor optimization: avoid loading related metadata when not needed
  278.         foreach ($metadata->discriminatorMap as $discriminatorValue => $discriminatorClass) {
  279.             if ($discriminatorClass === $metadata->name) {
  280.                 $metadata->discriminatorValue $discriminatorValue;
  281.                 return;
  282.             }
  283.         }
  284.         // iterate over discriminator mappings and resolve actual referenced classes according to existing metadata
  285.         foreach ($metadata->discriminatorMap as $discriminatorValue => $discriminatorClass) {
  286.             if ($metadata->name === $this->getMetadataFor($discriminatorClass)->getName()) {
  287.                 $metadata->discriminatorValue $discriminatorValue;
  288.                 return;
  289.             }
  290.         }
  291.         throw MappingException::mappedClassNotPartOfDiscriminatorMap($metadata->name$metadata->rootEntityName);
  292.     }
  293.     /**
  294.      * Adds a default discriminator map if no one is given
  295.      *
  296.      * If an entity is of any inheritance type and does not contain a
  297.      * discriminator map, then the map is generated automatically. This process
  298.      * is expensive computation wise.
  299.      *
  300.      * The automatically generated discriminator map contains the lowercase short name of
  301.      * each class as key.
  302.      *
  303.      * @throws MappingException
  304.      */
  305.     private function addDefaultDiscriminatorMap(ClassMetadata $class): void
  306.     {
  307.         $allClasses $this->driver->getAllClassNames();
  308.         $fqcn       $class->getName();
  309.         $map        = [$this->getShortName($class->name) => $fqcn];
  310.         $duplicates = [];
  311.         foreach ($allClasses as $subClassCandidate) {
  312.             if (is_subclass_of($subClassCandidate$fqcn)) {
  313.                 $shortName $this->getShortName($subClassCandidate);
  314.                 if (isset($map[$shortName])) {
  315.                     $duplicates[] = $shortName;
  316.                 }
  317.                 $map[$shortName] = $subClassCandidate;
  318.             }
  319.         }
  320.         if ($duplicates) {
  321.             throw MappingException::duplicateDiscriminatorEntry($class->name$duplicates$map);
  322.         }
  323.         $class->setDiscriminatorMap($map);
  324.     }
  325.     /**
  326.      * Gets the lower-case short name of a class.
  327.      *
  328.      * @psalm-param class-string $className
  329.      */
  330.     private function getShortName(string $className): string
  331.     {
  332.         if (strpos($className'\\') === false) {
  333.             return strtolower($className);
  334.         }
  335.         $parts explode('\\'$className);
  336.         return strtolower(end($parts));
  337.     }
  338.     /**
  339.      * Adds inherited fields to the subclass mapping.
  340.      */
  341.     private function addInheritedFields(ClassMetadata $subClassClassMetadata $parentClass): void
  342.     {
  343.         foreach ($parentClass->fieldMappings as $mapping) {
  344.             if (! isset($mapping['inherited']) && ! $parentClass->isMappedSuperclass) {
  345.                 $mapping['inherited'] = $parentClass->name;
  346.             }
  347.             if (! isset($mapping['declared'])) {
  348.                 $mapping['declared'] = $parentClass->name;
  349.             }
  350.             $subClass->addInheritedFieldMapping($mapping);
  351.         }
  352.         foreach ($parentClass->reflFields as $name => $field) {
  353.             $subClass->reflFields[$name] = $field;
  354.         }
  355.     }
  356.     /**
  357.      * Adds inherited association mappings to the subclass mapping.
  358.      *
  359.      * @throws MappingException
  360.      */
  361.     private function addInheritedRelations(ClassMetadata $subClassClassMetadata $parentClass): void
  362.     {
  363.         foreach ($parentClass->associationMappings as $field => $mapping) {
  364.             if ($parentClass->isMappedSuperclass) {
  365.                 if ($mapping['type'] & ClassMetadata::TO_MANY && ! $mapping['isOwningSide']) {
  366.                     throw MappingException::illegalToManyAssociationOnMappedSuperclass($parentClass->name$field);
  367.                 }
  368.                 $mapping['sourceEntity'] = $subClass->name;
  369.             }
  370.             //$subclassMapping = $mapping;
  371.             if (! isset($mapping['inherited']) && ! $parentClass->isMappedSuperclass) {
  372.                 $mapping['inherited'] = $parentClass->name;
  373.             }
  374.             if (! isset($mapping['declared'])) {
  375.                 $mapping['declared'] = $parentClass->name;
  376.             }
  377.             $subClass->addInheritedAssociationMapping($mapping);
  378.         }
  379.     }
  380.     private function addInheritedEmbeddedClasses(ClassMetadata $subClassClassMetadata $parentClass): void
  381.     {
  382.         foreach ($parentClass->embeddedClasses as $field => $embeddedClass) {
  383.             if (! isset($embeddedClass['inherited']) && ! $parentClass->isMappedSuperclass) {
  384.                 $embeddedClass['inherited'] = $parentClass->name;
  385.             }
  386.             if (! isset($embeddedClass['declared'])) {
  387.                 $embeddedClass['declared'] = $parentClass->name;
  388.             }
  389.             $subClass->embeddedClasses[$field] = $embeddedClass;
  390.         }
  391.     }
  392.     /**
  393.      * Adds nested embedded classes metadata to a parent class.
  394.      *
  395.      * @param ClassMetadata $subClass    Sub embedded class metadata to add nested embedded classes metadata from.
  396.      * @param ClassMetadata $parentClass Parent class to add nested embedded classes metadata to.
  397.      * @param string        $prefix      Embedded classes' prefix to use for nested embedded classes field names.
  398.      */
  399.     private function addNestedEmbeddedClasses(
  400.         ClassMetadata $subClass,
  401.         ClassMetadata $parentClass,
  402.         string $prefix
  403.     ): void {
  404.         foreach ($subClass->embeddedClasses as $property => $embeddableClass) {
  405.             if (isset($embeddableClass['inherited'])) {
  406.                 continue;
  407.             }
  408.             $embeddableMetadata $this->getMetadataFor($embeddableClass['class']);
  409.             $parentClass->mapEmbedded(
  410.                 [
  411.                     'fieldName' => $prefix '.' $property,
  412.                     'class' => $embeddableMetadata->name,
  413.                     'columnPrefix' => $embeddableClass['columnPrefix'],
  414.                     'declaredField' => $embeddableClass['declaredField']
  415.                             ? $prefix '.' $embeddableClass['declaredField']
  416.                             : $prefix,
  417.                     'originalField' => $embeddableClass['originalField'] ?: $property,
  418.                 ]
  419.             );
  420.         }
  421.     }
  422.     /**
  423.      * Copy the table indices from the parent class superclass to the child class
  424.      */
  425.     private function addInheritedIndexes(ClassMetadata $subClassClassMetadata $parentClass): void
  426.     {
  427.         if (! $parentClass->isMappedSuperclass) {
  428.             return;
  429.         }
  430.         foreach (['uniqueConstraints''indexes'] as $indexType) {
  431.             if (isset($parentClass->table[$indexType])) {
  432.                 foreach ($parentClass->table[$indexType] as $indexName => $index) {
  433.                     if (isset($subClass->table[$indexType][$indexName])) {
  434.                         continue; // Let the inheriting table override indices
  435.                     }
  436.                     $subClass->table[$indexType][$indexName] = $index;
  437.                 }
  438.             }
  439.         }
  440.     }
  441.     /**
  442.      * Adds inherited named queries to the subclass mapping.
  443.      */
  444.     private function addInheritedNamedQueries(ClassMetadata $subClassClassMetadata $parentClass): void
  445.     {
  446.         foreach ($parentClass->namedQueries as $name => $query) {
  447.             if (! isset($subClass->namedQueries[$name])) {
  448.                 $subClass->addNamedQuery(
  449.                     [
  450.                         'name'  => $query['name'],
  451.                         'query' => $query['query'],
  452.                     ]
  453.                 );
  454.             }
  455.         }
  456.     }
  457.     /**
  458.      * Adds inherited named native queries to the subclass mapping.
  459.      */
  460.     private function addInheritedNamedNativeQueries(ClassMetadata $subClassClassMetadata $parentClass): void
  461.     {
  462.         foreach ($parentClass->namedNativeQueries as $name => $query) {
  463.             if (! isset($subClass->namedNativeQueries[$name])) {
  464.                 $subClass->addNamedNativeQuery(
  465.                     [
  466.                         'name'              => $query['name'],
  467.                         'query'             => $query['query'],
  468.                         'isSelfClass'       => $query['isSelfClass'],
  469.                         'resultSetMapping'  => $query['resultSetMapping'],
  470.                         'resultClass'       => $query['isSelfClass'] ? $subClass->name $query['resultClass'],
  471.                     ]
  472.                 );
  473.             }
  474.         }
  475.     }
  476.     /**
  477.      * Adds inherited sql result set mappings to the subclass mapping.
  478.      */
  479.     private function addInheritedSqlResultSetMappings(ClassMetadata $subClassClassMetadata $parentClass): void
  480.     {
  481.         foreach ($parentClass->sqlResultSetMappings as $name => $mapping) {
  482.             if (! isset($subClass->sqlResultSetMappings[$name])) {
  483.                 $entities = [];
  484.                 foreach ($mapping['entities'] as $entity) {
  485.                     $entities[] = [
  486.                         'fields'                => $entity['fields'],
  487.                         'isSelfClass'           => $entity['isSelfClass'],
  488.                         'discriminatorColumn'   => $entity['discriminatorColumn'],
  489.                         'entityClass'           => $entity['isSelfClass'] ? $subClass->name $entity['entityClass'],
  490.                     ];
  491.                 }
  492.                 $subClass->addSqlResultSetMapping(
  493.                     [
  494.                         'name'          => $mapping['name'],
  495.                         'columns'       => $mapping['columns'],
  496.                         'entities'      => $entities,
  497.                     ]
  498.                 );
  499.             }
  500.         }
  501.     }
  502.     /**
  503.      * Completes the ID generator mapping. If "auto" is specified we choose the generator
  504.      * most appropriate for the targeted database platform.
  505.      *
  506.      * @throws ORMException
  507.      */
  508.     private function completeIdGeneratorMapping(ClassMetadataInfo $class): void
  509.     {
  510.         $idGenType $class->generatorType;
  511.         if ($idGenType === ClassMetadata::GENERATOR_TYPE_AUTO) {
  512.             if ($this->getTargetPlatform()->prefersSequences()) {
  513.                 $class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_SEQUENCE);
  514.             } elseif ($this->getTargetPlatform()->prefersIdentityColumns()) {
  515.                 $class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_IDENTITY);
  516.             } else {
  517.                 $class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_TABLE);
  518.             }
  519.         }
  520.         // Create & assign an appropriate ID generator instance
  521.         switch ($class->generatorType) {
  522.             case ClassMetadata::GENERATOR_TYPE_IDENTITY:
  523.                 $sequenceName null;
  524.                 $fieldName    $class->identifier $class->getSingleIdentifierFieldName() : null;
  525.                 // Platforms that do not have native IDENTITY support need a sequence to emulate this behaviour.
  526.                 if ($this->getTargetPlatform()->usesSequenceEmulatedIdentityColumns()) {
  527.                     $columnName     $class->getSingleIdentifierColumnName();
  528.                     $quoted         = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']);
  529.                     $sequencePrefix $class->getSequencePrefix($this->getTargetPlatform());
  530.                     $sequenceName   $this->getTargetPlatform()->getIdentitySequenceName($sequencePrefix$columnName);
  531.                     $definition     = [
  532.                         'sequenceName' => $this->getTargetPlatform()->fixSchemaElementName($sequenceName),
  533.                     ];
  534.                     if ($quoted) {
  535.                         $definition['quoted'] = true;
  536.                     }
  537.                     $sequenceName $this
  538.                         ->em
  539.                         ->getConfiguration()
  540.                         ->getQuoteStrategy()
  541.                         ->getSequenceName($definition$class$this->getTargetPlatform());
  542.                 }
  543.                 $generator $fieldName && $class->fieldMappings[$fieldName]['type'] === 'bigint'
  544.                     ? new BigIntegerIdentityGenerator($sequenceName)
  545.                     : new IdentityGenerator($sequenceName);
  546.                 $class->setIdGenerator($generator);
  547.                 break;
  548.             case ClassMetadata::GENERATOR_TYPE_SEQUENCE:
  549.                 // If there is no sequence definition yet, create a default definition
  550.                 $definition $class->sequenceGeneratorDefinition;
  551.                 if (! $definition) {
  552.                     $fieldName    $class->getSingleIdentifierFieldName();
  553.                     $sequenceName $class->getSequenceName($this->getTargetPlatform());
  554.                     $quoted       = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']);
  555.                     $definition = [
  556.                         'sequenceName'      => $this->getTargetPlatform()->fixSchemaElementName($sequenceName),
  557.                         'allocationSize'    => 1,
  558.                         'initialValue'      => 1,
  559.                     ];
  560.                     if ($quoted) {
  561.                         $definition['quoted'] = true;
  562.                     }
  563.                     $class->setSequenceGeneratorDefinition($definition);
  564.                 }
  565.                 $sequenceGenerator = new SequenceGenerator(
  566.                     $this->em->getConfiguration()->getQuoteStrategy()->getSequenceName($definition$class$this->getTargetPlatform()),
  567.                     $definition['allocationSize']
  568.                 );
  569.                 $class->setIdGenerator($sequenceGenerator);
  570.                 break;
  571.             case ClassMetadata::GENERATOR_TYPE_NONE:
  572.                 $class->setIdGenerator(new AssignedGenerator());
  573.                 break;
  574.             case ClassMetadata::GENERATOR_TYPE_UUID:
  575.                 $class->setIdGenerator(new UuidGenerator());
  576.                 break;
  577.             case ClassMetadata::GENERATOR_TYPE_TABLE:
  578.                 throw new ORMException('TableGenerator not yet implemented.');
  579.                 break;
  580.             case ClassMetadata::GENERATOR_TYPE_CUSTOM:
  581.                 $definition $class->customGeneratorDefinition;
  582.                 if ($definition === null) {
  583.                     throw new ORMException("Can't instantiate custom generator : no custom generator definition");
  584.                 }
  585.                 if (! class_exists($definition['class'])) {
  586.                     throw new ORMException("Can't instantiate custom generator : " .
  587.                         $definition['class']);
  588.                 }
  589.                 $class->setIdGenerator(new $definition['class']());
  590.                 break;
  591.             default:
  592.                 throw new ORMException('Unknown generator type: ' $class->generatorType);
  593.         }
  594.     }
  595.     /**
  596.      * Inherits the ID generator mapping from a parent class.
  597.      */
  598.     private function inheritIdGeneratorMapping(ClassMetadataInfo $classClassMetadataInfo $parent): void
  599.     {
  600.         if ($parent->isIdGeneratorSequence()) {
  601.             $class->setSequenceGeneratorDefinition($parent->sequenceGeneratorDefinition);
  602.         } elseif ($parent->isIdGeneratorTable()) {
  603.             $class->tableGeneratorDefinition $parent->tableGeneratorDefinition;
  604.         }
  605.         if ($parent->generatorType) {
  606.             $class->setIdGeneratorType($parent->generatorType);
  607.         }
  608.         if ($parent->idGenerator) {
  609.             $class->setIdGenerator($parent->idGenerator);
  610.         }
  611.     }
  612.     /**
  613.      * {@inheritDoc}
  614.      */
  615.     protected function wakeupReflection(ClassMetadataInterface $classReflectionService $reflService)
  616.     {
  617.         assert($class instanceof ClassMetadata);
  618.         $class->wakeupReflection($reflService);
  619.     }
  620.     /**
  621.      * {@inheritDoc}
  622.      */
  623.     protected function initializeReflection(ClassMetadataInterface $classReflectionService $reflService)
  624.     {
  625.         assert($class instanceof ClassMetadata);
  626.         $class->initializeReflection($reflService);
  627.     }
  628.     /**
  629.      * {@inheritDoc}
  630.      */
  631.     protected function getFqcnFromAlias($namespaceAlias$simpleClassName)
  632.     {
  633.         /** @psalm-var class-string */
  634.         return $this->em->getConfiguration()->getEntityNamespace($namespaceAlias) . '\\' $simpleClassName;
  635.     }
  636.     /**
  637.      * {@inheritDoc}
  638.      */
  639.     protected function getDriver()
  640.     {
  641.         return $this->driver;
  642.     }
  643.     /**
  644.      * {@inheritDoc}
  645.      */
  646.     protected function isEntity(ClassMetadataInterface $class)
  647.     {
  648.         return isset($class->isMappedSuperclass) && $class->isMappedSuperclass === false;
  649.     }
  650.     private function getTargetPlatform(): Platforms\AbstractPlatform
  651.     {
  652.         if (! $this->targetPlatform) {
  653.             $this->targetPlatform $this->em->getConnection()->getDatabasePlatform();
  654.         }
  655.         return $this->targetPlatform;
  656.     }
  657. }