1<?php
2
3declare(strict_types=1);
4
5namespace JMS\Serializer\Handler;
6
7use Doctrine\Common\Collections\ArrayCollection;
8use Doctrine\Common\Collections\Collection;
9use JMS\Serializer\DeserializationContext;
10use JMS\Serializer\GraphNavigatorInterface;
11use JMS\Serializer\SerializationContext;
12use JMS\Serializer\Visitor\DeserializationVisitorInterface;
13use JMS\Serializer\Visitor\SerializationVisitorInterface;
14
15final class ArrayCollectionHandler implements SubscribingHandlerInterface
16{
17    /**
18     * @var bool
19     */
20    private $initializeExcluded = true;
21
22    public function __construct(bool $initializeExcluded = true)
23    {
24        $this->initializeExcluded = $initializeExcluded;
25    }
26
27    /**
28     * {@inheritdoc}
29     */
30    public static function getSubscribingMethods()
31    {
32        $methods = [];
33        $formats = ['json', 'xml', 'yml'];
34        $collectionTypes = [
35            'ArrayCollection',
36            'Doctrine\Common\Collections\ArrayCollection',
37            'Doctrine\ORM\PersistentCollection',
38            'Doctrine\ODM\MongoDB\PersistentCollection',
39            'Doctrine\ODM\PHPCR\PersistentCollection',
40        ];
41
42        foreach ($collectionTypes as $type) {
43            foreach ($formats as $format) {
44                $methods[] = [
45                    'direction' => GraphNavigatorInterface::DIRECTION_SERIALIZATION,
46                    'type' => $type,
47                    'format' => $format,
48                    'method' => 'serializeCollection',
49                ];
50
51                $methods[] = [
52                    'direction' => GraphNavigatorInterface::DIRECTION_DESERIALIZATION,
53                    'type' => $type,
54                    'format' => $format,
55                    'method' => 'deserializeCollection',
56                ];
57            }
58        }
59
60        return $methods;
61    }
62
63    /**
64     * @return array|\ArrayObject
65     */
66    public function serializeCollection(SerializationVisitorInterface $visitor, Collection $collection, array $type, SerializationContext $context)
67    {
68        // We change the base type, and pass through possible parameters.
69        $type['name'] = 'array';
70
71        $context->stopVisiting($collection);
72
73        if (false === $this->initializeExcluded) {
74            $exclusionStrategy = $context->getExclusionStrategy();
75            if (null !== $exclusionStrategy && $exclusionStrategy->shouldSkipClass($context->getMetadataFactory()->getMetadataForClass(\get_class($collection)), $context)) {
76                $context->startVisiting($collection);
77
78                return $visitor->visitArray([], $type, $context);
79            }
80        }
81        $result = $visitor->visitArray($collection->toArray(), $type);
82
83        $context->startVisiting($collection);
84        return $result;
85    }
86
87    /**
88     * @param mixed $data
89     */
90    public function deserializeCollection(DeserializationVisitorInterface $visitor, $data, array $type, DeserializationContext $context): ArrayCollection
91    {
92        // See above.
93        $type['name'] = 'array';
94
95        return new ArrayCollection($visitor->visitArray($data, $type));
96    }
97}
98