Skip to content

Commit

Permalink
[Serializer] Added a ChainEncoder and a ChainDecoder
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
stof committed Jul 14, 2012
1 parent cf41bf8 commit 28e137c
Show file tree
Hide file tree
Showing 3 changed files with 183 additions and 66 deletions.
82 changes: 82 additions & 0 deletions src/Symfony/Component/Serializer/Encoder/ChainDecoder.php
@@ -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));
}
}
82 changes: 82 additions & 0 deletions src/Symfony/Component/Serializer/Encoder/ChainEncoder.php
@@ -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));
}
}
85 changes: 19 additions & 66 deletions src/Symfony/Component/Serializer/Serializer.php
Expand Up @@ -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;
Expand All @@ -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();
Expand All @@ -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);
}

/**
Expand All @@ -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);
Expand Down Expand Up @@ -197,15 +210,15 @@ 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);
}

/**
* {@inheritdoc}
*/
final public function decode($data, $format)
{
return $this->getEncoder($format)->decode($data, $format);
return $this->decoder->decode($data, $format);
}

/**
Expand Down Expand Up @@ -271,74 +284,14 @@ 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);
}

/**
* {@inheritdoc}
*/
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);
}
}

0 comments on commit 28e137c

Please sign in to comment.