vendor/symfony/doctrine-bridge/Form/ChoiceList/IdReader.php line 25

  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Bridge\Doctrine\Form\ChoiceList;
  11. use Doctrine\Persistence\Mapping\ClassMetadata;
  12. use Doctrine\Persistence\ObjectManager;
  13. use Symfony\Component\Form\Exception\RuntimeException;
  14. /**
  15. * A utility for reading object IDs.
  16. *
  17. * @author Bernhard Schussek <bschussek@gmail.com>
  18. *
  19. * @internal
  20. */
  21. class IdReader
  22. {
  23. private readonly bool $singleId;
  24. private readonly bool $intId;
  25. private readonly string $idField;
  26. private readonly ?self $associationIdReader;
  27. public function __construct(
  28. private readonly ObjectManager $om,
  29. private readonly ClassMetadata $classMetadata,
  30. ) {
  31. $ids = $classMetadata->getIdentifierFieldNames();
  32. $idType = $classMetadata->getTypeOfField(current($ids));
  33. $singleId = 1 === \count($ids);
  34. $this->idField = current($ids);
  35. // single field association are resolved, since the schema column could be an int
  36. if ($singleId && $classMetadata->hasAssociation($this->idField)) {
  37. $this->associationIdReader = new self($om, $om->getClassMetadata(
  38. $classMetadata->getAssociationTargetClass($this->idField)
  39. ));
  40. $singleId = $this->associationIdReader->isSingleId();
  41. $this->intId = $this->associationIdReader->isIntId();
  42. } else {
  43. $this->intId = $singleId && \in_array($idType, ['integer', 'smallint', 'bigint']);
  44. $this->associationIdReader = null;
  45. }
  46. $this->singleId = $singleId;
  47. }
  48. /**
  49. * Returns whether the class has a single-column ID.
  50. */
  51. public function isSingleId(): bool
  52. {
  53. return $this->singleId;
  54. }
  55. /**
  56. * Returns whether the class has a single-column integer ID.
  57. */
  58. public function isIntId(): bool
  59. {
  60. return $this->intId;
  61. }
  62. /**
  63. * Returns the ID value for an object.
  64. *
  65. * This method assumes that the object has a single-column ID.
  66. */
  67. public function getIdValue(?object $object = null): string
  68. {
  69. if (!$object) {
  70. return '';
  71. }
  72. if (!$this->om->contains($object)) {
  73. throw new RuntimeException(sprintf('Entity of type "%s" passed to the choice field must be managed. Maybe you forget to persist it in the entity manager?', get_debug_type($object)));
  74. }
  75. $this->om->initializeObject($object);
  76. $idValue = current($this->classMetadata->getIdentifierValues($object));
  77. if ($this->associationIdReader) {
  78. $idValue = $this->associationIdReader->getIdValue($idValue);
  79. }
  80. return (string) $idValue;
  81. }
  82. /**
  83. * Returns the name of the ID field.
  84. *
  85. * This method assumes that the object has a single-column ID.
  86. */
  87. public function getIdField(): string
  88. {
  89. return $this->idField;
  90. }
  91. }