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

Open in your IDE?
  1. <?php
  2. namespace EasyCorp\Bundle\EasyAdminBundle\Dto;
  3. use Doctrine\ORM\Mapping\ClassMetadata;
  4. use Doctrine\ORM\Mapping\FieldMapping;
  5. use Doctrine\ORM\Mapping\ManyToManyAssociationMapping;
  6. use Doctrine\ORM\Mapping\ManyToOneAssociationMapping;
  7. use Doctrine\ORM\Mapping\OneToManyAssociationMapping;
  8. use Doctrine\ORM\Mapping\OneToOneAssociationMapping;
  9. use EasyCorp\Bundle\EasyAdminBundle\Collection\ActionCollection;
  10. use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
  11. use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore;
  12. use Symfony\Component\ExpressionLanguage\Expression;
  13. use Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException;
  14. use Symfony\Component\PropertyAccess\PropertyAccess;
  15. /**
  16.  * @author Javier Eguiluz <javier.eguiluz@gmail.com>
  17.  */
  18. final class EntityDto
  19. {
  20.     private bool $isAccessible true;
  21.     private string $fqcn;
  22.     private ClassMetadata $metadata;
  23.     private $instance;
  24.     private $primaryKeyName;
  25.     private mixed $primaryKeyValue null;
  26.     private string|Expression|null $permission;
  27.     private ?FieldCollection $fields null;
  28.     private ?ActionCollection $actions null;
  29.     public function __construct(string $entityFqcnClassMetadata $entityMetadatastring|Expression|null $entityPermission null/* ?object */ $entityInstance null)
  30.     {
  31.         if (!\is_object($entityInstance)
  32.             && null !== $entityInstance) {
  33.             trigger_deprecation(
  34.                 'easycorp/easyadmin-bundle',
  35.                 '4.0.5',
  36.                 'Argument "%s" for "%s" must be one of these types: %s. Passing type "%s" will cause an error in 5.0.0.',
  37.                 '$entityInstance',
  38.                 __METHOD__,
  39.                 '"object" or "null"',
  40.                 \gettype($entityInstance)
  41.             );
  42.         }
  43.         $this->fqcn $entityFqcn;
  44.         $this->metadata $entityMetadata;
  45.         $this->instance $entityInstance;
  46.         $this->primaryKeyName $this->metadata->getIdentifierFieldNames()[0];
  47.         $this->permission $entityPermission;
  48.     }
  49.     public function __toString(): string
  50.     {
  51.         return $this->toString();
  52.     }
  53.     public function getFqcn(): string
  54.     {
  55.         return $this->fqcn;
  56.     }
  57.     public function getName(): string
  58.     {
  59.         return basename(str_replace('\\''/'$this->fqcn));
  60.     }
  61.     public function toString(): string
  62.     {
  63.         if (null === $this->instance) {
  64.             return '';
  65.         }
  66.         if (method_exists($this->instance'__toString')) {
  67.             return (string) $this->instance;
  68.         }
  69.         return sprintf('%s #%s'$this->getName(), substr($this->getPrimaryKeyValueAsString(), 016));
  70.     }
  71.     public function getInstance()/* : ?object */
  72.     {
  73.         return $this->instance;
  74.     }
  75.     public function getPrimaryKeyName(): ?string
  76.     {
  77.         return $this->primaryKeyName;
  78.     }
  79.     public function getPrimaryKeyValue(): mixed
  80.     {
  81.         if (null === $this->instance) {
  82.             return null;
  83.         }
  84.         if (null !== $this->primaryKeyValue) {
  85.             return $this->primaryKeyValue;
  86.         }
  87.         $propertyAccessor PropertyAccess::createPropertyAccessorBuilder()
  88.             ->enableExceptionOnInvalidIndex()
  89.             ->getPropertyAccessor();
  90.         try {
  91.             $primaryKeyValue $propertyAccessor->getValue($this->instance$this->primaryKeyName);
  92.         } catch (UninitializedPropertyException $exception) {
  93.             $primaryKeyValue null;
  94.         }
  95.         return $this->primaryKeyValue $primaryKeyValue;
  96.     }
  97.     public function getPrimaryKeyValueAsString(): string
  98.     {
  99.         return (string) $this->getPrimaryKeyValue();
  100.     }
  101.     public function getPermission(): string|Expression|null
  102.     {
  103.         return $this->permission;
  104.     }
  105.     public function isAccessible(): bool
  106.     {
  107.         return $this->isAccessible;
  108.     }
  109.     public function markAsInaccessible(): void
  110.     {
  111.         $this->isAccessible false;
  112.         $this->instance null;
  113.         $this->fields null;
  114.     }
  115.     public function getFields(): ?FieldCollection
  116.     {
  117.         return $this->fields;
  118.     }
  119.     public function setFields(FieldCollection $fields): void
  120.     {
  121.         $this->fields $fields;
  122.     }
  123.     public function setActions(ActionCollection $actions): void
  124.     {
  125.         $this->actions $actions;
  126.     }
  127.     public function getActions(): ActionCollection
  128.     {
  129.         return $this->actions;
  130.     }
  131.     /**
  132.      * Returns the names of all properties defined in the entity, no matter
  133.      * if they are used or not in the application.
  134.      */
  135.     public function getAllPropertyNames(): array
  136.     {
  137.         return $this->metadata->getFieldNames();
  138.     }
  139.     public function getPropertyMetadata(string $propertyName): KeyValueStore
  140.     {
  141.         if (\array_key_exists($propertyName$this->metadata->fieldMappings)) {
  142.             /** @var FieldMapping|array $fieldMapping */
  143.             $fieldMapping $this->metadata->fieldMappings[$propertyName];
  144.             // Doctrine ORM 2.x returns an array and Doctrine ORM 3.x returns a FieldMapping object
  145.             if ($fieldMapping instanceof FieldMapping) {
  146.                 $fieldMapping = (array) $fieldMapping;
  147.             }
  148.             return KeyValueStore::new($fieldMapping);
  149.         }
  150.         if (\array_key_exists($propertyName$this->metadata->associationMappings)) {
  151.             /** @var OneToOneAssociationMapping|OneToManyAssociationMapping|ManyToOneAssociationMapping|ManyToManyAssociationMapping|array $associationMapping */
  152.             $associationMapping $this->metadata->associationMappings[$propertyName];
  153.             // Doctrine ORM 2.x returns an array and Doctrine ORM 3.x returns one of the many *Mapping objects
  154.             // there's not a single interface implemented by all of them, so let's only check if it's an object
  155.             if (\is_object($associationMapping)) {
  156.                 // Doctrine ORM 3.x doesn't include the 'type' key that tells the type of association
  157.                 // recreate that key to keep the code compatible with both versions
  158.                 $associationType = match (true) {
  159.                     $associationMapping instanceof OneToOneAssociationMapping => ClassMetadata::ONE_TO_ONE,
  160.                     $associationMapping instanceof OneToManyAssociationMapping => ClassMetadata::ONE_TO_MANY,
  161.                     $associationMapping instanceof ManyToOneAssociationMapping => ClassMetadata::MANY_TO_ONE,
  162.                     $associationMapping instanceof ManyToManyAssociationMapping => ClassMetadata::MANY_TO_MANY,
  163.                     default => null,
  164.                 };
  165.                 $associationMapping = (array) $associationMapping;
  166.                 $associationMapping['type'] = $associationType;
  167.             }
  168.             return KeyValueStore::new($associationMapping);
  169.         }
  170.         throw new \InvalidArgumentException(sprintf('The "%s" field does not exist in the "%s" entity.'$propertyName$this->getFqcn()));
  171.     }
  172.     public function getPropertyDataType(string $propertyName)
  173.     {
  174.         return $this->getPropertyMetadata($propertyName)->get('type');
  175.     }
  176.     public function hasProperty(string $propertyName): bool
  177.     {
  178.         return \array_key_exists($propertyName$this->metadata->fieldMappings)
  179.             || \array_key_exists($propertyName$this->metadata->associationMappings);
  180.     }
  181.     public function isAssociation(string $propertyName): bool
  182.     {
  183.         return \array_key_exists($propertyName$this->metadata->associationMappings)
  184.             || (str_contains($propertyName'.') && !$this->isEmbeddedClassProperty($propertyName));
  185.     }
  186.     public function isToOneAssociation(string $propertyName): bool
  187.     {
  188.         $associationType $this->getPropertyMetadata($propertyName)->get('type');
  189.         return \in_array($associationType, [ClassMetadata::ONE_TO_ONEClassMetadata::MANY_TO_ONE], true);
  190.     }
  191.     public function isToManyAssociation(string $propertyName): bool
  192.     {
  193.         $associationType $this->getPropertyMetadata($propertyName)->get('type');
  194.         return \in_array($associationType, [ClassMetadata::ONE_TO_MANYClassMetadata::MANY_TO_MANY], true);
  195.     }
  196.     public function isEmbeddedClassProperty(string $propertyName): bool
  197.     {
  198.         $propertyNameParts explode('.'$propertyName2);
  199.         return \array_key_exists($propertyNameParts[0], $this->metadata->embeddedClasses);
  200.     }
  201.     public function setInstance(?object $newEntityInstance): void
  202.     {
  203.         if (null !== $this->instance && null !== $newEntityInstance && !$newEntityInstance instanceof $this->fqcn) {
  204.             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$newEntityInstance::class));
  205.         }
  206.         $this->instance $newEntityInstance;
  207.         $this->primaryKeyValue null;
  208.     }
  209.     public function newWithInstance(/* object */ $newEntityInstance): self
  210.     {
  211.         if (!\is_object($newEntityInstance)) {
  212.             trigger_deprecation(
  213.                 'easycorp/easyadmin-bundle',
  214.                 '4.0.5',
  215.                 'Argument "%s" for "%s" must be one of these types: %s. Passing type "%s" will cause an error in 5.0.0.',
  216.                 '$newEntityInstance',
  217.                 __METHOD__,
  218.                 '"object"',
  219.                 \gettype($newEntityInstance)
  220.             );
  221.         }
  222.         if (null !== $this->instance && !$newEntityInstance instanceof $this->fqcn) {
  223.             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$newEntityInstance::class));
  224.         }
  225.         return new self($this->fqcn$this->metadata$this->permission$newEntityInstance);
  226.     }
  227. }