Skip to content

Commit 42fb7ba

Browse files
author
Jelle van Oosterbosch
committed
Merge branch 'normalize-strategy' into 2.1
2 parents 41aa8a5 + 39dcf8b commit 42fb7ba

File tree

10 files changed

+290
-21
lines changed

10 files changed

+290
-21
lines changed

Resources/config/services.exporter.types.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@ services:
22
_defaults:
33
public: false
44

5+
superbrave_gdpr.exporter.serializer.normalizer.iterable_normalizer:
6+
class: Superbrave\GdprBundle\Serializer\Normalizer\IterableNormalizer
7+
tags:
8+
- { name: "superbrave_gdpr.serializer.normalizer" }
9+
10+
superbrave_gdpr.exporter.serializer.normalizer.datetime_normalizer:
11+
class: Symfony\Component\Serializer\Normalizer\DateTimeNormalizer
12+
tags:
13+
- { name: "superbrave_gdpr.serializer.normalizer" }
14+
515
superbrave_gdpr.exporter.serializer.normalizer.export_annotation:
616
class: Superbrave\GdprBundle\Serializer\Normalizer\AnnotationNormalizer
717
arguments:

Serializer/Normalizer/AnnotationNormalizer.php

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,20 @@
1616
use Superbrave\GdprBundle\Annotation\AnnotationReader;
1717
use Superbrave\GdprBundle\Manipulator\PropertyManipulator;
1818
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
19+
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
20+
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
1921
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
2022

