Skip to content

Commit 765f435

Browse files
committed
modify serializer to work with php 7.4
1 parent 06c176d commit 765f435

File tree

6 files changed

+157
-38
lines changed

6 files changed

+157
-38
lines changed

src/Symfony/Extensions/PropertyNormalizerWrapper.php

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ final class PropertyNormalizerWrapper extends PropertyNormalizer
2626
*/
2727
private array
2828

29-
$localStorage = [];
29+
$localStorage = [];
3030

3131
/**
3232
* {@inheritdoc}
@@ -40,7 +40,8 @@ protected function instantiateObject(
4040
\ReflectionClass $reflectionClass,
4141
$allowedAttributes,
4242
string $format = null
43-
): object {
43+
): object
44+
{
4445
return $reflectionClass->newInstanceWithoutConstructor();
4546
}
4647

@@ -51,11 +52,44 @@ protected function extractAttributes(object $object, string $format = null, arra
5152
{
5253
$class = \get_class($object);
5354

54-
if (false === isset($this->localStorage[$class]))
55+
if(false === isset($this->localStorage[$class]))
5556
{
56-
$this->localStorage[$class] = parent::extractAttributes($object, $format, $context);
57+
$this->localStorage[$class] = [];
58+
59+
foreach(\get_object_vars($object) as $key => $value)
60+
{
61+
$this->localStorage[$class][] = $key;
62+
}
5763
}
5864

5965
return $this->localStorage[$class];
6066
}
67+
68+
/**
69+
* {@inheritdoc}
70+
*/
71+
protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = [])
72+
{
73+
if(isset($object->{$attribute}) === true)
74+
{
75+
return $object->{$attribute};
76+
}
77+
78+
return parent::getAttributeValue($object, $attribute, $format, $context);
79+
}
80+
81+
/**
82+
* {@inheritdoc}
83+
*/
84+
protected function setAttributeValue(object $object, string $attribute, $value, string $format = null, array $context = [])
85+
{
86+
if(isset($object->{$attribute}) === true)
87+
{
88+
$object->{$attribute} = $value;
89+
}
90+
else
91+
{
92+
parent::setAttributeValue($object, $attribute, $value, $format, $context);
93+
}
94+
}
6195
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
/**
4+
* Messages serializer implementation.
5+
*
6+
* @author Maksim Masiukevich <[email protected]>
7+
* @license MIT
8+
* @license https://opensource.org/licenses/MIT
9+
*/
10+
11+
declare(strict_types = 1);
12+
13+
namespace ServiceBus\MessageSerializer\Symfony\Extractor;
14+
15+
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
16+
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
17+
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
18+
use Symfony\Component\PropertyInfo\Type;
19+
20+
/**
21+
*/
22+
final class FailOverExtractor implements PropertyTypeExtractorInterface
23+
{
24+
/**
25+
* @var PropertyTypeExtractorInterface[]
26+
*/
27+
private array $extractors;
28+
29+
public function __construct()
30+
{
31+
$this->extractors = [
32+
new ReflectionExtractor(),
33+
new PhpDocExtractor()
34+
];
35+
}
36+
37+
/**
38+
* @inheritDoc
39+
*/
40+
public function getTypes(string $class, string $property, array $context = []): ?array
41+
{
42+
foreach($this->extractors as $extractor)
43+
{
44+
$types = $extractor->getTypes($class, $property, $context);
45+
46+
if(null !== $types)
47+
{
48+
return $types;
49+
}
50+
}
51+
52+
return null;
53+
}
54+
}

src/Symfony/SymfonyMessageSerializer.php

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@
2020
use ServiceBus\MessageSerializer\MessageDecoder;
2121
use ServiceBus\MessageSerializer\MessageEncoder;
2222
use ServiceBus\MessageSerializer\Serializer;
23+
use ServiceBus\MessageSerializer\Symfony\Extractor\FailOverExtractor;
2324
use ServiceBus\MessageSerializer\SymfonyNormalizer\Extensions\EmptyDataNormalizer;
2425
use ServiceBus\MessageSerializer\SymfonyNormalizer\Extensions\PropertyNameConverter;
2526
use ServiceBus\MessageSerializer\SymfonyNormalizer\Extensions\PropertyNormalizerWrapper;
26-
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
27+
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
2728
use Symfony\Component\Serializer as SymfonySerializer;
29+
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
2830

