/lib/Doctrine/ORM/Mapping/Builder/ValueGeneratorMetadataBuilder.php

https://github.com/jaikdean/doctrine2 · PHP · 190 lines · 136 code · 46 blank · 8 comment · 7 complexity · 42975cb592dcf3f5479cc19023deed3b MD5 · raw file

  1. <?php
  2. declare(strict_types=1);
  3. namespace Doctrine\ORM\Mapping\Builder;
  4. use Doctrine\DBAL\Types\Type;
  5. use Doctrine\ORM\Annotation;
  6. use Doctrine\ORM\Mapping;
  7. use Doctrine\ORM\Mapping\Exception\TableGeneratorNotImplementedYet;
  8. use Doctrine\ORM\Mapping\Exception\UnknownGeneratorType;
  9. use Doctrine\ORM\Mapping\GeneratorType;
  10. use Doctrine\ORM\Sequencing\Generator;
  11. use ReflectionClass;
  12. use ReflectionException;
  13. use function assert;
  14. use function constant;
  15. use function in_array;
  16. use function sprintf;
  17. use function strtoupper;
  18. class ValueGeneratorMetadataBuilder
  19. {
  20. /** @var Mapping\ClassMetadataBuildingContext */
  21. private $metadataBuildingContext;
  22. /** @var Mapping\ClassMetadata */
  23. private $componentMetadata;
  24. /** @var string */
  25. private $fieldName;
  26. /** @var Type */
  27. private $fieldType;
  28. /** @var Annotation\GeneratedValue|null */
  29. private $generatedValueAnnotation;
  30. /** @var Annotation\SequenceGenerator|null */
  31. private $sequenceGeneratorAnnotation;
  32. /** @var Annotation\CustomIdGenerator|null */
  33. private $customIdGeneratorAnnotation;
  34. public function __construct(Mapping\ClassMetadataBuildingContext $metadataBuildingContext)
  35. {
  36. $this->metadataBuildingContext = $metadataBuildingContext;
  37. }
  38. public function withComponentMetadata(Mapping\ClassMetadata $componentMetadata) : ValueGeneratorMetadataBuilder
  39. {
  40. $this->componentMetadata = $componentMetadata;
  41. return $this;
  42. }
  43. public function withFieldName(string $fieldName) : ValueGeneratorMetadataBuilder
  44. {
  45. $this->fieldName = $fieldName;
  46. return $this;
  47. }
  48. public function withFieldType(Type $fieldType) : ValueGeneratorMetadataBuilder
  49. {
  50. $this->fieldType = $fieldType;
  51. return $this;
  52. }
  53. public function withGeneratedValueAnnotation(
  54. ?Annotation\GeneratedValue $generatedValueAnnotation
  55. ) : ValueGeneratorMetadataBuilder {
  56. $this->generatedValueAnnotation = $generatedValueAnnotation;
  57. return $this;
  58. }
  59. public function withSequenceGeneratorAnnotation(
  60. ?Annotation\SequenceGenerator $sequenceGeneratorAnnotation
  61. ) : ValueGeneratorMetadataBuilder {
  62. $this->sequenceGeneratorAnnotation = $sequenceGeneratorAnnotation;
  63. return $this;
  64. }
  65. public function withCustomIdGeneratorAnnotation(
  66. ?Annotation\CustomIdGenerator $customIdGeneratorAnnotation
  67. ) : ValueGeneratorMetadataBuilder {
  68. $this->customIdGeneratorAnnotation = $customIdGeneratorAnnotation;
  69. return $this;
  70. }
  71. public function build() : ?Mapping\ValueGeneratorMetadata
  72. {
  73. // Validate required fields
  74. assert($this->componentMetadata !== null);
  75. assert($this->fieldName !== null);
  76. assert($this->fieldType !== null);
  77. if (! $this->generatedValueAnnotation) {
  78. return null;
  79. }
  80. $platform = $this->metadataBuildingContext->getTargetPlatform();
  81. $strategy = strtoupper($this->generatedValueAnnotation->strategy);
  82. $generatorType = constant(sprintf('%s::%s', Mapping\GeneratorType::class, $strategy));
  83. if (in_array($generatorType, [Mapping\GeneratorType::AUTO, Mapping\GeneratorType::IDENTITY], true)) {
  84. $generatorType = $platform->prefersSequences() || $platform->usesSequenceEmulatedIdentityColumns()
  85. ? Mapping\GeneratorType::SEQUENCE
  86. : ($platform->prefersIdentityColumns() ? Mapping\GeneratorType::IDENTITY : Mapping\GeneratorType::TABLE);
  87. }
  88. switch ($generatorType) {
  89. case Mapping\GeneratorType::IDENTITY:
  90. $generator = $this->fieldType->getName() === 'bigint'
  91. ? new Generator\BigIntegerIdentityGenerator()
  92. : new Generator\IdentityGenerator();
  93. return new Mapping\ValueGeneratorMetadata($generatorType, $generator);
  94. break;
  95. case Mapping\GeneratorType::SEQUENCE:
  96. $sequenceName = null;
  97. $allocationSize = 1;
  98. if ($this->sequenceGeneratorAnnotation) {
  99. $sequenceName = $this->sequenceGeneratorAnnotation->sequenceName ?? null;
  100. $allocationSize = $this->sequenceGeneratorAnnotation->allocationSize ?? 1;
  101. }
  102. if (empty($sequenceName)) {
  103. $sequenceName = $platform->fixSchemaElementName(
  104. sprintf(
  105. '%s_%s_seq',
  106. $platform->getSequencePrefix(
  107. $this->componentMetadata->getTableName(),
  108. $this->componentMetadata->getSchemaName()
  109. ),
  110. $this->fieldName
  111. )
  112. );
  113. }
  114. $generator = new Generator\SequenceGenerator($sequenceName, $allocationSize);
  115. return new Mapping\ValueGeneratorMetadata($generatorType, $generator);
  116. break;
  117. case Mapping\GeneratorType::CUSTOM:
  118. assert($this->customIdGeneratorAnnotation !== null);
  119. if (empty($this->customIdGeneratorAnnotation->class)) {
  120. $message = 'Cannot instantiate custom generator, no class has been defined';
  121. throw new Mapping\MappingException($message);
  122. }
  123. try {
  124. $reflectionClass = new ReflectionClass($this->customIdGeneratorAnnotation->class);
  125. $generator = $reflectionClass->newInstanceArgs($this->customIdGeneratorAnnotation->arguments);
  126. return new Mapping\ValueGeneratorMetadata($generatorType, $generator);
  127. } catch (ReflectionException $exception) {
  128. $message = sprintf(
  129. 'Cannot instantiate custom generator : %s',
  130. $this->customIdGeneratorAnnotation->class
  131. );
  132. throw new Mapping\MappingException($message);
  133. }
  134. break;
  135. case GeneratorType::TABLE:
  136. throw TableGeneratorNotImplementedYet::create();
  137. case null: // Function constant() returns null if it is not defined in class.
  138. throw UnknownGeneratorType::create($strategy);
  139. case Mapping\GeneratorType::NONE:
  140. default:
  141. return null;
  142. }
  143. }
  144. }