2123
/**
2224
* Normalizes object data based on the specified property annotation.
2325
*
2426
* @author Niels Nijens <nn@superbrave.nl>
27+
* @author Jelle van Oosterbosch <jvo@superbrave.nl>
2528
*/
26-
class AnnotationNormalizer implements NormalizerInterface
29+
class AnnotationNormalizer implements NormalizerInterface, NormalizerAwareInterface
2730
{
31+
use NormalizerAwareTrait;
32+
2833
/**
2934
* The AnnotationReader instance.
3035
*
@@ -70,6 +75,8 @@ public function __construct(
7075
* @param string $format The format being (de-)serialized from or into
7176
*
7277
* @return bool
78+
*
79+
* @throws \ReflectionException
7380
*/
7481
public function supportsNormalization($data, $format = null)
7582
{
@@ -93,6 +100,8 @@ public function supportsNormalization($data, $format = null)
93100
* @param array $context Context options for the normalizer
94101
*
95102
* @return array|string|int|float|bool
103+
*
104+
* @throws \ReflectionException
96105
*/
97106
public function normalize($object, $format = null, array $context = array())
98107
{
@@ -108,7 +117,11 @@ public function normalize($object, $format = null, array $context = array())
108117
$propertyName = $propertyAnnotation->alias;
109118
}
110119

111-
$normalizedData[$propertyName] = $this->getMappedPropertyValue($propertyAnnotation, $propertyValue);
120+
if (false === is_scalar($propertyValue)) {
121+
$normalizedData[$propertyName] = $this->normalizer->normalize($propertyValue, $format, $context);
122+
} else {
123+
$normalizedData[$propertyName] = $this->getMappedPropertyValue($propertyAnnotation, $propertyValue);
124+
}
112125
}
113126

114127
return $normalizedData;
@@ -124,10 +137,6 @@ public function normalize($object, $format = null, array $context = array())
124137
*/
125138
private function getMappedPropertyValue($annotation, $propertyValue)
126139
{
127-
if (is_scalar($propertyValue) === false) {
128-
return $propertyValue;
129-
}
130-
131140
if (property_exists($annotation, 'valueMap') === false || isset($annotation->valueMap) === false) {
132141
return $propertyValue;
133142
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
/**
3+
* This file is part of the GDPR bundle.
4+
*
5+
* @category Bundle
6+
* @package Gdpr
7+
* @author SuperBrave <info@superbrave.nl>
8+
* @copyright 2018 SuperBrave <info@superbrave.nl>
9+
* @license https://github.com/superbrave/gdpr-bundle/blob/master/LICENSE MIT
10+
* @link https://www.superbrave.nl/
11+
*/
12+
13+
namespace Superbrave\GdprBundle\Serializer\Normalizer;
14+
15+
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
16+
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
17+
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
18+
19+
/**
20+
* Normalizes data if it's iterable by calling the normalizer chain.
21+
*
22+
* @author Jelle van Oosterbosch <jvo@superbrave.nl>
23+
*/
24+
class IterableNormalizer implements NormalizerInterface, NormalizerAwareInterface
25+
{
26+
use NormalizerAwareTrait;
27+
28+
/**
29+
* {@inheritdoc}
30+
*/
31+
public function supportsNormalization($data, $format = null)
32+
{
33+
if (is_array($data) || $data instanceof \Traversable) {
34+
return true;
35+
}
36+
37+
return false;
38+
}
39+
40+
/**
41+
* {@inheritdoc}
42+
*/
43+
public function normalize($object, $format = null, array $context = array())
44+
{
45+
$normalizedData = [];
46+
47+
foreach ($object as $value) {
48+
$normalizedData[] = $this->normalizer->normalize($value, $format, $context);
49+
}
50+
51+
return $normalizedData;
52+
}
53+
}

Tests/AnnotatedMock.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
* Class used to test the @see GDPR\AnnotationReader.
2020
*
2121
* @author Niels Nijens <nn@superbrave.nl>
22+
* @author Jelle van Oosterbosch <jvo@superbrave.nl>
2223
*/
2324
class AnnotatedMock
2425
{
@@ -59,6 +60,15 @@ class AnnotatedMock
5960
*/
6061
private $quux;
6162

63+
/**
64+
* The quuz property.
65+
*
66+
* @GDPR\Export()
67+
*
68+
* @var \DateTime
69+
*/
70+
private $quuz;
71+
6272
/**
6373
* The property that is annotated with the Export annotation, but without getter method.
6474
*
@@ -90,8 +100,10 @@ public function __construct(AnnotatedMock $annotatedMock = null)
90100
$elements = array();
91101
if ($annotatedMock instanceof AnnotatedMock) {
92102
$elements[] = $annotatedMock;
103+
$elements[] = clone $annotatedMock;
93104
}
94105

106+
$this->quuz = new \DateTime('2016/01/01');
95107
$this->quux = new ArrayCollection($elements);
96108
}
97109

@@ -135,6 +147,14 @@ public function getQuux()
135147
return $this->quux;
136148
}
137149

150+
/**
151+
* @return \DateTime
152+
*/
153+
public function getQuuz()
154+
{
155+
return $this->quuz;
156+
}
157+
138158
/**
139159
* Returns the value of the notAnnotatedProperty property.
140160
*

Tests/Annotation/AnnotationReaderTest.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
* AnnotationReaderTest.
2525
*
2626
* @author Niels Nijens <nn@superbrave.nl>
27+
* @author Jelle van Oosterbosch <jvo@superbrave.nl>
2728
*/
2829
class AnnotationReaderTest extends PHPUnit_Framework_TestCase
2930
{
@@ -64,9 +65,9 @@ public function testGetPropertiesWithAnnotationExport()
6465
);
6566

6667
$this->assertInternalType('array', $result);
67-
$this->assertCount(5, $result);
68+
$this->assertCount(6, $result);
6869
$this->assertSame(
69-
array('foo', 'baz', 'qux', 'quux', 'annotatedPropertyWithoutMethod'),
70+
array('foo', 'baz', 'qux', 'quux', 'quuz', 'annotatedPropertyWithoutMethod'),
7071
array_keys($result)
7172
);
7273
$this->assertInstanceOf(Export::class, current($result));
@@ -108,11 +109,12 @@ public function testGetPropertiesWithAnnotationForExtendedClass()
108109
);
109110

110111
$this->assertInternalType('array', $result);
111-
$this->assertCount(6, $result);
112+
$this->assertCount(7, $result);
112113
$this->assertSame(
113-
array('extendedProperty', 'foo', 'baz', 'qux', 'quux', 'annotatedPropertyWithoutMethod'),
114+
array('extendedProperty', 'foo', 'baz', 'qux', 'quux', 'quuz', 'annotatedPropertyWithoutMethod'),
114115
array_keys($result)
115116
);
117+
116118
$this->assertInstanceOf(Export::class, current($result));
117119
}
118120
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"foo":"bar","baz":1,"qux":[],"quuxs":[{"foo":"bar","baz":1,"qux":[],"quuxs":[],"quuz":"2016-01-01T00:00:00+00:00","annotatedPropertyWithoutMethod":"Yes"},{"foo":"bar","baz":1,"qux":[],"quuxs":[],"quuz":"2016-01-01T00:00:00+00:00","annotatedPropertyWithoutMethod":"Yes"}],"quuz":"2016-01-01T00:00:00+00:00","annotatedPropertyWithoutMethod":"Yes"}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
["bar",1,[["2020-01-01T00:00:00+00:00","2020-01-01T00:00:00+00:00"]]]
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
<?xml version="1.0"?>
2-
<mock><foo>bar</foo><baz>1</baz><qux/><quuxs><item key="0"><foo>bar</foo><baz>1</baz><qux/><quuxs/><annotatedPropertyWithoutMethod>Yes</annotatedPropertyWithoutMethod></item></quuxs><annotatedPropertyWithoutMethod>Yes</annotatedPropertyWithoutMethod></mock>
2+
<mock><foo>bar</foo><baz>1</baz><qux/><quuxs><foo>bar</foo><baz>1</baz><qux/><quuxs/><quuz>2016-01-01T00:00:00+00:00</quuz><annotatedPropertyWithoutMethod>Yes</annotatedPropertyWithoutMethod></quuxs><quuxs><foo>bar</foo><baz>1</baz><qux/><quuxs/><quuz>2016-01-01T00:00:00+00:00</quuz><annotatedPropertyWithoutMethod>Yes</annotatedPropertyWithoutMethod></quuxs><quuz>2016-01-01T00:00:00+00:00</quuz><annotatedPropertyWithoutMethod>Yes</annotatedPropertyWithoutMethod></mock>

Tests/Serializer/Normalizer/AnnotationNormalizerTest.php

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,25 @@
1212

1313
namespace Superbrave\GdprBundle\Tests\Serializer\Normalizer;
1414

15-
use Doctrine\Common\Collections\ArrayCollection;
1615
use PHPUnit_Framework_MockObject_MockObject;
1716
use ReflectionClass;
1817
use Superbrave\GdprBundle\Annotation\AnnotationReader;
1918
use Superbrave\GdprBundle\Annotation\Export;
2019
use Superbrave\GdprBundle\Manipulator\PropertyManipulator;
2120
use Superbrave\GdprBundle\Serializer\Normalizer\AnnotationNormalizer;
21+
use Superbrave\GdprBundle\Serializer\Normalizer\IterableNormalizer;
2222
use Superbrave\GdprBundle\Tests\AnnotatedMock;
2323
use Symfony\Component\PropertyAccess\PropertyAccess;
24+
use Symfony\Component\Serializer\Encoder\JsonEncoder;
2425
use Symfony\Component\Serializer\Encoder\XmlEncoder;
26+
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
2527
use Symfony\Component\Serializer\Serializer;
2628

2729
/**
2830
* AnnotationNormalizerTest.
2931
*
3032
* @author Niels Nijens <nn@superbrave.nl>
33+
* @author Jelle van Oosterbosch <jvo@superbrave.nl>
3134
*/
3235
class AnnotationNormalizerTest extends \PHPUnit_Framework_TestCase
3336
{
@@ -153,47 +156,91 @@ public function testNormalize()
153156
);
154157

155158
$normalizer = new AnnotationNormalizer($annotationReader, Export::class, $propertyManipulator);
159+
$serializer = new Serializer([
160+
new DateTimeNormalizer(),
161+
new IterableNormalizer(),
162+
$normalizer,
163+
]);
164+
$normalizer->setNormalizer($serializer);
156165

157166
$annotatedMock = new AnnotatedMock();
158167

159168
$this->assertEquals(
160169
array(
161170
'foo' => 'bar',
162171
'baz' => 1,
163-
'qux' => array(),
164-
'quuxs' => new ArrayCollection(),
172+
'qux' => [],
173+
'quuxs' => [],
174+
'quuz' => '2016-01-01T00:00:00+00:00',
165175
'annotatedPropertyWithoutMethod' => 'Yes',
166176
),
167177
$normalizer->normalize($annotatedMock)
168178
);
169179
}
170180

171181
/**
172-
* Tests if AnnotationNormalizer::normalize returns the expected normalized data
182+
* Tests if @see AnnotationNormalizer::normalize returns the expected xml normalized data
173183
* for serialization through the Serializer.
174184
*
175185
* @return void
176186
*/
177-
public function testNormalizeThroughSerializer()
187+
public function testNormalizeThroughXmlSerializer()
178188
{
179189
$annotationReader = new AnnotationReader();
180190
$propertyManipulator = new PropertyManipulator(
181191
PropertyAccess::createPropertyAccessor()
182192
);
183193

184-
$normalizer = new AnnotationNormalizer($annotationReader, Export::class, $propertyManipulator);
185-
$encoder = new XmlEncoder('mock');
194+
$normalizers = [
195+
new DateTimeNormalizer(),
196+
new IterableNormalizer(),
197+
new AnnotationNormalizer($annotationReader, Export::class, $propertyManipulator),
198+
];
199+
$encoders = [new XmlEncoder('mock')];
186200

187201
$serializer = new Serializer(
188-
array($normalizer),
189-
array($encoder)
202+
$normalizers,
203+
$encoders
190204
);
191205

192206
$data = new AnnotatedMock(new AnnotatedMock());
193207

194208
$this->assertStringEqualsFile(
195-
__DIR__.'/../../Resources/xml/annotation_normalizer_result.xml',
209+
__DIR__ . '/../../Resources/xml/annotation_normalizer_result.xml',
196210
$serializer->serialize($data, 'xml')
197211
);
198212
}
213+
214+
/**
215+
* Test if @see AnnotationNormalizer::normalize returns the expected json normalized data
216+
* for serialization through the Serializer.
217+
*
218+
* @return void
219+
*/
220+
public function testNormalizeThroughJsonSerializer()
221+
{
222+
$annotationReader = new AnnotationReader();
223+
$propertyManipulator = new PropertyManipulator(
224+
PropertyAccess::createPropertyAccessor()
225+
);
226+
227+
$normalizers = [
228+
new DateTimeNormalizer(),
229+
new IterableNormalizer(),
230+
new AnnotationNormalizer($annotationReader, Export::class, $propertyManipulator),
231+
];
232+
$encoders = [new JsonEncoder()];
233+
234+
$serializer = new Serializer(
235+
$normalizers,
236+
$encoders
237+
);
238+
239+
$data = new AnnotatedMock(new AnnotatedMock());
240+
241+
$this->assertStringEqualsFile(
242+
__DIR__ . '/../../Resources/json/annotation_normalize_result.json',
243+
$serializer->serialize($data, 'json')
244+
);
245+
}
199246
}

0 commit comments

Comments
 (0)