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

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