2931
/**
3032
*
@@ -47,9 +49,9 @@ final class SymfonyMessageSerializer implements MessageEncoder, MessageDecoder
4749
public function __construct(Serializer $serializer = null, array $normalizers = [])
4850
{
4951
$defaultNormalizers = [
50-
new SymfonySerializer\Normalizer\DateTimeNormalizer(['datetime_format' => 'c']),
52+
new DateTimeNormalizer(['datetime_format' => 'c']),
5153
new SymfonySerializer\Normalizer\ArrayDenormalizer(),
52-
new PropertyNormalizerWrapper(null, new PropertyNameConverter(), new PhpDocExtractor()),
54+
new PropertyNormalizerWrapper(null, new PropertyNameConverter(), new FailOverExtractor()),
5355
new EmptyDataNormalizer(),
5456
];
5557

@@ -71,7 +73,7 @@ public function encode(object $message): string
7173

7274
return $this->serializer->serialize($data);
7375
}
74-
catch (\Throwable $throwable)
76+
catch(\Throwable $throwable)
7577
{
7678
throw new EncodeMessageFailed($throwable->getMessage(), (int) $throwable->getCode(), $throwable);
7779
}
@@ -94,7 +96,7 @@ public function decode(string $serializedMessage): object
9496

9597
return $object;
9698
}
97-
catch (\Throwable $throwable)
99+
catch(\Throwable $throwable)
98100
{
99101
throw new DecodeMessageFailed($throwable->getMessage(), (int) $throwable->getCode(), $throwable);
100102
}
@@ -115,7 +117,7 @@ public function denormalize(array $payload, string $class): object
115117

116118
return $object;
117119
}
118-
catch (\Throwable $throwable)
120+
catch(\Throwable $throwable)
119121
{
120122
throw new DenormalizeFailed($throwable->getMessage(), (int) $throwable->getCode(), $throwable);
121123
}
@@ -130,7 +132,7 @@ public function normalize(object $message): array
130132
{
131133
$data = $this->normalizer->normalize($message);
132134

133-
if (true === \is_array($data))
135+
if(true === \is_array($data))
134136
{
135137
/** @psalm-var array<string, mixed> $data */
136138

