Skip to content

Instantly share code, notes, and snippets.

@weaverryan weaverryan/UserNormalizer.php Secret
Last active Nov 18, 2019

Embed
What would you like to do?
Example of is owner denormalizer
<?php
namespace App\Serializer\Normalizer;
use App\Entity\User;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Serializer\Exception\BadMethodCallException;
use Symfony\Component\Serializer\Exception\ExceptionInterface;
use Symfony\Component\Serializer\Exception\ExtraAttributesException;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
use Symfony\Component\Serializer\Exception\LogicException;
use Symfony\Component\Serializer\Exception\RuntimeException;
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface;
use Symfony\Component\Serializer\Normalizer\ContextAwareDenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizerAwareTrait;
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
class UserNormalizer implements ContextAwareNormalizerInterface, CacheableSupportsMethodInterface, NormalizerAwareInterface, ContextAwareDenormalizerInterface, DenormalizerAwareInterface
{
use NormalizerAwareTrait;
use DenormalizerAwareTrait;
private const ALREADY_CALLED = 'USER_NORMALIZER_ALREADY_CALLED';
private $security;
/**
* @var RequestStack
*/
private $requestStack;
public function __construct(Security $security, RequestStack $requestStack)
{
$this->security = $security;
$this->requestStack = $requestStack;
}
/**
* @param User $object
*/
public function normalize($object, $format = null, array $context = array()): array
{
if ($this->userIsOwner($object)) {
$context['groups'][] = 'owner:read';
}
$context[self::ALREADY_CALLED] = true;
$data = $this->normalizer->normalize($object, $format, $context);
// Here: add, edit, or delete some data
return $data;
}
public function supportsNormalization($data, $format = null, array $context = [])
{
// avoid recursion: only call once per object
if (isset($context[self::ALREADY_CALLED])) {
return false;
}
return $data instanceof User;
}
private function userIsOwner(User $user): bool
{
/** @var User|null $authenticatedUser */
$authenticatedUser = $this->security->getUser();
if (!$authenticatedUser) {
return false;
}
return $authenticatedUser->getEmail() === $user->getEmail();
}
public function hasCacheableSupportsMethod(): bool
{
return false;
}
public function supportsDenormalization($data, $type, $format = null, array $context = [])
{
// avoid recursion: only call once per object
if (isset($context[self::ALREADY_CALLED])) {
return false;
}
return $type === User::class;
}
public function denormalize($data, $class, $format = null, array $context = [])
{
$context[self::ALREADY_CALLED] = true;
/** @var User $apiResource */
$apiResource = $this->requestStack->getCurrentRequest()
->attributes->get('data');
if ($this->userIsOwner($apiResource)) {
$context['groups'][] = 'owner:write';
}
$object = $this->denormalizer->denormalize($data, $class, $format, $context);
if (!$object instanceof User) {
throw new \Exception('This should be a User! Something went wrong!');
}
return $object;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.