Lullabot/mpx-php

View on GitHub
src/Normalizer/UnixMillisecondNormalizer.php

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
<?php

namespace Lullabot\Mpx\Normalizer;

use Lullabot\Mpx\DataService\DateTime\ConcreteDateTime;
use Lullabot\Mpx\DataService\DateTime\ConcreteDateTimeInterface;
use Lullabot\Mpx\DataService\DateTime\DateTimeFormatInterface;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

/**
 * Denormalize a millisecond timestamp into a date object.
 *
 * Note this doesn't extend the
 * \Symfony\Component\Serializer\Normalizer\DateTimeNormalizer normalizer
 * directly because the ::denormalize() method in that class is typehinted to
 * \DateTimeInterface but we want to return a ConcreteDateTime object instead.
 * Because of this, we decorate here a DateTimeNormalizer object and delegate
 * all methods but ::denormalize().
 */
class UnixMillisecondNormalizer implements NormalizerInterface, DenormalizerInterface, CacheableSupportsMethodInterface
{
    /**
     * @var \Symfony\Component\Serializer\Normalizer\DateTimeNormalizer
     */
    private $decorated;

    private static array $supportedTypes = [
        DateTimeFormatInterface::class => true,
        ConcreteDateTimeInterface::class => true,
        ConcreteDateTime::class => true,
    ];

    public function __construct(array $defaultContext = [])
    {
        $this->decorated = new DateTimeNormalizer($defaultContext);
    }

    public function setDefaultContext(array $defaultContext): void
    {
        $this->decorated->setDefaultContext($defaultContext);
    }

    public function getSupportedTypes(?string $format): array
    {
        return self::$supportedTypes;
    }

    /**
     * @throws InvalidArgumentException
     */
    public function normalize(mixed $object, string $format = null, array $context = []): string
    {
        return $this->decorated->normalize($object, $format, $context);
    }

    public function supportsNormalization(mixed $data, string $format = null): bool
    {
        return $this->decorated->supportsNormalization($data, $format);
    }

    public function denormalize(mixed $data, string $type, string $format = null, array $context = []): ConcreteDateTime
    {
        if (!\is_int($data)) {
            throw new NotNormalizableValueException('The data is not an integer, you should pass an integer representing the unix time in milliseconds.');
        }

        $seconds = floor($data / 1000);
        $remainder = $data % 1000;
        $bySeconds = "$seconds.$remainder";

        $context[$this->decorated::FORMAT_KEY] = 'U.u';

        $date = $this->decorated->denormalize($bySeconds, \DateTime::class, $format, $context);

        return new ConcreteDateTime($date);
    }

    public function supportsDenormalization(mixed $data, string $type, string $format = null): bool
    {
        return isset(self::$supportedTypes[$type]);
    }

    /**
     * @deprecated since Symfony 6.3, use "getSupportedTypes()" instead
     */
    public function hasCacheableSupportsMethod(): bool
    {
        return $this->decorated->hasCacheableSupportsMethod();
    }
}