1<?php
2
3declare(strict_types=1);
4
5namespace JMS\Serializer\Handler;
6
7use JMS\Serializer\Exception\InvalidArgumentException;
8use Psr\Container\ContainerInterface as PsrContainerInterface;
9use Symfony\Component\DependencyInjection\ContainerInterface;
10
11final class LazyHandlerRegistry extends HandlerRegistry
12{
13    /**
14     * @var PsrContainerInterface|ContainerInterface
15     */
16    private $container;
17
18    /**
19     * @var array
20     */
21    private $initializedHandlers = [];
22
23    /**
24     * @param PsrContainerInterface|ContainerInterface $container
25     * @param array $handlers
26     */
27    public function __construct($container, array $handlers = [])
28    {
29        if (!$container instanceof PsrContainerInterface && !$container instanceof ContainerInterface) {
30            throw new InvalidArgumentException(sprintf('The container must be an instance of %s or %s (%s given).', PsrContainerInterface::class, ContainerInterface::class, \is_object($container) ? \get_class($container) : \gettype($container)));
31        }
32
33        parent::__construct($handlers);
34        $this->container = $container;
35    }
36
37    /**
38     * {@inheritdoc}
39     */
40    public function registerHandler(int $direction, string $typeName, string $format, $handler): void
41    {
42        parent::registerHandler($direction, $typeName, $format, $handler);
43        unset($this->initializedHandlers[$direction][$typeName][$format]);
44    }
45
46    /**
47     * {@inheritdoc}
48     */
49    public function getHandler(int $direction, string $typeName, string $format)
50    {
51        if (isset($this->initializedHandlers[$direction][$typeName][$format])) {
52            return $this->initializedHandlers[$direction][$typeName][$format];
53        }
54
55        if (!isset($this->handlers[$direction][$typeName][$format])) {
56            return null;
57        }
58
59        $handler = $this->handlers[$direction][$typeName][$format];
60        if (\is_array($handler) && \is_string($handler[0]) && $this->container->has($handler[0])) {
61            $handler[0] = $this->container->get($handler[0]);
62        }
63
64        return $this->initializedHandlers[$direction][$typeName][$format] = $handler;
65    }
66}
67