1 <?php
2 
3 declare(strict_types=1);
4 
5 namespace JMS\Serializer\Handler;
6 
7 use Doctrine\Common\Collections\ArrayCollection;
8 use Doctrine\Common\Collections\Collection;
9 use JMS\Serializer\DeserializationContext;
10 use JMS\Serializer\GraphNavigatorInterface;
11 use JMS\Serializer\SerializationContext;
12 use JMS\Serializer\Visitor\DeserializationVisitorInterface;
13 use JMS\Serializer\Visitor\SerializationVisitorInterface;
14 
15 final 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