@@ -147,7 +149,7 @@ public function normalize(object $message): array
147149
);
148150
// @codeCoverageIgnoreEnd
149151
}
150-
catch (\Throwable $throwable)
152+
catch(\Throwable $throwable)
151153
{
152154
throw new NormalizationFailed($throwable->getMessage(), (int) $throwable->getCode(), $throwable);
153155
}
@@ -161,10 +163,11 @@ public function normalize(object $message): array
161163
private static function validateUnserializedData(array $data): void
162164
{
163165
/** Let's check if there are mandatory fields */
164-
if (
166+
if(
165167
false === isset($data['namespace']) ||
166168
false === isset($data['message'])
167-
) {
169+
)
170+
{
168171
throw new \UnexpectedValueException(
169172
'The serialized data must contains a "namespace" field (indicates the message class) and "message" (indicates the message parameters)'
170173
);
@@ -175,7 +178,7 @@ private static function validateUnserializedData(array $data): void
175178
*
176179
* @psalm-suppress DocblockTypeContradiction
177180
*/
178-
if ('' === $data['namespace'] || false === \class_exists((string) $data['namespace']))
181+
if('' === $data['namespace'] || false === \class_exists((string) $data['namespace']))
179182
{
180183
throw new \UnexpectedValueException(
181184
\sprintf('Class "%s" not found', $data['namespace'])

tests/Stubs/AuthorCollection.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
/**
4+
* Messages serializer implementation.
5+
*
6+
* @author Maksim Masiukevich <[email protected]>
7+
* @license MIT
8+
* @license https://opensource.org/licenses/MIT
9+
*/
10+
11+
declare(strict_types = 1);
12+
13+
namespace ServiceBus\MessageSerializer\Tests\Stubs;
14+
15+
/**
16+
*/
17+
final class AuthorCollection
18+
{
19+
/**
20+
* @var Author[]
21+
*/
22+
public array $collection;
23+
}

tests/Stubs/ClassWithPrivateConstructor.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,15 @@
1717
*/
1818
final class ClassWithPrivateConstructor
1919
{
20-
private string $value;
20+
/**
21+
* @var string
22+
*/
23+
public string $value;
2124

2225
/**
23-
* @param mixed $value
26+
* @param mixed
27+
*
28+
* @return self
2429
*/
2530
public static function create($value): self
2631
{
@@ -32,7 +37,6 @@ public static function create($value): self
3237
*/
3338
private function __construct($value)
3439
{
35-
/** @noinspection UnusedConstructorDependenciesInspection */
3640
$this->value = $value;
3741
}
3842
}

tests/Symfony/SymfonyMessageSerializerTest.php

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use ServiceBus\MessageSerializer\Exceptions\EncodeMessageFailed;
1919
use ServiceBus\MessageSerializer\Symfony\SymfonyMessageSerializer;
2020
use ServiceBus\MessageSerializer\Tests\Stubs\Author;
21+
use ServiceBus\MessageSerializer\Tests\Stubs\AuthorCollection;
2122
use ServiceBus\MessageSerializer\Tests\Stubs\ClassWithPrivateConstructor;
2223
use ServiceBus\MessageSerializer\Tests\Stubs\EmptyClassWithPrivateConstructor;
2324
use ServiceBus\MessageSerializer\Tests\Stubs\TestMessage;
@@ -185,42 +186,42 @@ public function withWrongCharset(): void
185186
*
186187
* @throws \Throwable
187188
*/
188-
public function withIncorrectType(): void
189+
public function successFlow(): void
189190
{
190-
$this->expectException(DecodeMessageFailed::class);
191-
$this->expectExceptionMessage(
192-
\sprintf(
193-
'The type of the "value" attribute for class "%s" must be one of "string" ("integer" given)',
194-
ClassWithPrivateConstructor::class
195-
)
196-
);
197-
198191
$serializer = new SymfonyMessageSerializer();
199192

200-
$data = $serializer->encode(ClassWithPrivateConstructor::create(100));
193+
$object = TestMessage::create(
194+
'message-serializer',
195+
null,
196+
'dev-master',
197+
Author::create('Vasiya', 'Pupkin')
198+
);
201199

202-
$serializer->decode($data);
200+
static::assertSame(
201+
\get_object_vars($object),
202+
\get_object_vars($serializer->decode($serializer->encode($object)))
203+
);
203204
}
204205

205206
/**
206207
* @test
207208
*
208209
* @throws \Throwable
209210
*/
210-
public function successFlow(): void
211+
public function successCollection(): void
211212
{
212213
$serializer = new SymfonyMessageSerializer();
213214

214-
$object = TestMessage::create(
215-
'message-serializer',
216-
null,
217-
'dev-master',
218-
Author::create('Vasiya', 'Pupkin')
219-
);
215+
$object = new AuthorCollection();
216+
$object->collection[] = Author::create('qwerty', 'root');
217+
$object->collection[] = Author::create('root', 'qwerty');
218+
219+
/** @var AuthorCollection $unserialized */
220+
$unserialized = $serializer->decode($serializer->encode($object));
220221

221222
static::assertSame(
222-
\get_object_vars($object),
223-
\get_object_vars($serializer->decode($serializer->encode($object)))
223+
array_map(fn(Author $author): string => $author->firstName, $object->collection),
224+
array_map(fn(Author $author): string => $author->firstName, $unserialized->collection),
224225
);
225226
}
226227
}

0 commit comments

Comments
 (0)