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

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