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

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