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

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.             //$subclassMapping = $mapping;
  330.             if (! isset($mapping['inherited']) && ! $parentClass->isMappedSuperclass) {
  331.                 $mapping['inherited'] = $parentClass->name;
  332.             }
  333.             if (! isset($mapping['declared'])) {
  334.                 $mapping['declared'] = $parentClass->name;
  335.             }
  336.             $subClass->addInheritedAssociationMapping($mapping);
  337.         }
  338.     }
  339.     private function addInheritedEmbeddedClasses(ClassMetadata $subClassClassMetadata $parentClass): void
  340.     {
  341.         foreach ($parentClass->embeddedClasses as $field => $embeddedClass) {
  342.             if (! isset($embeddedClass['inherited']) && ! $parentClass->isMappedSuperclass) {
  343.                 $embeddedClass['inherited'] = $parentClass->name;
  344.             }
  345.             if (! isset($embeddedClass['declared'])) {
  346.                 $embeddedClass['declared'] = $parentClass->name;
  347.             }
  348.             $subClass->embeddedClasses[$field] = $embeddedClass;
  349.         }
  350.     }
  351.     /**
  352.      * Adds nested embedded classes metadata to a parent class.
  353.      *
  354.      * @param ClassMetadata $subClass    Sub embedded class metadata to add nested embedded classes metadata from.
  355.      * @param ClassMetadata $parentClass Parent class to add nested embedded classes metadata to.
  356.      * @param string        $prefix      Embedded classes' prefix to use for nested embedded classes field names.
  357.      */
  358.     private function addNestedEmbeddedClasses(
  359.         ClassMetadata $subClass,
  360.         ClassMetadata $parentClass,
  361.         string $prefix
  362.     ): void {
  363.         foreach ($subClass->embeddedClasses as $property => $embeddableClass) {
  364.             if (isset($embeddableClass['inherited'])) {
  365.                 continue;
  366.             }
  367.             $embeddableMetadata $this->getMetadataFor($embeddableClass['class']);
  368.             $parentClass->mapEmbedded(
  369.                 [
  370.                     'fieldName' => $prefix '.' $property,
  371.                     'class' => $embeddableMetadata->name,
  372.                     'columnPrefix' => $embeddableClass['columnPrefix'],
  373.                     'declaredField' => $embeddableClass['declaredField']
  374.                             ? $prefix '.' $embeddableClass['declaredField']
  375.                             : $prefix,
  376.                     'originalField' => $embeddableClass['originalField'] ?: $property,
  377.                 ]
  378.             );
  379.         }
  380.     }
  381.     /**
  382.      * Copy the table indices from the parent class superclass to the child class
  383.      */
  384.     private function addInheritedIndexes(ClassMetadata $subClassClassMetadata $parentClass): void
  385.     {
  386.         if (! $parentClass->isMappedSuperclass) {
  387.             return;
  388.         }
  389.         foreach (['uniqueConstraints''indexes'] as $indexType) {
  390.             if (isset($parentClass->table[$indexType])) {
  391.                 foreach ($parentClass->table[$indexType] as $indexName => $index) {
  392.                     if (isset($subClass->table[$indexType][$indexName])) {
  393.                         continue; // Let the inheriting table override indices
  394.                     }
  395.                     $subClass->table[$indexType][$indexName] = $index;
  396.                 }
  397.             }
  398.         }
  399.     }
  400.     /**
  401.      * Adds inherited named queries to the subclass mapping.
  402.      */
  403.     private function addInheritedNamedQueries(ClassMetadata $subClassClassMetadata $parentClass): void
  404.     {
  405.         foreach ($parentClass->namedQueries as $name => $query) {
  406.             if (! isset($subClass->namedQueries[$name])) {
  407.                 $subClass->addNamedQuery(
  408.                     [
  409.                         'name'  => $query['name'],
  410.                         'query' => $query['query'],
  411.                     ]
  412.                 );
  413.             }
  414.         }
  415.     }
  416.     /**
  417.      * Adds inherited named native queries to the subclass mapping.
  418.      */
  419.     private function addInheritedNamedNativeQueries(ClassMetadata $subClassClassMetadata $parentClass): void
  420.     {
  421.         foreach ($parentClass->namedNativeQueries as $name => $query) {
  422.             if (! isset($subClass->namedNativeQueries[$name])) {
  423.                 $subClass->addNamedNativeQuery(
  424.                     [
  425.                         'name'              => $query['name'],
  426.                         'query'             => $query['query'],
  427.                         'isSelfClass'       => $query['isSelfClass'],
  428.                         'resultSetMapping'  => $query['resultSetMapping'],
  429.                         'resultClass'       => $query['isSelfClass'] ? $subClass->name $query['resultClass'],
  430.                     ]
  431.                 );
  432.             }
  433.         }
  434.     }
  435.     /**
  436.      * Adds inherited sql result set mappings to the subclass mapping.
  437.      */
  438.     private function addInheritedSqlResultSetMappings(ClassMetadata $subClassClassMetadata $parentClass): void
  439.     {
  440.         foreach ($parentClass->sqlResultSetMappings as $name => $mapping) {
  441.             if (! isset($subClass->sqlResultSetMappings[$name])) {
  442.                 $entities = [];
  443.                 foreach ($mapping['entities'] as $entity) {
  444.                     $entities[] = [
  445.                         'fields'                => $entity['fields'],
  446.                         'isSelfClass'           => $entity['isSelfClass'],
  447.                         'discriminatorColumn'   => $entity['discriminatorColumn'],
  448.                         'entityClass'           => $entity['isSelfClass'] ? $subClass->name $entity['entityClass'],
  449.                     ];
  450.                 }
  451.                 $subClass->addSqlResultSetMapping(
  452.                     [
  453.                         'name'          => $mapping['name'],
  454.                         'columns'       => $mapping['columns'],
  455.                         'entities'      => $entities,
  456.                     ]
  457.                 );
  458.             }
  459.         }
  460.     }
  461.     /**
  462.      * Completes the ID generator mapping. If "auto" is specified we choose the generator
  463.      * most appropriate for the targeted database platform.
  464.      *
  465.      * @throws ORMException
  466.      */
  467.     private function completeIdGeneratorMapping(ClassMetadataInfo $class): void
  468.     {
  469.         $idGenType $class->generatorType;
  470.         if ($idGenType === ClassMetadata::GENERATOR_TYPE_AUTO) {
  471.             $class->setIdGeneratorType($this->determineIdGeneratorStrategy($this->getTargetPlatform()));
  472.         }
  473.         // Create & assign an appropriate ID generator instance
  474.         switch ($class->generatorType) {
  475.             case ClassMetadata::GENERATOR_TYPE_IDENTITY:
  476.                 $sequenceName null;
  477.                 $fieldName    $class->identifier $class->getSingleIdentifierFieldName() : null;
  478.                 // Platforms that do not have native IDENTITY support need a sequence to emulate this behaviour.
  479.                 if ($this->getTargetPlatform()->usesSequenceEmulatedIdentityColumns()) {
  480.                     Deprecation::trigger(
  481.                         'doctrine/orm',
  482.                         'https://github.com/doctrine/orm/issues/8850',
  483.                         <<<'DEPRECATION'
  484. Context: Loading metadata for class %s
  485. Problem: Using the IDENTITY generator strategy with platform "%s" is deprecated and will not be possible in Doctrine ORM 3.0.
  486. Solution: Use the SEQUENCE generator strategy instead.
  487. DEPRECATION
  488.                             ,
  489.                         $class->name,
  490.                         get_class($this->getTargetPlatform())
  491.                     );
  492.                     $columnName     $class->getSingleIdentifierColumnName();
  493.                     $quoted         = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']);
  494.                     $sequencePrefix $class->getSequencePrefix($this->getTargetPlatform());
  495.                     $sequenceName   $this->getTargetPlatform()->getIdentitySequenceName($sequencePrefix$columnName);
  496.                     $definition     = [
  497.                         'sequenceName' => $this->truncateSequenceName($sequenceName),
  498.                     ];
  499.                     if ($quoted) {
  500.                         $definition['quoted'] = true;
  501.                     }
  502.                     $sequenceName $this
  503.                         ->em
  504.                         ->getConfiguration()
  505.                         ->getQuoteStrategy()
  506.                         ->getSequenceName($definition$class$this->getTargetPlatform());
  507.                 }
  508.                 $generator $fieldName && $class->fieldMappings[$fieldName]['type'] === 'bigint'
  509.                     ? new BigIntegerIdentityGenerator($sequenceName)
  510.                     : new IdentityGenerator($sequenceName);
  511.                 $class->setIdGenerator($generator);
  512.                 break;
  513.             case ClassMetadata::GENERATOR_TYPE_SEQUENCE:
  514.                 // If there is no sequence definition yet, create a default definition
  515.                 $definition $class->sequenceGeneratorDefinition;
  516.                 if (! $definition) {
  517.                     $fieldName    $class->getSingleIdentifierFieldName();
  518.                     $sequenceName $class->getSequenceName($this->getTargetPlatform());
  519.                     $quoted       = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']);
  520.                     $definition = [
  521.                         'sequenceName'      => $this->truncateSequenceName($sequenceName),
  522.                         'allocationSize'    => 1,
  523.                         'initialValue'      => 1,
  524.                     ];
  525.                     if ($quoted) {
  526.                         $definition['quoted'] = true;
  527.                     }
  528.                     $class->setSequenceGeneratorDefinition($definition);
  529.                 }
  530.                 $sequenceGenerator = new SequenceGenerator(
  531.                     $this->em->getConfiguration()->getQuoteStrategy()->getSequenceName($definition$class$this->getTargetPlatform()),
  532.                     (int) $definition['allocationSize']
  533.                 );
  534.                 $class->setIdGenerator($sequenceGenerator);
  535.                 break;
  536.             case ClassMetadata::GENERATOR_TYPE_NONE:
  537.                 $class->setIdGenerator(new AssignedGenerator());
  538.                 break;
  539.             case ClassMetadata::GENERATOR_TYPE_UUID:
  540.                 Deprecation::trigger(
  541.                     'doctrine/orm',
  542.                     'https://github.com/doctrine/orm/issues/7312',
  543.                     'Mapping for %s: the "UUID" id generator strategy is deprecated with no replacement',
  544.                     $class->name
  545.                 );
  546.                 $class->setIdGenerator(new UuidGenerator());
  547.                 break;
  548.             case ClassMetadata::GENERATOR_TYPE_CUSTOM:
  549.                 $definition $class->customGeneratorDefinition;
  550.                 if ($definition === null) {
  551.                     throw InvalidCustomGenerator::onClassNotConfigured();
  552.                 }
  553.                 if (! class_exists($definition['class'])) {
  554.                     throw InvalidCustomGenerator::onMissingClass($definition);
  555.                 }
  556.                 $class->setIdGenerator(new $definition['class']());
  557.                 break;
  558.             default:
  559.                 throw UnknownGeneratorType::create($class->generatorType);
  560.         }
  561.     }
  562.     /** @psalm-return ClassMetadata::GENERATOR_TYPE_SEQUENCE|ClassMetadata::GENERATOR_TYPE_IDENTITY */
  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. }