<?php
declare(strict_types=1);
/**
* @author Piotr Kowalski <piotr.kowalski@autentika.pl>
* date: 2018-02-15 14:52
*/
namespace Hitso\Bundle\CommonBundle\Serializer;
use Doctrine\ORM\EntityManagerInterface;
use Hitso\Bundle\CommonBundle\Entity\EntityInterface;
use Hitso\Bundle\CommonBundle\Serializer\Extractor\EntityExtractor;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Webmozart\Assert\Assert;
/**
* Class ContentNormalizer.
*/
class EntityNormalizer extends ObjectNormalizer
{
/**
* @var EntityManagerInterface
*/
protected $entityManager;
/**
* ContentNormalizer constructor.
*
* @param ClassMetadataFactoryInterface|null $classMetadataFactory
* @param NameConverterInterface|null $nameConverter
* @param PropertyAccessorInterface|null $propertyAccessor
* @param EntityExtractor|null $propTypeExtractor
*/
public function __construct(
ClassMetadataFactoryInterface $classMetadataFactory = null,
NameConverterInterface $nameConverter = null,
PropertyAccessorInterface $propertyAccessor = null,
EntityExtractor $propTypeExtractor = null,
EntityManagerInterface $entityManager = null
) {
parent::__construct($classMetadataFactory, $nameConverter, $propertyAccessor, $propTypeExtractor);
Assert::notNull($entityManager);
$this->entityManager = $entityManager;
$this
->setCircularReferenceLimit(1)
->setCircularReferenceHandler(
function (EntityInterface $entity) {
return $entity->getId();
}
);
}
/**
* {@inheritdoc}
*/
public function supportsDenormalization($data, $type, $format = null)
{
return is_a($type, EntityInterface::class, true);
}
/**
* {@inheritdoc}
*/
public function supportsNormalization($data, $format = null)
{
return $data instanceof EntityInterface;
}
/**
* {@inheritdoc}
*/
public function denormalize($data, $class, $format = null, array $context = [])
{
if (!empty($data['attributes'])) {
$data = $data['attributes'];
}
$metadata = $this->entityManager->getClassMetadata($class);
$idFieldName = $metadata->getSingleIdentifierFieldName();
$allowedAttributes = $this->getAllowedAttributes($class, $context, true);
if (in_array($idFieldName, $allowedAttributes) && !empty($data[$idFieldName])) {
$idValue = $data[$idFieldName];
$entity = $this->entityManager
->getRepository($class)
->findOneBy([$idFieldName => $idValue]);
if ($entity) {
return $entity;
}
unset($data[$idFieldName]);
}
return parent::denormalize($data, $class, $format, $context);
}
public function normalize($object, $format = null, array $context = [])
{
/* @var Element $object */
return [
'id' => $object->getId(),
'attributes' => parent::normalize($object, $format, $context),
];
}
}