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

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