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

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