Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6c1b966

Browse files
committed
add flatten exception normalizer to serializer component
1 parent d81eb08 commit 6c1b966

File tree

3 files changed

+278
-0
lines changed

3 files changed

+278
-0
lines changed

src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@
8282
<tag name="serializer.normalizer" priority="-1000" />
8383
</service>
8484
<service id="Symfony\Component\Serializer\Normalizer\ObjectNormalizer" alias="serializer.normalizer.object" />
85+
86+
<service id="serializer.normalizer.flatten_exception" class="Symfony\Component\Serializer\Normalizer\FlattenExceptionNormalizer">
87+
<tag name="serializer.normalizer" />
88+
</service>
8589

8690
<service id="serializer.denormalizer.array" class="Symfony\Component\Serializer\Normalizer\ArrayDenormalizer">
8791
<!-- Run before the object normalizer -->
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Serializer\Normalizer;
13+
14+
use Symfony\Component\ErrorHandler\Exception\FlattenException;
15+
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
16+
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
17+
18+
/**
19+
* Normalizes FlattenException instances.
20+
*
21+
* @author Pascal Luna <[email protected]>
22+
*/
23+
class FlattenExceptionNormalizer implements NormalizerInterface, DenormalizerInterface, CacheableSupportsMethodInterface
24+
{
25+
/**
26+
* {@inheritdoc}
27+
*
28+
* @throws InvalidArgumentException
29+
*/
30+
public function normalize($object, $format = null, array $context = [])
31+
{
32+
if (!$object instanceof FlattenException) {
33+
throw new InvalidArgumentException(sprintf('The object must be an instance of "%s".', FlattenException::class));
34+
}
35+
36+
$normalized = [
37+
'message' => $object->getMessage(),
38+
'code' => $object->getCode(),
39+
'headers' => $object->getHeaders(),
40+
'class' => $object->getClass(),
41+
'file' => $object->getFile(),
42+
'line' => $object->getLine(),
43+
'previous' => null === $object->getPrevious() ? null : $this->normalize($object->getPrevious(), $format, $context),
44+
'trace' => $object->getTrace(),
45+
'trace_as_string' => $object->getTraceAsString(),
46+
];
47+
if (null !== $status = $object->getStatusCode()) {
48+
$normalized['status'] = $status;
49+
}
50+
51+
return $normalized;
52+
}
53+
54+
/**
55+
* {@inheritdoc}
56+
*/
57+
public function supportsNormalization($data, $format = null)
58+
{
59+
return $data instanceof FlattenException;
60+
}
61+
62+
/**
63+
* {@inheritdoc}
64+
*/
65+
public function denormalize($data, $type, $format = null, array $context = [])
66+
{
67+
if (!\is_array($data)) {
68+
throw new NotNormalizableValueException(sprintf('The normalized data must be an array, got "%s".', \is_object($data) ? \get_class($data) : \gettype($data)));
69+
}
70+
71+
$object = new FlattenException();
72+
73+
$object->setMessage($data['message'] ?? null);
74+
$object->setCode($data['code'] ?? null);
75+
$object->setStatusCode($data['status'] ?? null);
76+
$object->setClass($data['class'] ?? null);
77+
$object->setFile($data['file'] ?? null);
78+
$object->setLine($data['line'] ?? null);
79+
80+
if (isset($data['headers'])) {
81+
$object->setHeaders((array) $data['headers']);
82+
}
83+
if (isset($data['previous'])) {
84+
$object->setPrevious($this->denormalize($data['previous'], $type, $format, $context));
85+
}
86+
if (isset($data['trace'])) {
87+
$property = new \ReflectionProperty(FlattenException::class, 'trace');
88+
$property->setAccessible(true);
89+
$property->setValue($object, (array) $data['trace']);
90+
}
91+
if (isset($data['trace_as_string'])) {
92+
$property = new \ReflectionProperty(FlattenException::class, 'traceAsString');
93+
$property->setAccessible(true);
94+
$property->setValue($object, $data['trace_as_string']);
95+
}
96+
97+
return $object;
98+
}
99+
100+
/**
101+
* {@inheritdoc}
102+
*/
103+
public function supportsDenormalization($data, $type, $format = null, array $context = [])
104+
{
105+
return FlattenException::class === $type;
106+
}
107+
108+
/**
109+
* {@inheritdoc}
110+
*/
111+
public function hasCacheableSupportsMethod(): bool
112+
{
113+
return __CLASS__ === static::class;
114+
}
115+
}
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Serializer\Tests\Normalizer;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\ErrorHandler\Exception\FlattenException;
16+
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
17+
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
18+
use Symfony\Component\Serializer\Normalizer\FlattenExceptionNormalizer;
19+
20+
/**
21+
* @author Pascal Luna <[email protected]>
22+
*/
23+
class FlattenExceptionNormalizerTest extends TestCase
24+
{
25+
/**
26+
* @var FlattenExceptionNormalizer
27+
*/
28+
private $normalizer;
29+
30+
protected function setUp(): void
31+
{
32+
$this->normalizer = new FlattenExceptionNormalizer();
33+
}
34+
35+
public function testSupportsNormalization()
36+
{
37+
$this->assertTrue($this->normalizer->supportsNormalization(new FlattenException()));
38+
$this->assertFalse($this->normalizer->supportsNormalization(new \stdClass()));
39+
}
40+
41+
/**
42+
* @dataProvider provideFlattenException
43+
*/
44+
public function testNormalize(FlattenException $exception)
45+
{
46+
$normalized = $this->normalizer->normalize($exception);
47+
$previous = null === $exception->getPrevious() ? null : $this->normalizer->normalize($exception->getPrevious());
48+
49+
$this->assertSame($exception->getMessage(), $normalized['message']);
50+
$this->assertSame($exception->getCode(), $normalized['code']);
51+
if (null !== $exception->getStatusCode()) {
52+
$this->assertSame($exception->getStatusCode(), $normalized['status']);
53+
} else {
54+
$this->assertArrayNotHasKey('status', $normalized);
55+
}
56+
$this->assertSame($exception->getHeaders(), $normalized['headers']);
57+
$this->assertSame($exception->getClass(), $normalized['class']);
58+
$this->assertSame($exception->getFile(), $normalized['file']);
59+
$this->assertSame($exception->getLine(), $normalized['line']);
60+
$this->assertSame($previous, $normalized['previous']);
61+
$this->assertSame($exception->getTrace(), $normalized['trace']);
62+
$this->assertSame($exception->getTraceAsString(), $normalized['trace_as_string']);
63+
}
64+
65+
public function provideFlattenException(): array
66+
{
67+
return [
68+
'instance from constructor' => [new FlattenException()],
69+
'instance from exception' => [FlattenException::createFromThrowable(new \RuntimeException('foo', 42))],
70+
'instance with previous exception' => [FlattenException::createFromThrowable(new \RuntimeException('foo', 42, new \Exception()))],
71+
'instance with headers' => [FlattenException::createFromThrowable(new \RuntimeException('foo', 42), 404, ['Foo' => 'Bar'])],
72+
];
73+
}
74+
75+
public function testNormalizeBadObjectTypeThrowsException()
76+
{
77+
$this->expectException(InvalidArgumentException::class);
78+
$this->normalizer->normalize(new \stdClass());
79+
}
80+
81+
public function testSupportsDenormalization()
82+
{
83+
$this->assertTrue($this->normalizer->supportsDenormalization(null, FlattenException::class));
84+
$this->assertFalse($this->normalizer->supportsDenormalization(null, \stdClass::class));
85+
}
86+
87+
public function testDenormalizeValidData()
88+
{
89+
$normalized = [];
90+
$exception = $this->normalizer->denormalize($normalized, FlattenException::class);
91+
92+
$this->assertInstanceOf(FlattenException::class, $exception);
93+
$this->assertNull($exception->getMessage());
94+
$this->assertNull($exception->getCode());
95+
$this->assertNull($exception->getStatusCode());
96+
$this->assertNull($exception->getHeaders());
97+
$this->assertNull($exception->getClass());
98+
$this->assertNull($exception->getFile());
99+
$this->assertNull($exception->getLine());
100+
$this->assertNull($exception->getPrevious());
101+
$this->assertNull($exception->getTrace());
102+
$this->assertNull($exception->getTraceAsString());
103+
104+
$normalized = [
105+
'message' => 'Something went foobar.',
106+
'code' => 42,
107+
'status' => 404,
108+
'headers' => ['Content-Type' => 'application/json'],
109+
'class' => static::class,
110+
'file' => 'foo.php',
111+
'line' => 123,
112+
'previous' => [
113+
'message' => 'Previous exception',
114+
'code' => 0,
115+
],
116+
'trace' => [
117+
[
118+
'namespace' => '', 'short_class' => '', 'class' => '', 'type' => '', 'function' => '', 'file' => 'foo.php', 'line' => 123, 'args' => [],
119+
],
120+
],
121+
'trace_as_string' => '#0 foo.php(123): foo()'.PHP_EOL.'#1 bar.php(456): bar()',
122+
];
123+
$exception = $this->normalizer->denormalize($normalized, FlattenException::class);
124+
125+
$this->assertInstanceOf(FlattenException::class, $exception);
126+
$this->assertSame($normalized['message'], $exception->getMessage());
127+
$this->assertSame($normalized['code'], $exception->getCode());
128+
$this->assertSame($normalized['status'], $exception->getStatusCode());
129+
$this->assertSame($normalized['headers'], $exception->getHeaders());
130+
$this->assertSame($normalized['class'], $exception->getClass());
131+
$this->assertSame($normalized['file'], $exception->getFile());
132+
$this->assertSame($normalized['line'], $exception->getLine());
133+
$this->assertSame($normalized['trace'], $exception->getTrace());
134+
$this->assertSame($normalized['trace_as_string'], $exception->getTraceAsString());
135+
136+
$this->assertInstanceOf(FlattenException::class, $previous = $exception->getPrevious());
137+
$this->assertSame($normalized['previous']['message'], $previous->getMessage());
138+
$this->assertSame($normalized['previous']['code'], $previous->getCode());
139+
}
140+
141+
/**
142+
* @dataProvider provideInvalidNormalizedData
143+
*/
144+
public function testDenormalizeInvalidDataThrowsException($normalized)
145+
{
146+
$this->expectException(NotNormalizableValueException::class);
147+
$this->normalizer->denormalize($normalized, FlattenException::class);
148+
}
149+
150+
public function provideInvalidNormalizedData(): array
151+
{
152+
return [
153+
'null' => [null],
154+
'string' => ['foo'],
155+
'integer' => [42],
156+
'object' => [new \stdClass()],
157+
];
158+
}
159+
}

0 commit comments

Comments
 (0)