vendor/easycorp/easyadmin-bundle/src/Dto/EntityDto.php line 15

Open in your IDE?
  1. <?php
  2. namespace EasyCorp\Bundle\EasyAdminBundle\Dto;
  3. use Doctrine\ORM\Mapping\ClassMetadataInfo;
  4. use Doctrine\Persistence\Mapping\ClassMetadata;
  5. use EasyCorp\Bundle\EasyAdminBundle\Collection\ActionCollection;
  6. use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
  7. use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore;
  8. use Symfony\Component\PropertyAccess\PropertyAccess;
  9. /**
  10. * @author Javier Eguiluz <javier.eguiluz@gmail.com>
  11. */
  12. final class EntityDto
  13. {
  14. private $isAccessible;
  15. private $fqcn;
  16. private $metadata;
  17. private $instance;
  18. private $primaryKeyName;
  19. private $primaryKeyValue;
  20. private $permission;
  21. /** @var ?FieldCollection */
  22. private $fields;
  23. /** @var ActionCollection */
  24. private $actions;
  25. public function __construct(string $entityFqcn, ClassMetadata $entityMetadata, ?string $entityPermission = null, $entityInstance = null)
  26. {
  27. $this->isAccessible = true;
  28. $this->fqcn = $entityFqcn;
  29. $this->metadata = $entityMetadata;
  30. $this->instance = $entityInstance;
  31. $this->primaryKeyName = $this->metadata->getIdentifierFieldNames()[0];
  32. $this->permission = $entityPermission;
  33. }
  34. public function __toString(): string
  35. {
  36. return $this->toString();
  37. }
  38. public function getFqcn(): string
  39. {
  40. return $this->fqcn;
  41. }
  42. public function getName(): string
  43. {
  44. return basename(str_replace('\\', '/', $this->fqcn));
  45. }
  46. public function toString(): string
  47. {
  48. if (null === $this->instance) {
  49. return '';
  50. }
  51. if (method_exists($this->instance, '__toString')) {
  52. return (string) $this->instance;
  53. }
  54. return sprintf('%s #%s', $this->getName(), substr($this->getPrimaryKeyValueAsString(), 0, 16));
  55. }
  56. public function getInstance()
  57. {
  58. return $this->instance;
  59. }
  60. public function getPrimaryKeyName(): ?string
  61. {
  62. return $this->primaryKeyName;
  63. }
  64. public function getPrimaryKeyValue()
  65. {
  66. if (null === $this->instance) {
  67. return null;
  68. }
  69. if (null !== $this->primaryKeyValue) {
  70. return $this->primaryKeyValue;
  71. }
  72. $propertyAccessor = PropertyAccess::createPropertyAccessorBuilder()
  73. ->enableExceptionOnInvalidIndex()
  74. ->getPropertyAccessor();
  75. $primaryKeyValue = $propertyAccessor->getValue($this->instance, $this->primaryKeyName);
  76. return $this->primaryKeyValue = $primaryKeyValue;
  77. }
  78. public function getPrimaryKeyValueAsString(): string
  79. {
  80. return (string) $this->getPrimaryKeyValue();
  81. }
  82. public function getPermission(): ?string
  83. {
  84. return $this->permission;
  85. }
  86. public function isAccessible(): bool
  87. {
  88. return $this->isAccessible;
  89. }
  90. public function markAsInaccessible(): void
  91. {
  92. $this->isAccessible = false;
  93. $this->instance = null;
  94. $this->fields = null;
  95. }
  96. public function getFields(): ?FieldCollection
  97. {
  98. return $this->fields;
  99. }
  100. public function setFields(FieldCollection $fields): void
  101. {
  102. $this->fields = $fields;
  103. }
  104. public function setActions(ActionCollection $actions): void
  105. {
  106. $this->actions = $actions;
  107. }
  108. public function getActions(): ActionCollection
  109. {
  110. return $this->actions;
  111. }
  112. /**
  113. * Returns the names of all properties defined in the entity, no matter
  114. * if they are used or not in the application.
  115. */
  116. public function getAllPropertyNames(): array
  117. {
  118. return $this->metadata->getFieldNames();
  119. }
  120. public function getPropertyMetadata(string $propertyName): KeyValueStore
  121. {
  122. if (null === $this->metadata) {
  123. return KeyValueStore::new();
  124. }
  125. if (\array_key_exists($propertyName, $this->metadata->fieldMappings)) {
  126. return KeyValueStore::new($this->metadata->fieldMappings[$propertyName]);
  127. }
  128. if (\array_key_exists($propertyName, $this->metadata->associationMappings)) {
  129. return KeyValueStore::new($this->metadata->associationMappings[$propertyName]);
  130. }
  131. throw new \InvalidArgumentException(sprintf('The "%s" field does not exist in the "%s" entity.', $propertyName, $this->getFqcn()));
  132. }
  133. public function getPropertyDataType(string $propertyName)
  134. {
  135. return $this->getPropertyMetadata($propertyName)->get('type');
  136. }
  137. public function hasProperty(string $propertyName): bool
  138. {
  139. return \array_key_exists($propertyName, $this->metadata->fieldMappings)
  140. || \array_key_exists($propertyName, $this->metadata->associationMappings);
  141. }
  142. public function isAssociation(string $propertyName): bool
  143. {
  144. return \array_key_exists($propertyName, $this->metadata->associationMappings)
  145. || (false !== strpos($propertyName, '.') && !$this->isEmbeddedClassProperty($propertyName));
  146. }
  147. public function isToOneAssociation(string $propertyName): bool
  148. {
  149. $associationType = $this->getPropertyMetadata($propertyName)->get('type');
  150. return \in_array($associationType, [ClassMetadataInfo::ONE_TO_ONE, ClassMetadataInfo::MANY_TO_ONE], true);
  151. }
  152. public function isToManyAssociation(string $propertyName): bool
  153. {
  154. $associationType = $this->getPropertyMetadata($propertyName)->get('type');
  155. return \in_array($associationType, [ClassMetadataInfo::ONE_TO_MANY, ClassMetadataInfo::MANY_TO_MANY], true);
  156. }
  157. public function isEmbeddedClassProperty(string $propertyName): bool
  158. {
  159. $propertyNameParts = explode('.', $propertyName, 2);
  160. return \array_key_exists($propertyNameParts[0], $this->metadata->embeddedClasses);
  161. }
  162. public function setInstance($newEntityInstance): void
  163. {
  164. if (null !== $this->instance && !$newEntityInstance instanceof $this->fqcn) {
  165. throw new \InvalidArgumentException(sprintf('The new entity instance must be of the same type as the previous instance (original instance: "%s", new instance: "%s").', $this->fqcn, \get_class($newEntityInstance)));
  166. }
  167. $this->instance = $newEntityInstance;
  168. $this->primaryKeyValue = null;
  169. }
  170. public function newWithInstance($newEntityInstance): self
  171. {
  172. if (null !== $this->instance && !$newEntityInstance instanceof $this->fqcn) {
  173. throw new \InvalidArgumentException(sprintf('The new entity instance must be of the same type as the previous instance (original instance: "%s", new instance: "%s").', $this->fqcn, \get_class($newEntityInstance)));
  174. }
  175. return new self($this->fqcn, $this->metadata, $this->permission, $newEntityInstance);
  176. }
  177. }