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

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