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

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($className$this->em->getConfiguration()->getNamingStrategy());
  247.     }
  248.     /**
  249.      * Adds a default discriminator map if no one is given
  250.      *
  251.      * If an entity is of any inheritance type and does not contain a
  252.      * discriminator map, then the map is generated automatically. This process
  253.      * is expensive computation wise.
  254.      *
  255.      * The automatically generated discriminator map contains the lowercase short name of
  256.      * each class as key.
  257.      *
  258.      * @throws MappingException
  259.      */
  260.     private function addDefaultDiscriminatorMap(ClassMetadata $class): void
  261.     {
  262.         $allClasses $this->driver->getAllClassNames();
  263.         $fqcn       $class->getName();
  264.         $map        = [$this->getShortName($class->name) => $fqcn];
  265.         $duplicates = [];
  266.         foreach ($allClasses as $subClassCandidate) {
  267.             if (is_subclass_of($subClassCandidate$fqcn)) {
  268.                 $shortName $this->getShortName($subClassCandidate);
  269.                 if (isset($map[$shortName])) {
  270.                     $duplicates[] = $shortName;
  271.                 }
  272.                 $map[$shortName] = $subClassCandidate;
  273.             }
  274.         }
  275.         if ($duplicates) {
  276.             throw MappingException::duplicateDiscriminatorEntry($class->name$duplicates$map);
  277.         }
  278.         $class->setDiscriminatorMap($map);
  279.     }
  280.     /**
  281.      * Gets the lower-case short name of a class.
  282.      *
  283.      * @psalm-param class-string $className
  284.      */
  285.     private function getShortName(string $className): string
  286.     {
  287.         if (! str_contains($className'\\')) {
  288.             return strtolower($className);
  289.         }
  290.         $parts explode('\\'$className);
  291.         return strtolower(end($parts));
  292.     }
  293.     /**
  294.      * Adds inherited fields to the subclass mapping.
  295.      */
  296.     private function addInheritedFields(ClassMetadata $subClassClassMetadata $parentClass): void
  297.     {
  298.         foreach ($parentClass->fieldMappings as $mapping) {
  299.             if (! isset($mapping['inherited']) && ! $parentClass->isMappedSuperclass) {
  300.                 $mapping['inherited'] = $parentClass->name;
  301.             }
  302.             if (! isset($mapping['declared'])) {
  303.                 $mapping['declared'] = $parentClass->name;
  304.             }
  305.             $subClass->addInheritedFieldMapping($mapping);
  306.         }
  307.         foreach ($parentClass->reflFields as $name => $field) {
  308.             $subClass->reflFields[$name] = $field;
  309.         }
  310.     }
  311.     /**
  312.      * Adds inherited association mappings to the subclass mapping.
  313.      *
  314.      * @throws MappingException
  315.      */
  316.     private function addInheritedRelations(ClassMetadata $subClassClassMetadata $parentClass): void
  317.     {
  318.         foreach ($parentClass->associationMappings as $field => $mapping) {
  319.             if ($parentClass->isMappedSuperclass) {
  320.                 if ($mapping['type'] & ClassMetadata::TO_MANY && ! $mapping['isOwningSide']) {
  321.                     throw MappingException::illegalToManyAssociationOnMappedSuperclass($parentClass->name$field);
  322.                 }
  323.                 $mapping['sourceEntity'] = $subClass->name;
  324.             }
  325.             //$subclassMapping = $mapping;
  326.             if (! isset($mapping['inherited']) && ! $parentClass->isMappedSuperclass) {
  327.                 $mapping['inherited'] = $parentClass->name;
  328.             }
  329.             if (! isset($mapping['declared'])) {
  330.                 $mapping['declared'] = $parentClass->name;
  331.             }
  332.             $subClass->addInheritedAssociationMapping($mapping);
  333.         }
  334.     }
  335.     private function addInheritedEmbeddedClasses(ClassMetadata $subClassClassMetadata $parentClass): void
  336.     {
  337.         foreach ($parentClass->embeddedClasses as $field => $embeddedClass) {
  338.             if (! isset($embeddedClass['inherited']) && ! $parentClass->isMappedSuperclass) {
  339.                 $embeddedClass['inherited'] = $parentClass->name;
  340.             }
  341.             if (! isset($embeddedClass['declared'])) {
  342.                 $embeddedClass['declared'] = $parentClass->name;
  343.             }
  344.             $subClass->embeddedClasses[$field] = $embeddedClass;
  345.         }
  346.     }
  347.     /**
  348.      * Adds nested embedded classes metadata to a parent class.
  349.      *
  350.      * @param ClassMetadata $subClass    Sub embedded class metadata to add nested embedded classes metadata from.
  351.      * @param ClassMetadata $parentClass Parent class to add nested embedded classes metadata to.
  352.      * @param string        $prefix      Embedded classes' prefix to use for nested embedded classes field names.
  353.      */
  354.     private function addNestedEmbeddedClasses(
  355.         ClassMetadata $subClass,
  356.         ClassMetadata $parentClass,
  357.         string $prefix
  358.     ): void {
  359.         foreach ($subClass->embeddedClasses as $property => $embeddableClass) {
  360.             if (isset($embeddableClass['inherited'])) {
  361.                 continue;
  362.             }
  363.             $embeddableMetadata $this->getMetadataFor($embeddableClass['class']);
  364.             $parentClass->mapEmbedded(
  365.                 [
  366.                     'fieldName' => $prefix '.' $property,
  367.                     'class' => $embeddableMetadata->name,
  368.                     'columnPrefix' => $embeddableClass['columnPrefix'],
  369.                     'declaredField' => $embeddableClass['declaredField']
  370.                             ? $prefix '.' $embeddableClass['declaredField']
  371.                             : $prefix,
  372.                     'originalField' => $embeddableClass['originalField'] ?: $property,
  373.                 ]
  374.             );
  375.         }
  376.     }
  377.     /**
  378.      * Copy the table indices from the parent class superclass to the child class
  379.      */
  380.     private function addInheritedIndexes(ClassMetadata $subClassClassMetadata $parentClass): void
  381.     {
  382.         if (! $parentClass->isMappedSuperclass) {
  383.             return;
  384.         }
  385.         foreach (['uniqueConstraints''indexes'] as $indexType) {
  386.             if (isset($parentClass->table[$indexType])) {
  387.                 foreach ($parentClass->table[$indexType] as $indexName => $index) {
  388.                     if (isset($subClass->table[$indexType][$indexName])) {
  389.                         continue; // Let the inheriting table override indices
  390.                     }
  391.                     $subClass->table[$indexType][$indexName] = $index;
  392.                 }
  393.             }
  394.         }
  395.     }
  396.     /**
  397.      * Adds inherited named queries to the subclass mapping.
  398.      */
  399.     private function addInheritedNamedQueries(ClassMetadata $subClassClassMetadata $parentClass): void
  400.     {
  401.         foreach ($parentClass->namedQueries as $name => $query) {
  402.             if (! isset($subClass->namedQueries[$name])) {
  403.                 $subClass->addNamedQuery(
  404.                     [
  405.                         'name'  => $query['name'],
  406.                         'query' => $query['query'],
  407.                     ]
  408.                 );
  409.             }
  410.         }
  411.     }
  412.     /**
  413.      * Adds inherited named native queries to the subclass mapping.
  414.      */
  415.     private function addInheritedNamedNativeQueries(ClassMetadata $subClassClassMetadata $parentClass): void
  416.     {
  417.         foreach ($parentClass->namedNativeQueries as $name => $query) {
  418.             if (! isset($subClass->namedNativeQueries[$name])) {
  419.                 $subClass->addNamedNativeQuery(
  420.                     [
  421.                         'name'              => $query['name'],
  422.                         'query'             => $query['query'],
  423.                         'isSelfClass'       => $query['isSelfClass'],
  424.                         'resultSetMapping'  => $query['resultSetMapping'],
  425.                         'resultClass'       => $query['isSelfClass'] ? $subClass->name $query['resultClass'],
  426.                     ]
  427.                 );
  428.             }
  429.         }
  430.     }
  431.     /**
  432.      * Adds inherited sql result set mappings to the subclass mapping.
  433.      */
  434.     private function addInheritedSqlResultSetMappings(ClassMetadata $subClassClassMetadata $parentClass): void
  435.     {
  436.         foreach ($parentClass->sqlResultSetMappings as $name => $mapping) {
  437.             if (! isset($subClass->sqlResultSetMappings[$name])) {
  438.                 $entities = [];
  439.                 foreach ($mapping['entities'] as $entity) {
  440.                     $entities[] = [
  441.                         'fields'                => $entity['fields'],
  442.                         'isSelfClass'           => $entity['isSelfClass'],
  443.                         'discriminatorColumn'   => $entity['discriminatorColumn'],
  444.                         'entityClass'           => $entity['isSelfClass'] ? $subClass->name $entity['entityClass'],
  445.                     ];
  446.                 }
  447.                 $subClass->addSqlResultSetMapping(
  448.                     [
  449.                         'name'          => $mapping['name'],
  450.                         'columns'       => $mapping['columns'],
  451.                         'entities'      => $entities,
  452.                     ]
  453.                 );
  454.             }
  455.         }
  456.     }
  457.     /**
  458.      * Completes the ID generator mapping. If "auto" is specified we choose the generator
  459.      * most appropriate for the targeted database platform.
  460.      *
  461.      * @throws ORMException
  462.      */
  463.     private function completeIdGeneratorMapping(ClassMetadataInfo $class): void
  464.     {
  465.         $idGenType $class->generatorType;
  466.         if ($idGenType === ClassMetadata::GENERATOR_TYPE_AUTO) {
  467.             $class->setIdGeneratorType($this->determineIdGeneratorStrategy($this->getTargetPlatform()));
  468.         }
  469.         // Create & assign an appropriate ID generator instance
  470.         switch ($class->generatorType) {
  471.             case ClassMetadata::GENERATOR_TYPE_IDENTITY:
  472.                 $sequenceName null;
  473.                 $fieldName    $class->identifier $class->getSingleIdentifierFieldName() : null;
  474.                 // Platforms that do not have native IDENTITY support need a sequence to emulate this behaviour.
  475.                 if ($this->getTargetPlatform()->usesSequenceEmulatedIdentityColumns()) {
  476.                     Deprecation::trigger(
  477.                         'doctrine/orm',
  478.                         'https://github.com/doctrine/orm/issues/8850',
  479.                         <<<'DEPRECATION'
  480. Context: Loading metadata for class %s
  481. Problem: Using the IDENTITY generator strategy with platform "%s" is deprecated and will not be possible in Doctrine ORM 3.0.
  482. Solution: Use the SEQUENCE generator strategy instead.
  483. DEPRECATION
  484.                             ,
  485.                         $class->name,
  486.                         get_class($this->getTargetPlatform())
  487.                     );
  488.                     $columnName     $class->getSingleIdentifierColumnName();
  489.                     $quoted         = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']);
  490.                     $sequencePrefix $class->getSequencePrefix($this->getTargetPlatform());
  491.                     $sequenceName   $this->getTargetPlatform()->getIdentitySequenceName($sequencePrefix$columnName);
  492.                     $definition     = [
  493.                         'sequenceName' => $this->truncateSequenceName($sequenceName),
  494.                     ];
  495.                     if ($quoted) {
  496.                         $definition['quoted'] = true;
  497.                     }
  498.                     $sequenceName $this
  499.                         ->em
  500.                         ->getConfiguration()
  501.                         ->getQuoteStrategy()
  502.                         ->getSequenceName($definition$class$this->getTargetPlatform());
  503.                 }
  504.                 $generator $fieldName && $class->fieldMappings[$fieldName]['type'] === 'bigint'
  505.                     ? new BigIntegerIdentityGenerator($sequenceName)
  506.                     : new IdentityGenerator($sequenceName);
  507.                 $class->setIdGenerator($generator);
  508.                 break;
  509.             case ClassMetadata::GENERATOR_TYPE_SEQUENCE:
  510.                 // If there is no sequence definition yet, create a default definition
  511.                 $definition $class->sequenceGeneratorDefinition;
  512.                 if (! $definition) {
  513.                     $fieldName    $class->getSingleIdentifierFieldName();
  514.                     $sequenceName $class->getSequenceName($this->getTargetPlatform());
  515.                     $quoted       = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']);
  516.                     $definition = [
  517.                         'sequenceName'      => $this->truncateSequenceName($sequenceName),
  518.                         'allocationSize'    => 1,
  519.                         'initialValue'      => 1,
  520.                     ];
  521.                     if ($quoted) {
  522.                         $definition['quoted'] = true;
  523.                     }
  524.                     $class->setSequenceGeneratorDefinition($definition);
  525.                 }
  526.                 $sequenceGenerator = new SequenceGenerator(
  527.                     $this->em->getConfiguration()->getQuoteStrategy()->getSequenceName($definition$class$this->getTargetPlatform()),
  528.                     (int) $definition['allocationSize']
  529.                 );
  530.                 $class->setIdGenerator($sequenceGenerator);
  531.                 break;
  532.             case ClassMetadata::GENERATOR_TYPE_NONE:
  533.                 $class->setIdGenerator(new AssignedGenerator());
  534.                 break;
  535.             case ClassMetadata::GENERATOR_TYPE_UUID:
  536.                 Deprecation::trigger(
  537.                     'doctrine/orm',
  538.                     'https://github.com/doctrine/orm/issues/7312',
  539.                     'Mapping for %s: the "UUID" id generator strategy is deprecated with no replacement',
  540.                     $class->name
  541.                 );
  542.                 $class->setIdGenerator(new UuidGenerator());
  543.                 break;
  544.             case ClassMetadata::GENERATOR_TYPE_CUSTOM:
  545.                 $definition $class->customGeneratorDefinition;
  546.                 if ($definition === null) {
  547.                     throw InvalidCustomGenerator::onClassNotConfigured();
  548.                 }
  549.                 if (! class_exists($definition['class'])) {
  550.                     throw InvalidCustomGenerator::onMissingClass($definition);
  551.                 }
  552.                 $class->setIdGenerator(new $definition['class']());
  553.                 break;
  554.             default:
  555.                 throw UnknownGeneratorType::create($class->generatorType);
  556.         }
  557.     }
  558.     /** @psalm-return ClassMetadata::GENERATOR_TYPE_SEQUENCE|ClassMetadata::GENERATOR_TYPE_IDENTITY */
  559.     private function determineIdGeneratorStrategy(AbstractPlatform $platform): int
  560.     {
  561.         if (
  562.             $platform instanceof Platforms\OraclePlatform
  563.             || $platform instanceof Platforms\PostgreSQLPlatform
  564.         ) {
  565.             return ClassMetadata::GENERATOR_TYPE_SEQUENCE;
  566.         }
  567.         if ($platform->supportsIdentityColumns()) {
  568.             return ClassMetadata::GENERATOR_TYPE_IDENTITY;
  569.         }
  570.         if ($platform->supportsSequences()) {
  571.             return ClassMetadata::GENERATOR_TYPE_SEQUENCE;
  572.         }
  573.         throw CannotGenerateIds::withPlatform($platform);
  574.     }
  575.     private function truncateSequenceName(string $schemaElementName): string
  576.     {
  577.         $platform $this->getTargetPlatform();
  578.         if (! $platform instanceof Platforms\OraclePlatform && ! $platform instanceof Platforms\SQLAnywherePlatform) {
  579.             return $schemaElementName;
  580.         }
  581.         $maxIdentifierLength $platform->getMaxIdentifierLength();
  582.         if (strlen($schemaElementName) > $maxIdentifierLength) {
  583.             return substr($schemaElementName0$maxIdentifierLength);
  584.         }
  585.         return $schemaElementName;
  586.     }
  587.     /**
  588.      * Inherits the ID generator mapping from a parent class.
  589.      */
  590.     private function inheritIdGeneratorMapping(ClassMetadataInfo $classClassMetadataInfo $parent): void
  591.     {
  592.         if ($parent->isIdGeneratorSequence()) {
  593.             $class->setSequenceGeneratorDefinition($parent->sequenceGeneratorDefinition);
  594.         }
  595.         if ($parent->generatorType) {
  596.             $class->setIdGeneratorType($parent->generatorType);
  597.         }
  598.         if ($parent->idGenerator) {
  599.             $class->setIdGenerator($parent->idGenerator);
  600.         }
  601.     }
  602.     /**
  603.      * {@inheritDoc}
  604.      */
  605.     protected function wakeupReflection(ClassMetadataInterface $classReflectionService $reflService)
  606.     {
  607.         assert($class instanceof ClassMetadata);
  608.         $class->wakeupReflection($reflService);
  609.     }
  610.     /**
  611.      * {@inheritDoc}
  612.      */
  613.     protected function initializeReflection(ClassMetadataInterface $classReflectionService $reflService)
  614.     {
  615.         assert($class instanceof ClassMetadata);
  616.         $class->initializeReflection($reflService);
  617.     }
  618.     /**
  619.      * @deprecated This method will be removed in ORM 3.0.
  620.      *
  621.      * @return class-string
  622.      */
  623.     protected function getFqcnFromAlias($namespaceAlias$simpleClassName)
  624.     {
  625.         /** @psalm-var class-string */
  626.         return $this->em->getConfiguration()->getEntityNamespace($namespaceAlias) . '\\' $simpleClassName;
  627.     }
  628.     /**
  629.      * {@inheritDoc}
  630.      */
  631.     protected function getDriver()
  632.     {
  633.         return $this->driver;
  634.     }
  635.     /**
  636.      * {@inheritDoc}
  637.      */
  638.     protected function isEntity(ClassMetadataInterface $class)
  639.     {
  640.         return ! $class->isMappedSuperclass;
  641.     }
  642.     private function getTargetPlatform(): Platforms\AbstractPlatform
  643.     {
  644.         if (! $this->targetPlatform) {
  645.             $this->targetPlatform $this->em->getConnection()->getDatabasePlatform();
  646.         }
  647.         return $this->targetPlatform;
  648.     }
  649. }