Skip to content

Commit 28e137c

Browse files
committed
[Serializer] Added a ChainEncoder and a ChainDecoder
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.
1 parent cf41bf8 commit 28e137c

File tree

3 files changed

+183
-66
lines changed

3 files changed

+183
-66
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->supportsDecoding($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: 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\EncoderInterface;
15+
use Symfony\Component\Serializer\Exception\RuntimeException;
16+
17+
/**
18+
* Encoder delegating the decoding to a chain of encoders.
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 ChainEncoder implements EncoderInterface
25+
{
26+
protected $encoders = array();
27+
protected $encoderByFormat = array();
28+
29+
public function __construct(array $encoders = array())
30+
{
31+
$this->encoders = $encoders;
32+
}
33+
34+
/**
35+
* {@inheritdoc}
36+
*/
37+
final public function encode($data, $format)
38+
{
39+
return $this->getEncoder($format)->encode($data, $format);
40+
}
41+
42+
/**
43+
* {@inheritdoc}
44+
*/
45+
public function supportsEncoding($format)
46+
{
47+
try {
48+
$this->getEncoder($format);
49+
} catch (RuntimeException $e) {
50+
return false;
51+
}
52+
53+
return true;
54+
}
55+
56+
/**
57+
* Gets the encoder supporting the format.
58+
*
59+
* @param string $format
60+
*
61+
* @return EncoderInterface
62+
* @throws RuntimeException if no encoder is found
63+
*/
64+
public function getEncoder($format)
65+
{
66+
if (isset($this->encoderByFormat[$format])
67+
&& isset($this->encoders[$this->encoderByFormat[$format]])
68+
) {
69+
return $this->encoders[$this->encoderByFormat[$format]];
70+
}
71+
72+
foreach ($this->encoders as $i => $encoder) {
73+
if ($encoder->supportsEncoding($format)) {
74+
$this->encoderByFormat[$format] = $i;
75+
76+
return $encoder;
77+
}
78+
}
79+
80+
throw new RuntimeException(sprintf('No encoder found for format "%s".', $format));
81+
}
82+
}

src/Symfony/Component/Serializer/Serializer.php

Lines changed: 19 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
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;
1618
use Symfony\Component\Serializer\Encoder\NormalizationAwareInterface;
@@ -36,6 +38,8 @@
3638
*/
3739
class Serializer implements SerializerInterface, NormalizerInterface, DenormalizerInterface, EncoderInterface, DecoderInterface
3840
{
41+
protected $encoder;
42+
protected $decoder;
3943
protected $normalizers = array();
4044
protected $encoders = array();
4145
protected $normalizerCache = array();
@@ -52,12 +56,21 @@ public function __construct(array $normalizers = array(), array $encoders = arra
5256
}
5357
$this->normalizers = $normalizers;
5458

59+
$decoders = array();
60+
$realEncoders = array();
5561
foreach ($encoders as $encoder) {
5662
if ($encoder instanceof SerializerAwareInterface) {
5763
$encoder->setSerializer($this);
5864
}
65+
if ($encoder instanceof DecoderInterface) {
66+
$decoders[] = $encoder;
67+
}
68+
if ($encoder instanceof EncoderInterface) {
69+
$realEncoders[] = $encoder;
70+
}
5971
}
60-
$this->encoders = $encoders;
72+
$this->encoder = new ChainEncoder($realEncoders);
73+
$this->decoder = new ChainDecoder($decoders);
6174
}
6275

6376
/**
@@ -69,7 +82,7 @@ final public function serialize($data, $format)
6982
throw new UnexpectedValueException('Serialization for the format '.$format.' is not supported');
7083
}
7184

72-
$encoder = $this->getEncoder($format);
85+
$encoder = $this->encoder->getEncoder($format);
7386

7487
if (!$encoder instanceof NormalizationAwareInterface) {
7588
$data = $this->normalize($data, $format);
@@ -197,15 +210,15 @@ private function getDenormalizer($data, $type, $format = null)
197210
*/
198211
final public function encode($data, $format)
199212
{
200-
return $this->getEncoder($format)->encode($data, $format);
213+
return $this->encoder->encode($data, $format);
201214
}
202215

203216
/**
204217
* {@inheritdoc}
205218
*/
206219
final public function decode($data, $format)
207220
{
208-
return $this->getEncoder($format)->decode($data, $format);
221+
return $this->decoder->decode($data, $format);
209222
}
210223

211224
/**
@@ -271,74 +284,14 @@ private function denormalizeObject($data, $class, $format = null)
271284
*/
272285
public function supportsEncoding($format)
273286
{
274-
try {
275-
$this->getEncoder($format);
276-
} catch (RuntimeException $e) {
277-
return false;
278-
}
279-
280-
return true;
287+
return $this->encoder->supportsEncoding($format);
281288
}
282289

283290
/**
284291
* {@inheritdoc}
285292
*/
286293
public function supportsDecoding($format)
287294
{
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));
295+
return $this->decoder->supportsDecoding($format);
343296
}
344297
}

0 commit comments

Comments
 (0)