[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.
This commit is contained in:
Christophe Coevoet 2012-07-14 10:46:16 +02:00
parent cf41bf8776
commit 28e137c920
3 changed files with 183 additions and 66 deletions

View File

@ -0,0 +1,82 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Serializer\Encoder;
use Symfony\Component\Serializer\Encoder\DecoderInterface;
use Symfony\Component\Serializer\Exception\RuntimeException;
/**
* Decoder delegating the decoding to a chain of decoders.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
* @author Lukas Kahwe Smith <smith@pooteeweet.org>
*/
class ChainDecoder implements DecoderInterface
{
protected $decoders = array();
protected $decoderByFormat = array();
public function __construct(array $decoders = array())
{
$this->decoders = $decoders;
}
/**
* {@inheritdoc}
*/
final public function decode($data, $format)
{
return $this->getDecoder($format)->decode($data, $format);
}
/**
* {@inheritdoc}
*/
public function supportsDecoding($format)
{
try {
$this->getDecoder($format);
} catch (RuntimeException $e) {
return false;
}
return true;
}
/**
* Gets the decoder supporting the format.
*
* @param string $format
*
* @return DecoderInterface
* @throws RuntimeException if no decoder is found
*/
private function getDecoder($format)
{
if (isset($this->decoderByFormat[$format])
&& isset($this->decoders[$this->decoderByFormat[$format]])
) {
return $this->decoders[$this->decoderByFormat[$format]];
}
foreach ($this->decoders as $i => $decoder) {
if ($decoder->supportsDecoding($format)) {
$this->decoderByFormat[$format] = $i;
return $decoder;
}
}
throw new RuntimeException(sprintf('No decoder found for format "%s".', $format));
}
}

View File

@ -0,0 +1,82 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Serializer\Encoder;
use Symfony\Component\Serializer\Encoder\EncoderInterface;
use Symfony\Component\Serializer\Exception\RuntimeException;
/**
* Encoder delegating the decoding to a chain of encoders.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
* @author Lukas Kahwe Smith <smith@pooteeweet.org>
*/
class ChainEncoder implements EncoderInterface
{
protected $encoders = array();
protected $encoderByFormat = array();
public function __construct(array $encoders = array())
{
$this->encoders = $encoders;
}
/**
* {@inheritdoc}
*/
final public function encode($data, $format)
{
return $this->getEncoder($format)->encode($data, $format);
}
/**
* {@inheritdoc}
*/
public function supportsEncoding($format)
{
try {
$this->getEncoder($format);
} catch (RuntimeException $e) {
return false;
}
return true;
}
/**
* Gets the encoder supporting the format.
*
* @param string $format
*
* @return EncoderInterface
* @throws RuntimeException if no encoder is found
*/
public function getEncoder($format)
{
if (isset($this->encoderByFormat[$format])
&& isset($this->encoders[$this->encoderByFormat[$format]])
) {
return $this->encoders[$this->encoderByFormat[$format]];
}
foreach ($this->encoders as $i => $encoder) {
if ($encoder->supportsEncoding($format)) {
$this->encoderByFormat[$format] = $i;
return $encoder;
}
}
throw new RuntimeException(sprintf('No encoder found for format "%s".', $format));
}
}

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\Serializer;
use Symfony\Component\Serializer\Encoder\ChainDecoder;
use Symfony\Component\Serializer\Encoder\ChainEncoder;
use Symfony\Component\Serializer\Encoder\EncoderInterface;
use Symfony\Component\Serializer\Encoder\DecoderInterface;
use Symfony\Component\Serializer\Encoder\NormalizationAwareInterface;
@ -36,6 +38,8 @@ use Symfony\Component\Serializer\Exception\UnexpectedValueException;
*/
class Serializer implements SerializerInterface, NormalizerInterface, DenormalizerInterface, EncoderInterface, DecoderInterface
{
protected $encoder;
protected $decoder;
protected $normalizers = array();
protected $encoders = array();
protected $normalizerCache = array();
@ -52,12 +56,21 @@ class Serializer implements SerializerInterface, NormalizerInterface, Denormaliz
}
$this->normalizers = $normalizers;
$decoders = array();
$realEncoders = array();
foreach ($encoders as $encoder) {
if ($encoder instanceof SerializerAwareInterface) {
$encoder->setSerializer($this);
}
if ($encoder instanceof DecoderInterface) {
$decoders[] = $encoder;
}
if ($encoder instanceof EncoderInterface) {
$realEncoders[] = $encoder;
}
}
$this->encoders = $encoders;
$this->encoder = new ChainEncoder($realEncoders);
$this->decoder = new ChainDecoder($decoders);
}
/**
@ -69,7 +82,7 @@ class Serializer implements SerializerInterface, NormalizerInterface, Denormaliz
throw new UnexpectedValueException('Serialization for the format '.$format.' is not supported');
}
$encoder = $this->getEncoder($format);
$encoder = $this->encoder->getEncoder($format);
if (!$encoder instanceof NormalizationAwareInterface) {
$data = $this->normalize($data, $format);
@ -197,7 +210,7 @@ class Serializer implements SerializerInterface, NormalizerInterface, Denormaliz
*/
final public function encode($data, $format)
{
return $this->getEncoder($format)->encode($data, $format);
return $this->encoder->encode($data, $format);
}
/**
@ -205,7 +218,7 @@ class Serializer implements SerializerInterface, NormalizerInterface, Denormaliz
*/
final public function decode($data, $format)
{
return $this->getEncoder($format)->decode($data, $format);
return $this->decoder->decode($data, $format);
}
/**
@ -271,13 +284,7 @@ class Serializer implements SerializerInterface, NormalizerInterface, Denormaliz
*/
public function supportsEncoding($format)
{
try {
$this->getEncoder($format);
} catch (RuntimeException $e) {
return false;
}
return true;
return $this->encoder->supportsEncoding($format);
}
/**
@ -285,60 +292,6 @@ class Serializer implements SerializerInterface, NormalizerInterface, Denormaliz
*/
public function supportsDecoding($format)
{
try {
$this->getDecoder($format);
} catch (RuntimeException $e) {
return false;
}
return true;
}
/**
* {@inheritdoc}
*/
private function getEncoder($format)
{
if (isset($this->encoderByFormat[$format])
&& isset($this->encoders[$this->encoderByFormat[$format]])
) {
return $this->encoders[$this->encoderByFormat[$format]];
}
foreach ($this->encoders as $i => $encoder) {
if ($encoder instanceof EncoderInterface
&& $encoder->supportsEncoding($format)
) {
$this->encoderByFormat[$format] = $i;
return $encoder;
}
}
throw new RuntimeException(sprintf('No encoder found for format "%s".', $format));
}
/**
* {@inheritdoc}
*/
private function getDecoder($format)
{
if (isset($this->decoderByFormat[$format])
&& isset($this->encoders[$this->decoderByFormat[$format]])
) {
return $this->encoders[$this->decoderByFormat[$format]];
}
foreach ($this->encoders as $i => $encoder) {
if ($encoder instanceof DecoderInterface
&& $encoder->supportsDecoding($format)
) {
$this->decoderByFormat[$format] = $i;
return $encoder;
}
}
throw new RuntimeException(sprintf('No decoder found for format "%s".', $format));
return $this->decoder->supportsDecoding($format);
}
}