From 28e137c92038c139445c325ea4c15e0021e5bf5b Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Sat, 14 Jul 2012 10:46:16 +0200 Subject: [PATCH] [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. --- .../Serializer/Encoder/ChainDecoder.php | 82 ++++++++++++++++++ .../Serializer/Encoder/ChainEncoder.php | 82 ++++++++++++++++++ .../Component/Serializer/Serializer.php | 85 +++++-------------- 3 files changed, 183 insertions(+), 66 deletions(-) create mode 100644 src/Symfony/Component/Serializer/Encoder/ChainDecoder.php create mode 100644 src/Symfony/Component/Serializer/Encoder/ChainEncoder.php diff --git a/src/Symfony/Component/Serializer/Encoder/ChainDecoder.php b/src/Symfony/Component/Serializer/Encoder/ChainDecoder.php new file mode 100644 index 000000000000..f555c6a8c982 --- /dev/null +++ b/src/Symfony/Component/Serializer/Encoder/ChainDecoder.php @@ -0,0 +1,82 @@ + + * + * 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 + * @author Johannes M. Schmitt + * @author Lukas Kahwe Smith + */ +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)); + } +} diff --git a/src/Symfony/Component/Serializer/Encoder/ChainEncoder.php b/src/Symfony/Component/Serializer/Encoder/ChainEncoder.php new file mode 100644 index 000000000000..73fdd64959e5 --- /dev/null +++ b/src/Symfony/Component/Serializer/Encoder/ChainEncoder.php @@ -0,0 +1,82 @@ + + * + * 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 + * @author Johannes M. Schmitt + * @author Lukas Kahwe Smith + */ +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)); + } +} diff --git a/src/Symfony/Component/Serializer/Serializer.php b/src/Symfony/Component/Serializer/Serializer.php index 77500a10641b..15587fbf81a1 100644 --- a/src/Symfony/Component/Serializer/Serializer.php +++ b/src/Symfony/Component/Serializer/Serializer.php @@ -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 @@ */ 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 @@ public function __construct(array $normalizers = array(), array $encoders = arra } $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 @@ final public function serialize($data, $format) 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 @@ private function getDenormalizer($data, $type, $format = null) */ final public function encode($data, $format) { - return $this->getEncoder($format)->encode($data, $format); + return $this->encoder->encode($data, $format); } /** @@ -205,7 +218,7 @@ final public function encode($data, $format) */ final public function decode($data, $format) { - return $this->getEncoder($format)->decode($data, $format); + return $this->decoder->decode($data, $format); } /** @@ -271,13 +284,7 @@ private function denormalizeObject($data, $class, $format = null) */ public function supportsEncoding($format) { - try { - $this->getEncoder($format); - } catch (RuntimeException $e) { - return false; - } - - return true; + return $this->encoder->supportsEncoding($format); } /** @@ -285,60 +292,6 @@ public function supportsEncoding($format) */ 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); } }