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 Doctrine\ODM\MongoDB\PersistentCollection as MongoPersistentCollection; |
||||||
0 ignored issues
–
show
|
|||||||
10 | use Doctrine\ODM\PHPCR\PersistentCollection as PhpcrPersistentCollection; |
||||||
11 | use Doctrine\ORM\PersistentCollection as OrmPersistentCollection; |
||||||
12 | use Doctrine\Persistence\ManagerRegistry; |
||||||
13 | use JMS\Serializer\DeserializationContext; |
||||||
14 | use JMS\Serializer\GraphNavigatorInterface; |
||||||
15 | use JMS\Serializer\Metadata\PropertyMetadata; |
||||||
16 | use JMS\Serializer\SerializationContext; |
||||||
17 | use JMS\Serializer\Visitor\DeserializationVisitorInterface; |
||||||
18 | use JMS\Serializer\Visitor\SerializationVisitorInterface; |
||||||
19 | |||||||
20 | final class ArrayCollectionHandler implements SubscribingHandlerInterface |
||||||
21 | { |
||||||
22 | 329 | public const COLLECTION_TYPES = [ |
|||||
23 | 'ArrayCollection', |
||||||
24 | 329 | ArrayCollection::class, |
|||||
25 | 329 | OrmPersistentCollection::class, |
|||||
26 | MongoPersistentCollection::class, |
||||||
27 | 329 | PhpcrPersistentCollection::class, |
|||||
28 | ]; |
||||||
29 | 329 | ||||||
30 | 329 | /** |
|||||
31 | * @var bool |
||||||
32 | 329 | */ |
|||||
33 | private $initializeExcluded; |
||||||
34 | |||||||
35 | /** |
||||||
36 | * @var ManagerRegistry|null |
||||||
37 | */ |
||||||
38 | private $managerRegistry; |
||||||
39 | 329 | ||||||
40 | 329 | public function __construct( |
|||||
41 | 329 | bool $initializeExcluded = true, |
|||||
42 | 329 | ?ManagerRegistry $managerRegistry = null |
|||||
43 | 329 | ) { |
|||||
44 | 329 | $this->initializeExcluded = $initializeExcluded; |
|||||
45 | 329 | $this->managerRegistry = $managerRegistry; |
|||||
46 | } |
||||||
47 | |||||||
48 | 329 | /** |
|||||
49 | 329 | * {@inheritdoc} |
|||||
50 | 329 | */ |
|||||
51 | 329 | public static function getSubscribingMethods() |
|||||
52 | 329 | { |
|||||
53 | $methods = []; |
||||||
54 | $formats = ['json', 'xml']; |
||||||
55 | |||||||
56 | foreach (self::COLLECTION_TYPES as $type) { |
||||||
57 | 329 | foreach ($formats as $format) { |
|||||
58 | $methods[] = [ |
||||||
59 | 'direction' => GraphNavigatorInterface::DIRECTION_SERIALIZATION, |
||||||
60 | 9 | 'type' => $type, |
|||||
61 | 'format' => $format, |
||||||
62 | 'method' => 'serializeCollection', |
||||||
63 | 9 | ]; |
|||||
64 | |||||||
65 | 9 | $methods[] = [ |
|||||
66 | 'direction' => GraphNavigatorInterface::DIRECTION_DESERIALIZATION, |
||||||
67 | 9 | 'type' => $type, |
|||||
68 | 'format' => $format, |
||||||
69 | 'method' => 'deserializeCollection', |
||||||
70 | ]; |
||||||
71 | } |
||||||
72 | } |
||||||
73 | |||||||
74 | return $methods; |
||||||
75 | 9 | } |
|||||
76 | |||||||
77 | 9 | /** |
|||||
78 | 9 | * @return array|\ArrayObject |
|||||
79 | */ |
||||||
80 | public function serializeCollection(SerializationVisitorInterface $visitor, Collection $collection, array $type, SerializationContext $context) |
||||||
81 | 6 | { |
|||||
82 | // We change the base type, and pass through possible parameters. |
||||||
83 | $type['name'] = 'array'; |
||||||
84 | 6 | ||||||
85 | $context->stopVisiting($collection); |
||||||
86 | 6 | ||||||
87 | if (false === $this->initializeExcluded) { |
||||||
88 | $exclusionStrategy = $context->getExclusionStrategy(); |
||||||
89 | if (null !== $exclusionStrategy && $exclusionStrategy->shouldSkipClass($context->getMetadataFactory()->getMetadataForClass(\get_class($collection)), $context)) { |
||||||
0 ignored issues
–
show
It seems like
$context->getMetadataFac...get_class($collection)) can also be of type Metadata\ClassHierarchyMetadata and null ; however, parameter $metadata of JMS\Serializer\Exclusion...face::shouldSkipClass() does only seem to accept JMS\Serializer\Metadata\ClassMetadata , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
90 | $context->startVisiting($collection); |
||||||
91 | |||||||
92 | return $visitor->visitArray([], $type); |
||||||
93 | } |
||||||
94 | } |
||||||
95 | |||||||
96 | $result = $visitor->visitArray($collection->toArray(), $type); |
||||||
97 | |||||||
98 | $context->startVisiting($collection); |
||||||
99 | |||||||
100 | return $result; |
||||||
101 | } |
||||||
102 | |||||||
103 | /** |
||||||
104 | * @param mixed $data |
||||||
105 | */ |
||||||
106 | public function deserializeCollection( |
||||||
107 | DeserializationVisitorInterface $visitor, |
||||||
108 | $data, |
||||||
109 | array $type, |
||||||
110 | DeserializationContext $context |
||||||
111 | ): Collection { |
||||||
112 | // See above. |
||||||
113 | $type['name'] = 'array'; |
||||||
114 | |||||||
115 | $elements = new ArrayCollection($visitor->visitArray($data, $type)); |
||||||
116 | |||||||
117 | if (null === $this->managerRegistry) { |
||||||
118 | return $elements; |
||||||
119 | } |
||||||
120 | |||||||
121 | $propertyMetadata = $context->getMetadataStack()->top(); |
||||||
122 | if (!$propertyMetadata instanceof PropertyMetadata) { |
||||||
123 | return $elements; |
||||||
124 | } |
||||||
125 | |||||||
126 | $objectManager = $this->managerRegistry->getManagerForClass($propertyMetadata->class); |
||||||
127 | if (null === $objectManager) { |
||||||
128 | return $elements; |
||||||
129 | } |
||||||
130 | |||||||
131 | $classMetadata = $objectManager->getClassMetadata($propertyMetadata->class); |
||||||
132 | $currentObject = $visitor->getCurrentObject(); |
||||||
0 ignored issues
–
show
The method
getCurrentObject() does not exist on JMS\Serializer\Visitor\D...izationVisitorInterface . Since it exists in all sub-types, consider adding an abstract or default implementation to JMS\Serializer\Visitor\D...izationVisitorInterface .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
133 | |||||||
134 | if ( |
||||||
135 | array_key_exists('name', $propertyMetadata->type) |
||||||
136 | && in_array($propertyMetadata->type['name'], self::COLLECTION_TYPES) |
||||||
137 | && $classMetadata->isCollectionValuedAssociation($propertyMetadata->name) |
||||||
138 | ) { |
||||||
139 | $existingCollection = $classMetadata->getFieldValue($currentObject, $propertyMetadata->name); |
||||||
0 ignored issues
–
show
The method
getFieldValue() does not exist on Doctrine\Persistence\Mapping\ClassMetadata . Did you maybe mean getFieldNames() ?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed.
Loading history...
|
|||||||
140 | if (!$existingCollection instanceof OrmPersistentCollection) { |
||||||
141 | return $elements; |
||||||
142 | } |
||||||
143 | |||||||
144 | foreach ($elements as $element) { |
||||||
145 | if (!$existingCollection->contains($element)) { |
||||||
146 | $existingCollection->add($element); |
||||||
147 | } |
||||||
148 | } |
||||||
149 | |||||||
150 | foreach ($existingCollection as $collectionElement) { |
||||||
151 | if (!$elements->contains($collectionElement)) { |
||||||
152 | $existingCollection->removeElement($collectionElement); |
||||||
153 | } |
||||||
154 | } |
||||||
155 | |||||||
156 | return $existingCollection; |
||||||
157 | } |
||||||
158 | |||||||
159 | return $elements; |
||||||
160 | } |
||||||
161 | } |
||||||
162 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths