Last active
February 12, 2024 23:05
-
-
Save kmuenkel/a35ad658e30f5c80f35b7669e5b58492 to your computer and use it in GitHub Desktop.
Entity to array
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* @throws \Psr\Container\ContainerExceptionInterface | |
* @throws \Psr\Container\NotFoundExceptionInterface | |
*/ | |
$self = function entityToArray( | |
\Chess\WebBundle\Entity\EntityInterface|array $entity, | |
\Chess\WebBundle\Doctrine\ORM\EntityRepository|\Doctrine\ORM\EntityManager|string $manager = null, | |
\Psr\Container\ContainerInterface $container = null | |
) use(&$self): array { | |
if (!$entity) { | |
return []; | |
} | |
if (is_array($entity)) { | |
return array_map(fn ($item) => $self($item, $depth, $manager, $container), $entity); | |
} | |
if (!$container) { | |
require_once __DIR__ . '/../app/AppKernel.php'; | |
$kernel = new AppKernel('test', true); | |
$kernel->boot(); | |
$container = $kernel->getContainer(); | |
} | |
$entityManagerName = is_string($manager) ? $manager | |
: ($manager instanceof \Doctrine\ORM\EntityRepository | |
? ($manager->getConnection()?->getParams()['name'] ?: 'default') : 'default'); | |
/** @var \Doctrine\ORM\EntityManager $entityManager */ | |
$entityManager = $manager instanceof \Doctrine\ORM\EntityManager ? $manager | |
: $container->get('doctrine.orm.' . $entityManagerName . '_entity_manager'); | |
if ($entityManagerName == 'default' && null === $manager) { | |
try { | |
$entityManager->getRepository(get_class($entity)); | |
} catch (\Doctrine\Persistence\Mapping\MappingException) { | |
$entityManagers = []; | |
/** @var \Doctrine\ORM\EntityManagerInterface $entityManager */ | |
foreach ($container->get('doctrine')->getManagers() as $entityManager) { | |
try { | |
$entityManager->getRepository(get_class($entity)); | |
$entityManagers[] = $entityManager; | |
break; | |
} catch (\Doctrine\Persistence\Mapping\MappingException) { | |
} | |
} | |
if (count($entityManagers) != 1) { | |
throw new RuntimeException('Unable to identify a single EntityManager.'); | |
} | |
$entityManager = current($entityManagers); | |
} | |
} | |
$values = ($entityToArray = function ( | |
?Chess\WebBundle\Entity\EntityInterface $entity, | |
Doctrine\ORM\Mapping\ClassMetadataFactory $entityManager, | |
$depth | |
) use (&$entityToArray): array { | |
static $records = []; | |
if (in_array($recordId = $entity::class . '@' . $entity->getId(), $records)) { | |
return [$recordId => '{{RECURSION DETECTED}}']; | |
} | |
$records[] = $recordId; | |
$entityMetaData = $entityManager->getMetadataFor($entity::class); | |
$properties = array_keys($entityMetaData->getReflectionProperties()); | |
$values = array_map(function (string $property) use ($entityToArray, $entityMetaData, $entity, $entityManager, $depth) { | |
$value = $entityMetaData->getFieldValue($entity, $property); | |
return ($normalize = function ($value) use (&$normalize, $entityToArray, $entityManager, $depth) { | |
static $level = 0; | |
++$level; | |
if ($level > 5) { | |
throw new RuntimeException('Recursion detected'); | |
} | |
if ($value instanceof DateTimeImmutable || $value instanceof DateTime) { | |
$value = $value->format($value::ATOM); | |
} elseif (is_object($value) && in_array('__toString', get_class_methods($value))) { | |
$value = (string) $value; | |
$value = json_decode($value, true) ?: $value; | |
} elseif ($value instanceof \Chess\WebBundle\Entity\EntityInterface) { | |
$value = ($depth && $level >= $depth) ? '_DEPTH_REACHED' : $entityToArray($value, $entityManager, $depth); | |
} elseif ($value instanceof \Chess\Common\JsonData\DataTypeInterface) { | |
$properties = (new ReflectionClass($value))->getProperties(); | |
$values = array_map(fn (ReflectionProperty $property) => $normalize($property->getValue($value)), $properties); | |
$names = array_map(fn (ReflectionProperty $property): string => $property->name, $properties); | |
$value = array_combine($names, $values); | |
} elseif ($value instanceof \Doctrine\ORM\PersistentCollection) { | |
$value = array_map(fn ($collectionValue) => $normalize($collectionValue), $value->getValues()); | |
} elseif ($value instanceof stdClass) { | |
$value = json_decode(json_encode($value)); | |
} elseif (is_object($value)) { | |
$value = (array) $value; | |
} elseif (is_string($value) && ($decoded = json_decode($value, true))) { | |
$value = $decoded; | |
} | |
--$level; | |
return $value; | |
})($value); | |
}, $properties); | |
return array_combine($properties, $values); | |
})($entity, $entityManager->getMetadataFactory(), $depth); | |
return $values; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment