10000 merged branch stof/serializer_improvement (PR #4904) · nathanlon/symfony@36d12dd · GitHub
[go: up one dir, main page]

Skip to content

Commit 36d12dd

Browse files
committed
merged branch stof/serializer_improvement (PR symfony#4904)
Commits ------- 12bdec3 Moved the NormalizationAwareInterface check to the ChainEncoder 28e137c [Serializer] Added a ChainEncoder and a ChainDecoder Discussion ---------- [Serializer] Added a ChainEncoder and a ChainDecoder Bug fix: no Feature addition: yes Backwards compatibility break: no Symfony2 tests pass: [![Build Status](https://secure.travis-ci.org/stof/symfony.png?branch=serializer_improvement)](http://travis-ci.org/stof/symfony) Fixes the following tickets: - Todo: - These classes contains the logic previously defined in the Serializer itself to handle the choice of a serializer. This allows reusing it when using only the encoding part of the component, without having to use the Serializer class (which is not as handy to bootstrap when you want to use only encoders and decoders as normalizers come first) I was wondering if these classes should have adders but I kept the constructor injection only to be consistent with the current code (encoders cannot be registered after the instantiation) and to avoid implementing the SerializerAwareInterface in them (to allow injecting the Serializer in serializer-aware encoders and decoders added later). Note that this change is fully BC as it only changes the internal implementation of the Serializer. --------------------------------------------------------------------------- by fabpot at 2012-07-14T11:07:32Z ping @lsmith77 @Seldaek --------------------------------------------------------------------------- by Seldaek at 2012-07-14T15:17:42Z After a quick look, I'd say +1
2 parents 4dd47ac + 12bdec3 commit 36d12dd

File tree

3 files changed

+206
-72
lines changed

3 files changed

+206
-72
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
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\Encoder;
13+
14+
use Symfony\Component\Serializer\Encoder\DecoderInterface;
15+
use Symfony\Component\Serializer\Exception\RuntimeException;
16+
17+
/**
18+
* Decoder delegating the decoding to a chain of decoders.
19+
*
20+
* @author Jordi Boggiano <j.boggiano@seld.be>
21+
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
22+
* @author Lukas Kahwe Smith <smith@pooteeweet.org>
23+
*/
24+
class ChainDecoder implements DecoderInterface
25+
{
26+
protected $decoders = array();
27+
protected $decoderByFormat = array();
28+
29+
public function __construct(array $decoders = array())
30+
{
31+
$this->decoders = $decoders;
32+
}
33+
34+
/**
35+
* {@inheritdoc}
36+
*/
37+
final public function decode($data, $format)
38+
{
39+
return $this->getDecoder($format)->decode($data, $format);
40+
}
41+
42+
/**
43+
* {@inheritdoc}
44+
*/
45+
public function supportsDecoding($format)
46+
{
47+
try {
48+
$this->getDecoder($format);
49+
} catch (RuntimeException $e) {
50+
return false;
51+
}
52+
53+
return true;
54+
}
55+
56+
/**
57+
* Gets the decoder supporting the format.
58+
*
59+
* @param string $format
60+
*
61+
* @return DecoderInterface
62+
* @throws RuntimeException if no decoder is found
63+
*/
64+
private function getDecoder($format)
65+
{
66+
if (isset($this->decoderByFormat[$format])
67+
&& isset($this->decoders[$this->decoderByFormat[$format]])
68+
) {
69+
return $this->decoders[$this->decoderByFormat[$format]];
70+
}
71+
72+
foreach ($this->decoders as $i => $decoder) {
73+
if ($decoder->supportsDec B41A oding($format)) {
74+
$this->decoderByFormat[$format] = $i;
75+
76+
return $decoder;
77+
}
78+
}
79+
80+
throw new RuntimeException(sprintf('No decoder found for format "%s".', $format));
81+
}
82+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
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\Encoder;
13+
14+
use Symfony\Component\Serializer\Encoder\EncoderInterface;
15+
use Symfony\Component\Serializer\Encoder\NormalizationAwareInterface;
16+
use Symfony\Component\Serializer\Exception\RuntimeException;
17+
18+
/**
19+
* Encoder delegating the decoding to a chain of encoders.
20+
*
21+
* @author Jordi Boggiano <j.boggiano@seld.be>
22+
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
23+
* @author Lukas Kahwe Smith <smith@pooteeweet.org>
24+
*/
25+
class ChainEncoder implements EncoderInterface
26+
{
27+
protected $encoders = array();
28+
protected $encoderByFormat = array();
29+
30+
public function __construct(array $encoders = array())
31+
{
32+
$this->encoders = $encoders;
33+
}
34+
35+
/**
36+
* {@inheritdoc}
37+
*/
38+
final public function encode($data, $format)
39+
{
40+
return $this->getEncoder($format)->encode($data, $format);
41+
}
42+
43+
/**
44+
* {@inheritdoc}
45+
*/
46+
public function supportsEncoding($format)
47+
{
48+
try {
49+
$this->getEncoder($format);
50+
} catch (RuntimeException $e) {
51+
return false;
52+
}
53+
54+
return true;
55+
}
56+
57+
/**
58+
* Checks whether the normalization is needed for the given format.
59+
*
60+
* @param string $format
61+
*
62+
* @return Boolean
63+
*/
64+
public function needsNormalization($format)
65+
{
66+
$encoder = $this->getEncoder($format);
67+
68+
if (!$encoder instanceof NormalizationAwareInterface) {
69+
return true;
70+
}
71+
72+
if ($encoder instanceof self) {
73+
return $encoder->needsNormalization($format);
74+
}
75+
76+
return false;
77+
}
78+
79+
/**
80+
* Gets the encoder supporting the format.
81+
*
82+
* @param string $format
83+
*
84+
* @return EncoderInterface
85+
* @throws RuntimeException if no encoder is found
86+
*/
87+
private function getEncoder($format)
88+
{
89+
if (isset($this->encoderByFormat[$format])
90+
&& isset($this->encoders[$this->encoderByFormat[$format]])
91+
) {
92+
return $this->encoders[$this->encoderByFormat[$format]];
93+
}
94+
95+
foreach ($this->encoders as $i => $encoder) {
96+
if ($encoder->supportsEncoding($format)) {
97+
$this->encoderByFormat[$format] = $i;
98+
99+
return $encoder;
100+
}
101+
}
102+
103+
throw new RuntimeException(sprintf('No encoder found for format "%s".', $format));
104+
}
105+
}

src/Symfony/Component/Serializer/Serializer.php

Lines changed: 19 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111

1212
namespace Symfony\Component\Serializer;
1313

14+
use Symfony\Component\Serializer\Encoder\ChainDecoder;
15+
use Symfony\Component\Serializer\Encoder\ChainEncoder;
1416
use Symfony\Component\Serializer\Encoder\EncoderInterface;
1517
use Symfony\Component\Serializer\Encoder\DecoderInterface;
16-
use Symfony\Component\Serializer\Encoder\NormalizationAwareInterface;
1718
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
1819
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
1920
use Symfony\Component\Serializer\Exception\RuntimeException;
@@ -36,12 +37,11 @@
3637
*/
3738
class Serializer implements SerializerInterface, NormalizerInterface, DenormalizerInterface, EncoderInterface, DecoderInterface
3839
{
40+
protected $encoder;
41+
protected $decoder;
3942
protected $normalizers = array();
40-
protected $encoders = array();
4143
protected $normalizerCache = array();
4244
protected $denormalizerCache = array();
43-
protected $encoderByFormat = array();
44-
protected $decoderByFormat = array();
4545

4646
public function __construct(array $normalizers = array(), array $encoders = array())
4747
{
@@ -52,12 +52,21 @@ public function __construct(array $normalizers = array(), array $encoders = arra
5252
}
5353
$this->normalizers = $normalizers;
5454

55+
$decoders = array();
56+
$realEncoders = array();
5557
foreach ($encoders as $encoder) {
5658
if ($encoder instanceof SerializerAwareInterface) {
5759
$encoder->setSerializer($this);
5860
}
61+
if ($encoder instanceof DecoderInterface) {
62+
$decoders[] = $encoder;
63+
}
64+
if ($encoder instanceof EncoderInterface) {
65+
$realEncoders[] = $encoder;
66+
}
5967
}
60-
$this->encoders = $encoders;
68+
$this->encoder = new ChainEncoder($realEncoders);
69+
$this->decoder = new ChainDecoder($decoders);
6170
}
6271

6372
/**
@@ -69,9 +78,7 @@ final public function serialize($data, $format)
6978
throw new UnexpectedValueException('Serialization for the format '.$format.' is not supported');
7079
}
7180

72-
$encoder = $this->getEncoder($format);
73-
74-
if (!$encoder instanceof NormalizationAwareInterface) {
81+
if ($this->encoder->needsNormalization($format)) {
7582
$data = $this->normalize($data, $format);
7683
}
7784

@@ -197,15 +204,15 @@ private function getDenormalizer($data, $type, $format = null)
197204
*/
198205
final public function encode($data, $format)
199206
{
200-
return $this->getEncoder($format)->encode($data, $format);
207+
return $this->encoder->encode($data, $format);
201208
}
202209

203210
/**
204211
* {@inheritdoc}
205212
*/
206213
final public function decode($data, $format)
207214
{
208-
return $this->getEncoder($format)->decode($data, $format);
215+
return $this->decoder->decode($data, $format);
209216
}
210217

211218
/**
@@ -271,74 +278,14 @@ private function denormalizeObject($data, $class, $format = null)
271278
*/
272279
public function supportsEncoding($format)
273280
{
274-
try {
275-
$this->getEncoder($format);
276-
} catch (RuntimeException $e) {
277-
return false;
278-
}
279-
280-
return true;
281+
return $this->encoder->supportsEncoding($format);
281282
}
282283

283284
/**
284285
* {@inheritdoc}
285286
*/
286287
public function supportsDecoding($format)
287288
{
288-
try {
289-
$this->getDecoder($format);
290-
} catch (RuntimeException $e) {
291-
return false;
292-
}
293-
294-
return true;
295-
}
296-
297-
/**
298-
* {@inheritdoc}
299-
*/
300-
private function getEncoder($format)
301-
{
302-
if (isset($this->encoderByFormat[$format])
303-
&& isset($this->encoders[$this->encoderByFormat[$format]])
304-
) {
305-
return $this->encoders[$this->encoderByFormat[$format]];
306-
}
307-
308-
foreach ($this->encoders as $i => $encoder) {
309-
if ($encoder instanceof EncoderInterface
310-
&& $encoder->supportsEncoding($format)
311-
) {
312-
$this->encoderByFormat[$format] = $i;
313-
314-
return $encoder;
315-
}
316-
}
317-
318-
throw new RuntimeException(sprintf('No encoder found for format "%s".', $format));
319-
}
320-
321-
/**
322-
* {@inheritdoc}
323-
*/
324-
private function getDecoder($format)
325-
{
326-
if (isset($this->decoderByFormat[$format])
327-
&& isset($this->encoders[$this->decoderByFormat[$format]])
328-
) {
329-
return $this->encoders[$this->decoderByFormat[$format]];
330-
}
331-
332-
foreach ($this->encoders as $i => $encoder) {
333-
if ($encoder instanceof DecoderInterface
334-
&& $encoder->supportsDecoding($format)
335-
) {
336-
$this->decoderByFormat[$format] = $i;
337-
338-
return $encoder;
339-
}
340-
}
341-
342-
throw new RuntimeException(sprintf('No decoder found for format "%s".', $format));
289+
return $this->decoder->supportsDecoding($format);
343290
}
344291
}

0 commit comments

Comments
 (0)
0