diff --git a/core/COPYRIGHT.txt b/core/COPYRIGHT.txt index 1c4ad0e..913a27d 100644 --- a/core/COPYRIGHT.txt +++ b/core/COPYRIGHT.txt @@ -64,5 +64,6 @@ PHP - YUI - Copyright (c) 2010 Yahoo! Inc. - Zend Framework (1.10dev - 2010-01-24) - Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + - Serializer - Copyright (c) 2004 - 2012 Fabien Potencier Twig - Copyright (c) 2009 Twig Team diff --git a/core/composer.json b/core/composer.json index b9229e2..ff7ed3e 100644 --- a/core/composer.json +++ b/core/composer.json @@ -9,6 +9,7 @@ "symfony/http-foundation": "2.1.*", "symfony/http-kernel": "2.1.*", "symfony/routing": "2.1.*", + "symfony/serializer": "2.1.*", "symfony/yaml": "2.1.*", "twig/twig": "1.8.*", "doctrine/common": "2.3.*" diff --git a/core/composer.lock b/core/composer.lock index 1fc2aee..17faf57 100644 --- a/core/composer.lock +++ b/core/composer.lock @@ -30,6 +30,10 @@ "version": "v2.1.0-RC2" }, { + "package": "symfony/serializer", + "version": "v2.1.2" + }, + { "package": "symfony/yaml", "version": "v2.1.0-RC2" }, diff --git a/core/vendor/composer/autoload_namespaces.php b/core/vendor/composer/autoload_namespaces.php index 156e974..4aace89 100644 --- a/core/vendor/composer/autoload_namespaces.php +++ b/core/vendor/composer/autoload_namespaces.php @@ -8,6 +8,7 @@ return array( 'Twig_' => $vendorDir . '/twig/twig/lib/', 'Symfony\\Component\\Yaml' => $vendorDir . '/symfony/yaml/', + 'Symfony\\Component\\Serializer' => $vendorDir . '/symfony/serializer/', 'Symfony\\Component\\Routing' => $vendorDir . '/symfony/routing/', 'Symfony\\Component\\HttpKernel' => $vendorDir . '/symfony/http-kernel/', 'Symfony\\Component\\HttpFoundation' => $vendorDir . '/symfony/http-foundation/', diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/CHANGELOG.md b/core/vendor/symfony/serializer/Symfony/Component/Serializer/CHANGELOG.md new file mode 100644 index 0000000..de46533 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/CHANGELOG.md @@ -0,0 +1,44 @@ +CHANGELOG +========= + +2.1.0 +----- + + * added DecoderInterface::supportsDecoding(), + EncoderInterface::supportsEncoding() + * removed NormalizableInterface::denormalize(), + NormalizerInterface::denormalize(), + NormalizerInterface::supportsDenormalization() + * removed normalize() denormalize() encode() decode() supportsSerialization() + supportsDeserialization() supportsEncoding() supportsDecoding() + getEncoder() from SerializerInterface + * Serializer now implements NormalizerInterface, DenormalizerInterface, + EncoderInterface, DecoderInterface in addition to SerializerInterface + * added DenormalizableInterface and DenormalizerInterface + * [BC BREAK] changed `GetSetMethodNormalizer`'s key names from all lowercased + to camelCased (e.g. `mypropertyvalue` to `myPropertyValue`) + * [BC BREAK] convert the `item` XML tag to an array + + ``` xml + + + <![CDATA[title1]]><![CDATA[title2]]> + + ``` + + Before: + + Array() + + After: + + Array( + [item] => Array( + [0] => Array( + [title] => title1 + ) + [1] => Array( + [title] => title2 + ) + ) + ) diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/ChainDecoder.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/ChainDecoder.php new file mode 100644 index 0000000..f555c6a --- /dev/null +++ b/core/vendor/symfony/serializer/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/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/ChainEncoder.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/ChainEncoder.php new file mode 100644 index 0000000..ebb81ef --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/ChainEncoder.php @@ -0,0 +1,105 @@ + + * + * 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\Encoder\NormalizationAwareInterface; +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; + } + + /** + * Checks whether the normalization is needed for the given format. + * + * @param string $format + * + * @return Boolean + */ + public function needsNormalization($format) + { + $encoder = $this->getEncoder($format); + + if (!$encoder instanceof NormalizationAwareInterface) { + return true; + } + + if ($encoder instanceof self) { + return $encoder->needsNormalization($format); + } + + return false; + } + + /** + * Gets the encoder supporting the format. + * + * @param string $format + * + * @return EncoderInterface + * @throws RuntimeException if no encoder is found + */ + 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->supportsEncoding($format)) { + $this->encoderByFormat[$format] = $i; + + return $encoder; + } + } + + throw new RuntimeException(sprintf('No encoder found for format "%s".', $format)); + } +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/DecoderInterface.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/DecoderInterface.php new file mode 100644 index 0000000..21a3678 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/DecoderInterface.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Encoder; + +/** + * Defines the interface of decoders + * + * @author Jordi Boggiano + */ +interface DecoderInterface +{ + /** + * Decodes a string into PHP data + * + * @param scalar $data Data to decode + * @param string $format Format name + * + * @return mixed + */ + public function decode($data, $format); + + /** + * Checks whether the serializer can decode from given format + * + * @param string $format format name + * @return Boolean + */ + public function supportsDecoding($format); +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/EncoderInterface.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/EncoderInterface.php new file mode 100644 index 0000000..b4739ed --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/EncoderInterface.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Encoder; + +/** + * Defines the interface of encoders + * + * @author Jordi Boggiano + */ +interface EncoderInterface +{ + /** + * Encodes data into the given format + * + * @param mixed $data Data to encode + * @param string $format Format name + * + * @return scalar + */ + public function encode($data, $format); + + /** + * Checks whether the serializer can encode to given format + * + * @param string $format format name + * @return Boolean + */ + public function supportsEncoding($format); +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/JsonDecode.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/JsonDecode.php new file mode 100644 index 0000000..3cbbd03 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/JsonDecode.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Encoder; + +/** + * Decodes JSON data + * + * @author Sander Coolen + */ +class JsonDecode implements DecoderInterface +{ + private $associative; + private $recursionDepth; + private $lastError = JSON_ERROR_NONE; + + public function __construct($associative = false, $depth = 512) + { + $this->associative = $associative; + $this->recursionDepth = $depth; + } + + /** + * Returns the last decoding error (if any) + * + * @return integer + * + * @see http://php.net/manual/en/function.json-last-error.php json_last_error + */ + public function getLastError() + { + return $this->lastError; + } + + /** + * Decodes a JSON string into PHP data + * + * @param string $data JSON + * + * @return mixed + */ + public function decode($data, $format) + { + $decodedData = json_decode($data, $this->associative, $this->recursionDepth); + $this->lastError = json_last_error(); + + return $decodedData; + } + + /** + * {@inheritdoc} + */ + public function supportsDecoding($format) + { + return JsonEncoder::FORMAT === $format; + } +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/JsonEncode.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/JsonEncode.php new file mode 100644 index 0000000..8c5a34b --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/JsonEncode.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Encoder; + +/** + * Encodes JSON data + * + * @author Sander Coolen + */ +class JsonEncode implements EncoderInterface +{ + private $options ; + private $lastError = JSON_ERROR_NONE; + + public function __construct($bitmask = 0) + { + $this->options = $bitmask; + } + + /** + * Returns the last encoding error (if any) + * + * @return integer + * + * @see http://php.net/manual/en/function.json-last-error.php json_last_error + */ + public function getLastError() + { + return $this->lastError; + } + + /** + * Encodes PHP data to a JSON string + * + * @param mixed $data + * + * @return string + */ + public function encode($data, $format) + { + $encodedJson = json_encode($data, $this->options); + $this->lastError = json_last_error(); + + return $encodedJson; + } + + /** + * {@inheritdoc} + */ + public function supportsEncoding($format) + { + return JsonEncoder::FORMAT === $format; + } +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/JsonEncoder.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/JsonEncoder.php new file mode 100644 index 0000000..73918b7 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/JsonEncoder.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Encoder; + +/** + * Encodes JSON data + * + * @author Jordi Boggiano + */ +class JsonEncoder implements EncoderInterface, DecoderInterface +{ + const FORMAT = 'json'; + + /** + * @var JsonEncode + */ + protected $encodingImpl; + + /** + * @var JsonDecode + */ + protected $decodingImpl; + + public function __construct(JsonEncode $encodingImpl = null, JsonDecode $decodingImpl = null) + { + $this->encodingImpl = null === $encodingImpl ? new JsonEncode() : $encodingImpl; + $this->decodingImpl = null === $decodingImpl ? new JsonDecode(true) : $decodingImpl; + } + + /** + * Returns the last encoding error (if any) + * + * @return integer + */ + public function getLastEncodingError() + { + return $this->encodingImpl->getLastError(); + } + + /** + * Returns the last decoding error (if any) + * + * @return integer + */ + public function getLastDecodingError() + { + return $this->decodingImpl->getLastError(); + } + + /** + * {@inheritdoc} + */ + public function encode($data, $format) + { + return $this->encodingImpl->encode($data, self::FORMAT); + } + + /** + * {@inheritdoc} + */ + public function decode($data, $format) + { + return $this->decodingImpl->decode($data, self::FORMAT); + } + + /** + * {@inheritdoc} + */ + public function supportsEncoding($format) + { + return self::FORMAT === $format; + } + + /** + * {@inheritdoc} + */ + public function supportsDecoding($format) + { + return self::FORMAT === $format; + } +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/NormalizationAwareInterface.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/NormalizationAwareInterface.php new file mode 100644 index 0000000..8101332 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/NormalizationAwareInterface.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Encoder; + +/** + * Defines the interface of encoders that will normalize data themselves + * + * Implementing this interface essentially just tells the Serializer that the + * data should not be pre-normalized before being passed to this Encoder. + * + * @author Jordi Boggiano + */ +interface NormalizationAwareInterface +{ +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/SerializerAwareEncoder.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/SerializerAwareEncoder.php new file mode 100644 index 0000000..80bbb23 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/SerializerAwareEncoder.php @@ -0,0 +1,33 @@ + + * + * 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\SerializerInterface; +use Symfony\Component\Serializer\SerializerAwareInterface; + +/** + * SerializerAware Encoder implementation + * + * @author Jordi Boggiano + */ +abstract class SerializerAwareEncoder implements SerializerAwareInterface +{ + protected $serializer; + + /** + * {@inheritdoc} + */ + public function setSerializer(SerializerInterface $serializer) + { + $this->serializer = $serializer; + } +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/XmlEncoder.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/XmlEncoder.php new file mode 100644 index 0000000..cb46926 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Encoder/XmlEncoder.php @@ -0,0 +1,393 @@ + + * + * 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\Exception\UnexpectedValueException; + +/** + * Encodes XML data + * + * @author Jordi Boggiano + * @author John Wards + * @author Fabian Vogler + */ +class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, DecoderInterface, NormalizationAwareInterface +{ + private $dom; + private $format; + private $rootNodeName = 'response'; + + /** + * {@inheritdoc} + */ + public function encode($data, $format) + { + if ($data instanceof \DOMDocument) { + return $data->saveXML(); + } + + $this->dom = new \DOMDocument(); + $this->format = $format; + + if (null !== $data && !is_scalar($data)) { + $root = $this->dom->createElement($this->rootNodeName); + $this->dom->appendChild($root); + $this->buildXml($root, $data); + } else { + $this->appendNode($this->dom, $data, $this->rootNodeName); + } + + return $this->dom->saveXML(); + } + + /** + * {@inheritdoc} + */ + public function decode($data, $format) + { + $internalErrors = libxml_use_internal_errors(true); + $disableEntities = libxml_disable_entity_loader(true); + libxml_clear_errors(); + + $dom = new \DOMDocument(); + $dom->loadXML($data, LIBXML_NONET); + + libxml_use_internal_errors($internalErrors); + libxml_disable_entity_loader($disableEntities); + + foreach ($dom->childNodes as $child) { + if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) { + throw new UnexpectedValueException('Document types are not allowed.'); + } + } + + $xml = simplexml_import_dom($dom); + + if ($error = libxml_get_last_error()) { + throw new UnexpectedValueException($error->message); + } + + if (!$xml->count()) { + if (!$xml->attributes()) { + return (string) $xml; + } + $data = array(); + foreach ($xml->attributes() as $attrkey => $attr) { + $data['@'.$attrkey] = (string) $attr; + } + $data['#'] = (string) $xml; + + return $data; + } + + return $this->parseXml($xml); + } + + /** + * Checks whether the serializer can encode to given format + * + * @param string $format format name + * @return Boolean + */ + public function supportsEncoding($format) + { + return 'xml' === $format; + } + + /** + * Checks whether the serializer can decode from given format + * + * @param string $format format name + * @return Boolean + */ + public function supportsDecoding($format) + { + return 'xml' === $format; + } + + /** + * Sets the root node name + * @param string $name root node name + */ + public function setRootNodeName($name) + { + $this->rootNodeName = $name; + } + + /** + * Returns the root node name + * @return string + */ + public function getRootNodeName() + { + return $this->rootNodeName; + } + + /** + * @param DOMNode $node + * @param string $val + * + * @return Boolean + */ + final protected function appendXMLString($node, $val) + { + if (strlen($val) > 0) { + $frag = $this->dom->createDocumentFragment(); + $frag->appendXML($val); + $node->appendChild($frag); + + return true; + } + + return false; + } + + /** + * @param DOMNode $node + * @param string $val + * + * @return Boolean + */ + final protected function appendText($node, $val) + { + $nodeText = $this->dom->createTextNode($val); + $node->appendChild($nodeText); + + return true; + } + + /** + * @param DOMNode $node + * @param string $val + * + * @return Boolean + */ + final protected function appendCData($node, $val) + { + $nodeText = $this->dom->createCDATASection($val); + $node->appendChild($nodeText); + + return true; + } + + /** + * @param DOMNode $node + * @param DOMDocumentFragment $fragment + * + * @return Boolean + */ + final protected function appendDocumentFragment($node, $fragment) + { + if ($fragment instanceof \DOMDocumentFragment) { + $node->appendChild($fragment); + + return true; + } + + return false; + } + + /** + * Checks the name is a valid xml element name + * + * @param string $name + * + * @return Boolean + */ + final protected function isElementNameValid($name) + { + return $name && + false === strpos($name, ' ') && + preg_match('#^[\pL_][\pL0-9._-]*$#ui', $name); + } + + /** + * Parse the input SimpleXmlElement into an array. + * + * @param SimpleXmlElement $node xml to parse + * + * @return array + */ + private function parseXml($node) + { + $data = array(); + if ($node->attributes()) { + foreach ($node->attributes() as $attrkey => $attr) { + $data['@'.$attrkey] = (string) $attr; + } + } + foreach ($node->children() as $key => $subnode) { + if ($subnode->count()) { + $value = $this->parseXml($subnode); + } elseif ($subnode->attributes()) { + $value = array(); + foreach ($subnode->attributes() as $attrkey => $attr) { + $value['@'.$attrkey] = (string) $attr; + } + $value['#'] = (string) $subnode; + } else { + $value = (string) $subnode; + } + + if ($key === 'item') { + if (isset($value['@key'])) { + $data[(string) $value['@key']] = $value['#']; + } else { + $data['item'][] = $value; + } + } elseif (array_key_exists($key, $data)) { + if ((false === is_array($data[$key])) || (false === isset($data[$key][0]))) { + $data[$key] = array($data[$key]); + } + $data[$key][] = $value; + } else { + $data[$key] = $value; + } + } + + return $data; + } + + /** + * Parse the data and convert it to DOMElements + * + * @param DOMNode $parentNode + * @param array|object $data data + * + * @return Boolean + */ + private function buildXml($parentNode, $data) + { + $append = true; + + if (is_array($data) || $data instanceof \Traversable) { + foreach ($data as $key => $data) { + //Ah this is the magic @ attribute types. + if (0 === strpos($key, "@") && is_scalar($data) && $this->isElementNameValid($attributeName = substr($key, 1))) { + $parentNode->setAttribute($attributeName, $data); + } elseif ($key === '#') { + $append = $this->selectNodeType($parentNode, $data); + } elseif (is_array($data) && false === is_numeric($key)) { + /** + * Is this array fully numeric keys? + */ + if (ctype_digit(implode('', array_keys($data)))) { + /** + * Create nodes to append to $parentNode based on the $key of this array + * Produces 01 + * From array("item" => array(0,1)); + */ + foreach ($data as $subData) { + $append = $this->appendNode($parentNode, $subData, $key); + } + } else { + $append = $this->appendNode($parentNode, $data, $key); + } + } elseif (is_numeric($key) || !$this->isElementNameValid($key)) { + $append = $this->appendNode($parentNode, $data, "item", $key); + } else { + $append = $this->appendNode($parentNode, $data, $key); + } + } + + return $append; + } + if (is_object($data)) { + $data = $this->serializer->normalize($data, $this->format); + if (null !== $data && !is_scalar($data)) { + return $this->buildXml($parentNode, $data); + } + // top level data object was normalized into a scalar + if (!$parentNode->parentNode->parentNode) { + $root = $parentNode->parentNode; + $root->removeChild($parentNode); + + return $this->appendNode($root, $data, $this->rootNodeName); + } + + return $this->appendNode($parentNode, $data, 'data'); + } + throw new UnexpectedValueException('An unexpected value could not be serialized: '.var_export($data, true)); + } + + /** + * Selects the type of node to create and appends it to the parent. + * + * @param DOMNode $parentNode + * @param array|object $data + * @param string $nodeName + * @param string $key + * + * @return Boolean + */ + private function appendNode($parentNode, $data, $nodeName, $key = null) + { + $node = $this->dom->createElement($nodeName); + if (null !== $key) { + $node->setAttribute('key', $key); + } + $appendNode = $this->selectNodeType($node, $data); + // we may have decided not to append this node, either in error or if its $nodeName is not valid + if ($appendNode) { + $parentNode->appendChild($node); + } + + return $appendNode; + } + + /** + * Checks if a value contains any characters which would require CDATA wrapping. + * + * @param string $val + * + * @return Boolean + */ + private function needsCdataWrapping($val) + { + return preg_match('/[<>&]/', $val); + } + + /** + * Tests the value being passed and decide what sort of element to create + * + * @param DOMNode $node + * @param mixed $val + * + * @return Boolean + */ + private function selectNodeType($node, $val) + { + if (is_array($val)) { + return $this->buildXml($node, $val); + } elseif ($val instanceof \SimpleXMLElement) { + $child = $this->dom->importNode(dom_import_simplexml($val), true); + $node->appendChild($child); + } elseif ($val instanceof \Traversable) { + $this->buildXml($node, $val); + } elseif (is_object($val)) { + return $this->buildXml($node, $this->serializer->normalize($val, $this->format)); + } elseif (is_numeric($val)) { + return $this->appendText($node, (string) $val); + } elseif (is_string($val) && $this->needsCdataWrapping($val)) { + return $this->appendCData($node, $val); + } elseif (is_string($val)) { + return $this->appendText($node, $val); + } elseif (is_bool($val)) { + return $this->appendText($node, (int) $val); + } elseif ($val instanceof \DOMNode) { + $child = $this->dom->importNode($val, true); + $node->appendChild($child); + } + + return true; + } +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Exception/Exception.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Exception/Exception.php new file mode 100644 index 0000000..a141164 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Exception/Exception.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Exception; + +/** + * Base exception + * + * @author Johannes M. Schmitt + */ +interface Exception +{ +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Exception/InvalidArgumentException.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Exception/InvalidArgumentException.php new file mode 100644 index 0000000..d55e5ef --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Exception/InvalidArgumentException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Exception; + +/** + * InvalidArgumentException + * + * @author Johannes M. Schmitt + */ +class InvalidArgumentException extends \InvalidArgumentException implements Exception +{ +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Exception/LogicException.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Exception/LogicException.php new file mode 100644 index 0000000..354272f --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Exception/LogicException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Exception; + +/** + * LogicException + * + * @author Lukas Kahwe Smith + */ +class LogicException extends \LogicException implements Exception +{ +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Exception/RuntimeException.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Exception/RuntimeException.php new file mode 100644 index 0000000..afbf1db --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Exception/RuntimeException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Exception; + +/** + * RuntimeException + * + * @author Johannes M. Schmitt + */ +class RuntimeException extends \RuntimeException implements Exception +{ +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Exception/UnexpectedValueException.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Exception/UnexpectedValueException.php new file mode 100644 index 0000000..c4bc0ce --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Exception/UnexpectedValueException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Exception; + +/** + * UnexpectedValueException + * + * @author Lukas Kahwe Smith + */ +class UnexpectedValueException extends \UnexpectedValueException implements Exception +{ +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Exception/UnsupportedException.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Exception/UnsupportedException.php new file mode 100644 index 0000000..5a79efa --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Exception/UnsupportedException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Exception; + +/** + * UnsupportedException + * + * @author Johannes M. Schmitt + */ +class UnsupportedException extends InvalidArgumentException +{ +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/LICENSE b/core/vendor/symfony/serializer/Symfony/Component/Serializer/LICENSE new file mode 100644 index 0000000..cdffe7a --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-2012 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Normalizer/CustomNormalizer.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Normalizer/CustomNormalizer.php new file mode 100644 index 0000000..aba4df8 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Normalizer/CustomNormalizer.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Normalizer; + +/** + * @author Jordi Boggiano + */ +class CustomNormalizer extends SerializerAwareNormalizer implements NormalizerInterface, DenormalizerInterface +{ + /** + * {@inheritdoc} + */ + public function normalize($object, $format = null) + { + return $object->normalize($this->serializer, $format); + } + + /** + * {@inheritdoc} + */ + public function denormalize($data, $class, $format = null) + { + $object = new $class; + $object->denormalize($this->serializer, $data, $format); + + return $object; + } + + /** + * Checks if the given class implements the NormalizableInterface. + * + * @param mixed $data Data to normalize. + * @param string $format The format being (de-)serialized from or into. + * @return Boolean + */ + public function supportsNormalization($data, $format = null) + { + return $data instanceof NormalizableInterface; + } + + /** + * Checks if the given class implements the NormalizableInterface. + * + * @param mixed $data Data to denormalize from. + * @param string $type The class to which the data should be denormalized. + * @param string $format The format being deserialized from. + * @return Boolean + */ + public function supportsDenormalization($data, $type, $format = null) + { + $class = new \ReflectionClass($type); + + return $class->isSubclassOf('Symfony\Component\Serializer\Normalizer\DenormalizableInterface'); + } +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Normalizer/DenormalizableInterface.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Normalizer/DenormalizableInterface.php new file mode 100644 index 0000000..3f3bf88 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Normalizer/DenormalizableInterface.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Normalizer; + +/** + * Defines the most basic interface a class must implement to be denormalizable + * + * If a denormalizer is registered for the class and it doesn't implement + * the Denormalizable interfaces, the normalizer will be used instead + * + * @author Jordi Boggiano + */ +interface DenormalizableInterface +{ + /** + * Denormalizes the object back from an array of scalars|arrays. + * + * It is important to understand that the denormalize() call should denormalize + * recursively all child objects of the implementor. + * + * @param DenormalizerInterface $denormalizer The denormalizer is given so that you + * can use it to denormalize objects contained within this object. + * @param array|scalar $data The data from which to re-create the object. + * @param string|null $format The format is optionally given to be able to denormalize differently + * based on different input formats. + */ + public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null); +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php new file mode 100644 index 0000000..7c4fd4f --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Normalizer; + +/** + * Defines the interface of denormalizers. + * + * @author Jordi Boggiano + */ +interface DenormalizerInterface +{ + /** + * Denormalizes data back into an object of the given class + * + * @param mixed $data data to restore + * @param string $class the expected class to instantiate + * @param string $format format the given data was extracted from + * @return object + */ + public function denormalize($data, $class, $format = null); + + /** + * Checks whether the given class is supported for denormalization by this normalizer + * + * @param mixed $data Data to denormalize from. + * @param string $type The class to which the data should be denormalized. + * @param string $format The format being deserialized from. + * @return Boolean + */ + public function supportsDenormalization($data, $type, $format = null); +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php new file mode 100644 index 0000000..4dfe177 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php @@ -0,0 +1,190 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Normalizer; + +use Symfony\Component\Serializer\Exception\RuntimeException; + +/** + * Converts between objects with getter and setter methods and arrays. + * + * The normalization process looks at all public methods and calls the ones + * which have a name starting with get and take no parameters. The result is a + * map from property names (method name stripped of the get prefix and converted + * to lower case) to property values. Property values are normalized through the + * serializer. + * + * The denormalization first looks at the constructor of the given class to see + * if any of the parameters have the same name as one of the properties. The + * constructor is then called with all parameters or an exception is thrown if + * any required parameters were not present as properties. Then the denormalizer + * walks through the given map of property names to property values to see if a + * setter method exists for any of the properties. If a setter exists it is + * called with the property value. No automatic denormalization of the value + * takes place. + * + * @author Nils Adermann + */ +class GetSetMethodNormalizer extends SerializerAwareNormalizer implements NormalizerInterface, DenormalizerInterface +{ + protected $callbacks = array(); + protected $ignoredAttributes = array(); + + /** + * Set normalization callbacks + * + * @param array $callbacks help normalize the result + */ + public function setCallbacks(array $callbacks) + { + foreach ($callbacks as $attribute => $callback) { + if (!is_callable($callback)) { + throw new \InvalidArgumentException(sprintf('The given callback for attribute "%s" is not callable.', $attribute)); + } + } + $this->callbacks = $callbacks; + } + + /** + * Set ignored attributes for normalization + * + * @param array $ignoredAttributes + */ + public function setIgnoredAttributes(array $ignoredAttributes) + { + $this->ignoredAttributes = $ignoredAttributes; + } + + /** + * {@inheritdoc} + */ + public function normalize($object, $format = null) + { + $reflectionObject = new \ReflectionObject($object); + $reflectionMethods = $reflectionObject->getMethods(\ReflectionMethod::IS_PUBLIC); + + $attributes = array(); + foreach ($reflectionMethods as $method) { + if ($this->isGetMethod($method)) { + $attributeName = lcfirst(substr($method->name, 3)); + + if (in_array($attributeName, $this->ignoredAttributes)) { + continue; + } + + $attributeValue = $method->invoke($object); + if (array_key_exists($attributeName, $this->callbacks)) { + $attributeValue = call_user_func($this->callbacks[$attributeName], $attributeValue); + } + if (null !== $attributeValue && !is_scalar($attributeValue)) { + $attributeValue = $this->serializer->normalize($attributeValue, $format); + } + + $attributes[$attributeName] = $attributeValue; + } + } + + return $attributes; + } + + /** + * {@inheritdoc} + */ + public function denormalize($data, $class, $format = null) + { + $reflectionClass = new \ReflectionClass($class); + $constructor = $reflectionClass->getConstructor(); + + if ($constructor) { + $constructorParameters = $constructor->getParameters(); + + $params = array(); + foreach ($constructorParameters as $constructorParameter) { + $paramName = lcfirst($constructorParameter->name); + + if (isset($data[$paramName])) { + $params[] = $data[$paramName]; + // don't run set for a parameter passed to the constructor + unset($data[$paramName]); + } elseif (!$constructorParameter->isOptional()) { + throw new RuntimeException( + 'Cannot create an instance of '.$class. + ' from serialized data because its constructor requires '. + 'parameter "'.$constructorParameter->name. + '" to be present.'); + } + } + + $object = $reflectionClass->newInstanceArgs($params); + } else { + $object = new $class; + } + + foreach ($data as $attribute => $value) { + $setter = 'set'.$attribute; + if (method_exists($object, $setter)) { + $object->$setter($value); + } + } + + return $object; + } + + /** + * {@inheritDoc} + */ + public function supportsNormalization($data, $format = null) + { + return is_object($data) && $this->supports(get_class($data)); + } + + /** + * {@inheritDoc} + */ + public function supportsDenormalization($data, $type, $format = null) + { + return $this->supports($type); + } + + /** + * Checks if the given class has any get{Property} method. + * + * @param string $class + * @return Boolean + */ + private function supports($class) + { + $class = new \ReflectionClass($class); + $methods = $class->getMethods(\ReflectionMethod::IS_PUBLIC); + foreach ($methods as $method) { + if ($this->isGetMethod($method)) { + return true; + } + } + + return false; + } + + /** + * Checks if a method's name is get.* and can be called without parameters. + * + * @param ReflectionMethod $method the method to check + * @return Boolean whether the method is a getter. + */ + private function isGetMethod(\ReflectionMethod $method) + { + return ( + 0 === strpos($method->name, 'get') && + 3 < strlen($method->name) && + 0 === $method->getNumberOfRequiredParameters() + ); + } +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Normalizer/NormalizableInterface.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Normalizer/NormalizableInterface.php new file mode 100644 index 0000000..b7b8e51 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Normalizer/NormalizableInterface.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Normalizer; + +/** + * Defines the most basic interface a class must implement to be normalizable + * + * If a normalizer is registered for the class and it doesn't implement + * the Normalizable interfaces, the normalizer will be used instead + * + * @author Jordi Boggiano + */ +interface NormalizableInterface +{ + /** + * Normalizes the object into an array of scalars|arrays. + * + * It is important to understand that the normalize() call should normalize + * recursively all child objects of the implementor. + * + * @param NormalizerInterface $normalizer The normalizer is given so that you + * can use it to normalize objects contained within this object. + * @param string|null $format The format is optionally given to be able to normalize differently + * based on different output formats. + * @return array|scalar + */ + public function normalize(NormalizerInterface $normalizer, $format = null); +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php new file mode 100644 index 0000000..7b90d18 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Normalizer; + +/** + * Defines the interface of normalizers. + * + * @author Jordi Boggiano + */ +interface NormalizerInterface +{ + /** + * Normalizes an object into a set of arrays/scalars + * + * @param object $object object to normalize + * @param string $format format the normalization result will be encoded as + * @return array|scalar + */ + public function normalize($object, $format = null); + + /** + * Checks whether the given class is supported for normalization by this normalizer + * + * @param mixed $data Data to normalize. + * @param string $format The format being (de-)serialized from or into. + * @return Boolean + */ + public function supportsNormalization($data, $format = null); +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.php new file mode 100644 index 0000000..49916be --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Normalizer; + +use Symfony\Component\Serializer\SerializerInterface; +use Symfony\Component\Serializer\SerializerAwareInterface; + +/** + * SerializerAware Normalizer implementation + * + * @author Jordi Boggiano + */ +abstract class SerializerAwareNormalizer implements SerializerAwareInterface +{ + /** + * @var SerializerInterface + */ + protected $serializer; + + /** + * {@inheritdoc} + */ + public function setSerializer(SerializerInterface $serializer) + { + $this->serializer = $serializer; + } +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/README.md b/core/vendor/symfony/serializer/Symfony/Component/Serializer/README.md new file mode 100644 index 0000000..df74a9a --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/README.md @@ -0,0 +1,13 @@ +Serializer Component +==================== + +With the Serializer component its possible to handle serializing data structures, +including object graphs, into array structures or other formats like XML and JSON. +It can also handle deserializing XML and JSON back to object graphs. + +Resources +--------- + +You can run the unit tests with the following command: + + phpunit diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Serializer.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Serializer.php new file mode 100644 index 0000000..f2c513b --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Serializer.php @@ -0,0 +1,291 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +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\Normalizer\NormalizerInterface; +use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; +use Symfony\Component\Serializer\Exception\RuntimeException; +use Symfony\Component\Serializer\Exception\LogicException; +use Symfony\Component\Serializer\Exception\UnexpectedValueException; + +/** + * Serializer serializes and deserializes data + * + * objects are turned into arrays by normalizers + * arrays are turned into various output formats by encoders + * + * $serializer->serialize($obj, 'xml') + * $serializer->decode($data, 'xml') + * $serializer->denormalize($data, 'Class', 'xml') + * + * @author Jordi Boggiano + * @author Johannes M. Schmitt + * @author Lukas Kahwe Smith + */ +class Serializer implements SerializerInterface, NormalizerInterface, DenormalizerInterface, EncoderInterface, DecoderInterface +{ + protected $encoder; + protected $decoder; + protected $normalizers = array(); + protected $normalizerCache = array(); + protected $denormalizerCache = array(); + + public function __construct(array $normalizers = array(), array $encoders = array()) + { + foreach ($normalizers as $normalizer) { + if ($normalizer instanceof SerializerAwareInterface) { + $normalizer->setSerializer($this); + } + } + $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->encoder = new ChainEncoder($realEncoders); + $this->decoder = new ChainDecoder($decoders); + } + + /** + * {@inheritdoc} + */ + final public function serialize($data, $format) + { + if (!$this->supportsEncoding($format)) { + throw new UnexpectedValueException('Serialization for the format '.$format.' is not supported'); + } + + if ($this->encoder->needsNormalization($format)) { + $data = $this->normalize($data, $format); + } + + return $this->encode($data, $format); + } + + /** + * {@inheritdoc} + */ + final public function deserialize($data, $type, $format) + { + if (!$this->supportsDecoding($format)) { + throw new UnexpectedValueException('Deserialization for the format '.$format.' is not supported'); + } + + $data = $this->decode($data, $format); + + return $this->denormalize($data, $type, $format); + } + + /** + * {@inheritdoc} + */ + public function normalize($data, $format = null) + { + if (null === $data || is_scalar($data)) { + return $data; + } + if (is_object($data) && $this->supportsNormalization($data, $format)) { + return $this->normalizeObject($data, $format); + } + if ($data instanceof \Traversable) { + $normalized = array(); + foreach ($data as $key => $val) { + $normalized[$key] = $this->normalize($val, $format); + } + + return $normalized; + } + if (is_object($data)) { + return $this->normalizeObject($data, $format); + } + if (is_array($data)) { + foreach ($data as $key => $val) { + $data[$key] = $this->normalize($val, $format); + } + + return $data; + } + throw new UnexpectedValueException('An unexpected value could not be normalized: '.var_export($data, true)); + } + + /** + * {@inheritdoc} + */ + public function denormalize($data, $type, $format = null) + { + return $this->denormalizeObject($data, $type, $format); + } + + /** + * {@inheritdoc} + */ + public function supportsNormalization($data, $format = null) + { + try { + $this->getNormalizer($data, $format); + } catch (RuntimeException $e) { + return false; + } + + return true; + } + + /** + * {@inheritdoc} + */ + public function supportsDenormalization($data, $type, $format = null) + { + try { + $this->getDenormalizer($data, $type, $format = null); + } catch (RuntimeException $e) { + return false; + } + + return true; + } + + /** + * {@inheritdoc} + */ + private function getNormalizer($data, $format = null) + { + foreach ($this->normalizers as $normalizer) { + if ($normalizer instanceof NormalizerInterface + && $normalizer->supportsNormalization($data, $format) + ) { + return $normalizer; + } + } + + throw new RuntimeException(sprintf('No normalizer found for format "%s".', $format)); + } + + /** + * {@inheritdoc} + */ + private function getDenormalizer($data, $type, $format = null) + { + foreach ($this->normalizers as $normalizer) { + if ($normalizer instanceof DenormalizerInterface + && $normalizer->supportsDenormalization($data, $type, $format) + ) { + return $normalizer; + } + } + + throw new RuntimeException(sprintf('No denormalizer found for format "%s".', $format)); + } + + /** + * {@inheritdoc} + */ + final public function encode($data, $format) + { + return $this->encoder->encode($data, $format); + } + + /** + * {@inheritdoc} + */ + final public function decode($data, $format) + { + return $this->decoder->decode($data, $format); + } + + /** + * Normalizes an object into a set of arrays/scalars + * + * @param object $object object to normalize + * @param string $format format name, present to give the option to normalizers to act differently based on formats + * @return array|scalar + */ + private function normalizeObject($object, $format = null) + { + if (!$this->normalizers) { + throw new LogicException('You must register at least one normalizer to be able to normalize objects.'); + } + + $class = get_class($object); + if (isset($this->normalizerCache[$class][$format])) { + return $this->normalizerCache[$class][$format]->normalize($object, $format); + } + + foreach ($this->normalizers as $normalizer) { + if ($normalizer->supportsNormalization($object, $format)) { + $this->normalizerCache[$class][$format] = $normalizer; + + return $normalizer->normalize($object, $format); + } + } + + throw new UnexpectedValueException('Could not normalize object of type '.$class.', no supporting normalizer found.'); + } + + /** + * Denormalizes data back into an object of the given class + * + * @param mixed $data data to restore + * @param string $class the expected class to instantiate + * @param string $format format name, present to give the option to normalizers to act differently based on formats + * @return object + */ + private function denormalizeObject($data, $class, $format = null) + { + if (!$this->normalizers) { + throw new LogicException('You must register at least one normalizer to be able to denormalize objects.'); + } + + if (isset($this->denormalizerCache[$class][$format])) { + return $this->denormalizerCache[$class][$format]->denormalize($data, $class, $format); + } + + foreach ($this->normalizers as $normalizer) { + if ($normalizer->supportsDenormalization($data, $class, $format)) { + $this->denormalizerCache[$class][$format] = $normalizer; + + return $normalizer->denormalize($data, $class, $format); + } + } + + throw new UnexpectedValueException('Could not denormalize object of type '.$class.', no supporting normalizer found.'); + } + + /** + * {@inheritdoc} + */ + public function supportsEncoding($format) + { + return $this->encoder->supportsEncoding($format); + } + + /** + * {@inheritdoc} + */ + public function supportsDecoding($format) + { + return $this->decoder->supportsDecoding($format); + } +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/SerializerAwareInterface.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/SerializerAwareInterface.php new file mode 100644 index 0000000..dd0bb60 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/SerializerAwareInterface.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer; + +use Symfony\Component\Serializer\SerializerInterface; + +/** + * Defines the interface of encoders + * + * @author Jordi Boggiano + */ +interface SerializerAwareInterface +{ + /** + * Sets the owning Serializer object + * + * @param SerializerInterface $serializer + */ + public function setSerializer(SerializerInterface $serializer); +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/SerializerInterface.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/SerializerInterface.php new file mode 100644 index 0000000..f187959 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/SerializerInterface.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer; + +/** + * Defines the interface of the Serializer + * + * @author Jordi Boggiano + */ +interface SerializerInterface +{ + /** + * Serializes data in the appropriate format + * + * @param mixed $data any data + * @param string $format format name + * @return string + */ + public function serialize($data, $format); + + /** + * Deserializes data into the given type. + * + * @param mixed $data + * @param string $type + * @param string $format + */ + public function deserialize($data, $type, $format); +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php new file mode 100644 index 0000000..4986f79 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php @@ -0,0 +1,296 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Tests\Encoder; + +use Symfony\Component\Serializer\Tests\Fixtures\Dummy; +use Symfony\Component\Serializer\Tests\Fixtures\ScalarDummy; +use Symfony\Component\Serializer\Encoder\XmlEncoder; +use Symfony\Component\Serializer\Serializer; +use Symfony\Component\Serializer\Exception\UnexpectedValueException; +use Symfony\Component\Serializer\Normalizer\CustomNormalizer; + +class XmlEncoderTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + $this->encoder = new XmlEncoder; + $serializer = new Serializer(array(new CustomNormalizer()), array('xml' => new XmlEncoder())); + $this->encoder->setSerializer($serializer); + } + + public function testEncodeScalar() + { + $obj = new ScalarDummy; + $obj->xmlFoo = "foo"; + + $expected = ''."\n". + 'foo'."\n"; + + $this->assertEquals($expected, $this->encoder->encode($obj, 'xml')); + } + + public function testSetRootNodeName() + { + $obj = new ScalarDummy; + $obj->xmlFoo = "foo"; + + $this->encoder->setRootNodeName('test'); + $expected = ''."\n". + 'foo'."\n"; + + $this->assertEquals($expected, $this->encoder->encode($obj, 'xml')); + } + + /** + * @expectedException UnexpectedValueException + * @expectedExceptionMessage Document types are not allowed. + */ + public function testDocTypeIsNotAllowed() + { + $this->encoder->decode('', 'foo'); + } + + public function testAttributes() + { + $obj = new ScalarDummy; + $obj->xmlFoo = array( + 'foo-bar' => array( + '@id' => 1, + '@name' => 'Bar' + ), + 'Foo' => array( + 'Bar' => "Test", + '@Type' => 'test' + ), + 'föo_bär' => 'a', + "Bar" => array(1,2,3), + 'a' => 'b', + ); + $expected = ''."\n". + ''. + ''. + 'Test'. + 'a'. + '1'. + '2'. + '3'. + 'b'. + ''."\n"; + $this->assertEquals($expected, $this->encoder->encode($obj, 'xml')); + } + + public function testElementNameValid() + { + $obj = new ScalarDummy; + $obj->xmlFoo = array( + 'foo-bar' => 'a', + 'foo_bar' => 'a', + 'föo_bär' => 'a', + ); + + $expected = ''."\n". + ''. + 'a'. + 'a'. + 'a'. + ''."\n"; + + $this->assertEquals($expected, $this->encoder->encode($obj, 'xml')); + } + + public function testEncodeSimpleXML() + { + $xml = simplexml_load_string('Peter'); + $array = array('person' => $xml); + + $expected = ''."\n". + 'Peter'."\n"; + + $this->assertEquals($expected, $this->encoder->encode($array, 'xml')); + } + + public function testEncodeScalarRootAttributes() + { + $array = array( + '#' => 'Paul', + '@gender' => 'm' + ); + + $expected = ''."\n". + 'Paul'."\n"; + + $this->assertEquals($expected, $this->encoder->encode($array, 'xml')); + } + + public function testEncodeRootAttributes() + { + $array = array( + 'firstname' => 'Paul', + '@gender' => 'm' + ); + + $expected = ''."\n". + 'Paul'."\n"; + + $this->assertEquals($expected, $this->encoder->encode($array, 'xml')); + } + + public function testEncodeCdataWrapping() + { + $array = array( + 'firstname' => 'Paul ', + ); + + $expected = ''."\n". + ']]>'."\n"; + + $this->assertEquals($expected, $this->encoder->encode($array, 'xml')); + } + + public function testEncodeScalarWithAttribute() + { + $array = array( + 'person' => array('@gender' => 'M', '#' => 'Peter'), + ); + + $expected = ''."\n". + 'Peter'."\n"; + + $this->assertEquals($expected, $this->encoder->encode($array, 'xml')); + } + + public function testDecodeScalar() + { + $source = ''."\n". + 'foo'."\n"; + + $this->assertEquals('foo', $this->encoder->decode($source, 'xml')); + } + + public function testEncode() + { + $source = $this->getXmlSource(); + $obj = $this->getObject(); + + $this->assertEquals($source, $this->encoder->encode($obj, 'xml')); + } + + public function testDecode() + { + $source = $this->getXmlSource(); + $obj = $this->getObject(); + + $this->assertEquals(get_object_vars($obj), $this->encoder->decode($source, 'xml')); + } + + public function testDecodeScalarWithAttribute() + { + $source = ''."\n". + 'Peter'."\n"; + + $expected = array( + 'person' => array('@gender' => 'M', '#' => 'Peter'), + ); + + $this->assertEquals($expected, $this->encoder->decode($source, 'xml')); + } + + public function testDecodeScalarRootAttributes() + { + $source = ''."\n". + 'Peter'."\n"; + + $expected = array( + '#' => 'Peter', + '@gender' => 'M' + ); + + $this->assertEquals($expected, $this->encoder->decode($source, 'xml')); + } + + public function testDecodeRootAttributes() + { + $source = ''."\n". + 'PeterMac Calloway'."\n"; + + $expected = array( + 'firstname' => 'Peter', + 'lastname' => 'Mac Calloway', + '@gender' => 'M' + ); + + $this->assertEquals($expected, $this->encoder->decode($source, 'xml')); + } + + public function testDecodeArray() + { + $source = ''."\n". + ''. + ''. + 'BenjaminAlexandre'. + 'DamienClay'. + ''. + ''."\n"; + + $expected = array( + 'people' => array('person' => array( + array('firstname' => 'Benjamin', 'lastname' => 'Alexandre'), + array('firstname' => 'Damien', 'lastname' => 'Clay') + )) + ); + + $this->assertEquals($expected, $this->encoder->decode($source, 'xml')); + } + + public function testPreventsComplexExternalEntities() + { + $oldCwd = getcwd(); + chdir(__DIR__); + + try { + $this->encoder->decode(']>&test;', 'xml'); + chdir($oldCwd); + + $this->fail('No exception was thrown.'); + } catch (\Exception $e) { + chdir($oldCwd); + + if (!$e instanceof UnexpectedValueException) { + $this->fail('Expected UnexpectedValueException'); + } + } + } + + protected function getXmlSource() + { + return ''."\n". + ''. + 'foo'. + 'ab'. + 'valvalbar'. + 'title1title2'. + 'Ed'. + '1'. + ''."\n"; + } + + protected function getObject() + { + $obj = new Dummy; + $obj->foo = 'foo'; + $obj->bar = array('a', 'b'); + $obj->baz = array('key' => 'val', 'key2' => 'val', 'A B' => 'bar', 'item' => array(array('title' => 'title1'), array('title' => 'title2')), 'Barry' => array('FooBar' => array('Baz' => 'Ed', '@id' => 1))); + $obj->qux = "1"; + + return $obj; + } +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Fixtures/DenormalizableDummy.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Fixtures/DenormalizableDummy.php new file mode 100644 index 0000000..468d444 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Fixtures/DenormalizableDummy.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Tests\Fixtures; + +use Symfony\Component\Serializer\Normalizer\DenormalizableInterface; +use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; + +class DenormalizableDummy implements DenormalizableInterface +{ + + public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null) + { + + } + +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Fixtures/Dummy.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Fixtures/Dummy.php new file mode 100644 index 0000000..cdcf510 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Fixtures/Dummy.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Tests\Fixtures; + +use Symfony\Component\Serializer\Normalizer\NormalizableInterface; +use Symfony\Component\Serializer\Normalizer\DenormalizableInterface; +use Symfony\Component\Serializer\Normalizer\NormalizerInterface; +use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; + +class Dummy implements NormalizableInterface, DenormalizableInterface +{ + public $foo; + public $bar; + public $baz; + public $qux; + + public function normalize(NormalizerInterface $normalizer, $format = null) + { + return array( + 'foo' => $this->foo, + 'bar' => $this->bar, + 'baz' => $this->baz, + 'qux' => $this->qux, + ); + } + + public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null) + { + $this->foo = $data['foo']; + $this->bar = $data['bar']; + $this->baz = $data['baz']; + $this->qux = $data['qux']; + } +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Fixtures/NormalizableTraversableDummy.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Fixtures/NormalizableTraversableDummy.php new file mode 100644 index 0000000..ba1f924 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Fixtures/NormalizableTraversableDummy.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Tests\Fixtures; + +use Symfony\Component\Serializer\Normalizer\NormalizableInterface; +use Symfony\Component\Serializer\Normalizer\DenormalizableInterface; +use Symfony\Component\Serializer\Normalizer\NormalizerInterface; +use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; + +class NormalizableTraversableDummy extends TraversableDummy implements NormalizableInterface, DenormalizableInterface +{ + public function normalize(NormalizerInterface $normalizer, $format = null) + { + return array( + 'foo' => 'normalizedFoo', + 'bar' => 'normalizedBar', + ); + } + + public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null) + { + return array( + 'foo' => 'denormalizedFoo', + 'bar' => 'denormalizedBar', + ); + } +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Fixtures/ScalarDummy.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Fixtures/ScalarDummy.php new file mode 100644 index 0000000..1b0516a --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Fixtures/ScalarDummy.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Tests\Fixtures; + +use Symfony\Component\Serializer\Normalizer\NormalizableInterface; +use Symfony\Component\Serializer\Normalizer\DenormalizableInterface; +use Symfony\Component\Serializer\Normalizer\NormalizerInterface; +use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; + +class ScalarDummy implements NormalizableInterface, DenormalizableInterface +{ + public $foo; + public $xmlFoo; + + public function normalize(NormalizerInterface $normalizer, $format = null) + { + return $format === 'xml' ? $this->xmlFoo : $this->foo; + } + + public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null) + { + if ($format === 'xml') { + $this->xmlFoo = $data; + } else { + $this->foo = $data; + } + } +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Fixtures/TraversableDummy.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Fixtures/TraversableDummy.php new file mode 100644 index 0000000..bcf46e5 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Fixtures/TraversableDummy.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Tests\Fixtures; + +class TraversableDummy implements \IteratorAggregate +{ + public $foo = 'foo'; + public $bar = 'bar'; + + public function getIterator() + { + return new \ArrayIterator(get_object_vars($this)); + } +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Normalizer/CustomNormalizerTest.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Normalizer/CustomNormalizerTest.php new file mode 100644 index 0000000..7b4b4ae --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Normalizer/CustomNormalizerTest.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Tests\Normalizer; + +use Symfony\Component\Serializer\Tests\Fixtures\ScalarDummy; +use Symfony\Component\Serializer\Normalizer\CustomNormalizer; +use Symfony\Component\Serializer\Serializer; + +class CustomNormalizerTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + $this->normalizer = new CustomNormalizer; + $this->normalizer->setSerializer(new Serializer); + } + + public function testSerialize() + { + $obj = new ScalarDummy; + $obj->foo = 'foo'; + $obj->xmlFoo = 'xml'; + $this->assertEquals('foo', $this->normalizer->normalize($obj, 'json')); + $this->assertEquals('xml', $this->normalizer->normalize($obj, 'xml')); + } + + public function testDeserialize() + { + $obj = $this->normalizer->denormalize('foo', get_class(new ScalarDummy), 'xml'); + $this->assertEquals('foo', $obj->xmlFoo); + $this->assertNull($obj->foo); + + $obj = $this->normalizer->denormalize('foo', get_class(new ScalarDummy), 'json'); + $this->assertEquals('foo', $obj->foo); + $this->assertNull($obj->xmlFoo); + } + + public function testSupportsNormalization() + { + $this->assertTrue($this->normalizer->supportsNormalization(new ScalarDummy)); + $this->assertFalse($this->normalizer->supportsNormalization(new \stdClass)); + } + + public function testSupportsDenormalization() + { + $this->assertTrue($this->normalizer->supportsDenormalization(array(), 'Symfony\Component\Serializer\Tests\Fixtures\ScalarDummy')); + $this->assertFalse($this->normalizer->supportsDenormalization(array(), 'stdClass')); + $this->assertTrue($this->normalizer->supportsDenormalization(array(), 'Symfony\Component\Serializer\Tests\Fixtures\DenormalizableDummy')); + } +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php new file mode 100644 index 0000000..0637532 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php @@ -0,0 +1,220 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Tests\Normalizer; + +use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer; + +class GetSetMethodNormalizerTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + $this->normalizer = new GetSetMethodNormalizer; + $this->normalizer->setSerializer($this->getMock('Symfony\Component\Serializer\Serializer')); + } + + public function testNormalize() + { + $obj = new GetSetDummy; + $obj->setFoo('foo'); + $obj->setBar('bar'); + $this->assertEquals( + array('foo' => 'foo', 'bar' => 'bar', 'fooBar' => 'foobar'), + $this->normalizer->normalize($obj, 'any') + ); + } + + public function testDenormalize() + { + $obj = $this->normalizer->denormalize( + array('foo' => 'foo', 'bar' => 'bar', 'fooBar' => 'foobar'), + __NAMESPACE__.'\GetSetDummy', + 'any' + ); + $this->assertEquals('foo', $obj->getFoo()); + $this->assertEquals('bar', $obj->getBar()); + } + + public function testConstructorDenormalize() + { + $obj = $this->normalizer->denormalize( + array('foo' => 'foo', 'bar' => 'bar', 'fooBar' => 'foobar'), + __NAMESPACE__.'\GetConstructorDummy', 'any'); + $this->assertEquals('foo', $obj->getFoo()); + $this->assertEquals('bar', $obj->getBar()); + } + + /** + * @dataProvider provideCallbacks + */ + public function testCallbacks($callbacks, $value, $result, $message) + { + $this->normalizer->setCallbacks($callbacks); + + $obj = new GetConstructorDummy('', $value); + + $this->assertEquals( + $result, + $this->normalizer->normalize($obj, 'any'), + $message + ); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testUncallableCallbacks() + { + $this->normalizer->setCallbacks(array('bar' => null)); + + $obj = new GetConstructorDummy('baz', 'quux'); + + $this->normalizer->normalize($obj, 'any'); + } + + public function testIgnoredAttributes() + { + $this->normalizer->setIgnoredAttributes(array('foo', 'bar')); + + $obj = new GetSetDummy; + $obj->setFoo('foo'); + $obj->setBar('bar'); + + $this->assertEquals( + array('fooBar' => 'foobar'), + $this->normalizer->normalize($obj, 'any') + ); + } + + public function provideCallbacks() + { + return array( + array( + array( + 'bar' => function ($bar) { + return 'baz'; + }, + ), + 'baz', + array('foo' => '', 'bar' => 'baz'), + 'Change a string', + ), + array( + array( + 'bar' => function ($bar) { + return null; + }, + ), + 'baz', + array('foo' => '', 'bar' => null), + 'Null an item' + ), + array( + array( + 'bar' => function ($bar) { + return $bar->format('d-m-Y H:i:s'); + }, + ), + new \DateTime('2011-09-10 06:30:00'), + array('foo' => '', 'bar' => '10-09-2011 06:30:00'), + 'Format a date', + ), + array( + array( + 'bar' => function ($bars) { + $foos = ''; + foreach ($bars as $bar) { + $foos .= $bar->getFoo(); + } + + return $foos; + }, + ), + array(new GetConstructorDummy('baz', ''), new GetConstructorDummy('quux', '')), + array('foo' => '', 'bar' => 'bazquux'), + 'Collect a property', + ), + array( + array( + 'bar' => function ($bars) { + return count($bars); + }, + ), + array(new GetConstructorDummy('baz', ''), new GetConstructorDummy('quux', '')), + array('foo' => '', 'bar' => 2), + 'Count a property', + ), + ); + } +} + +class GetSetDummy +{ + protected $foo; + private $bar; + + public function getFoo() + { + return $this->foo; + } + + public function setFoo($foo) + { + $this->foo = $foo; + } + + public function getBar() + { + return $this->bar; + } + + public function setBar($bar) + { + $this->bar = $bar; + } + + public function getFooBar() + { + return $this->foo . $this->bar; + } + + public function otherMethod() + { + throw new \RuntimeException("Dummy::otherMethod() should not be called"); + } +} + +class GetConstructorDummy +{ + protected $foo; + private $bar; + + public function __construct($foo, $bar) + { + $this->foo = $foo; + $this->bar = $bar; + } + + public function getFoo() + { + return $this->foo; + } + + public function getBar() + { + return $this->bar; + } + + public function otherMethod() + { + throw new \RuntimeException("Dummy::otherMethod() should not be called"); + } +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/SerializerTest.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/SerializerTest.php new file mode 100644 index 0000000..6470393 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/SerializerTest.php @@ -0,0 +1,227 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Tests; + +use Symfony\Component\Serializer\Serializer; +use Symfony\Component\Serializer\Encoder\JsonEncoder; +use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer; +use Symfony\Component\Serializer\Normalizer\CustomNormalizer; +use Symfony\Component\Serializer\Tests\Fixtures\TraversableDummy; +use Symfony\Component\Serializer\Tests\Fixtures\NormalizableTraversableDummy; + +class SerializerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException + */ + public function testNormalizeNoMatch() + { + $this->serializer = new Serializer(array($this->getMock('Symfony\Component\Serializer\Normalizer\CustomNormalizer'))); + $this->serializer->normalize(new \stdClass, 'xml'); + } + + public function testNormalizeTraversable() + { + $this->serializer = new Serializer(array(), array('json' => new JsonEncoder())); + $result = $this->serializer->serialize(new TraversableDummy, 'json'); + $this->assertEquals('{"foo":"foo","bar":"bar"}', $result); + } + + public function testNormalizeGivesPriorityToInterfaceOverTraversable() + { + $this->serializer = new Serializer(array(new CustomNormalizer), array('json' => new JsonEncoder())); + $result = $this->serializer->serialize(new NormalizableTraversableDummy, 'json'); + $this->assertEquals('{"foo":"normalizedFoo","bar":"normalizedBar"}', $result); + } + + /** + * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException + */ + public function testDenormalizeNoMatch() + { + $this->serializer = new Serializer(array($this->getMock('Symfony\Component\Serializer\Normalizer\CustomNormalizer'))); + $this->serializer->denormalize('foo', 'stdClass'); + } + + public function testSerialize() + { + $this->serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new JsonEncoder())); + $data = array('title' => 'foo', 'numbers' => array(5, 3)); + $result = $this->serializer->serialize(Model::fromArray($data), 'json'); + $this->assertEquals(json_encode($data), $result); + } + + public function testSerializeScalar() + { + $this->serializer = new Serializer(array(), array('json' => new JsonEncoder())); + $result = $this->serializer->serialize('foo', 'json'); + $this->assertEquals('"foo"', $result); + } + + public function testSerializeArrayOfScalars() + { + $this->serializer = new Serializer(array(), array('json' => new JsonEncoder())); + $data = array('foo', array(5, 3)); + $result = $this->serializer->serialize($data, 'json'); + $this->assertEquals(json_encode($data), $result); + } + + /** + * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException + */ + public function testSerializeNoEncoder() + { + $this->serializer = new Serializer(array(), array()); + $data = array('title' => 'foo', 'numbers' => array(5, 3)); + $this->serializer->serialize($data, 'json'); + } + + /** + * @expectedException \Symfony\Component\Serializer\Exception\LogicException + */ + public function testSerializeNoNormalizer() + { + $this->serializer = new Serializer(array(), array('json' => new JsonEncoder())); + $data = array('title' => 'foo', 'numbers' => array(5, 3)); + $this->serializer->serialize(Model::fromArray($data), 'json'); + } + + public function testDeserialize() + { + $this->serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new JsonEncoder())); + $data = array('title' => 'foo', 'numbers' => array(5, 3)); + $result = $this->serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json'); + $this->assertEquals($data, $result->toArray()); + } + + public function testDeserializeUseCache() + { + $this->serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new JsonEncoder())); + $data = array('title' => 'foo', 'numbers' => array(5, 3)); + $this->serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json'); + $data = array('title' => 'bar', 'numbers' => array(2, 8)); + $result = $this->serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json'); + $this->assertEquals($data, $result->toArray()); + } + + /** + * @expectedException \Symfony\Component\Serializer\Exception\LogicException + */ + public function testDeserializeNoNormalizer() + { + $this->serializer = new Serializer(array(), array('json' => new JsonEncoder())); + $data = array('title' => 'foo', 'numbers' => array(5, 3)); + $this->serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json'); + } + + /** + * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException + */ + public function testDeserializeWrongNormalizer() + { + $this->serializer = new Serializer(array(new CustomNormalizer()), array('json' => new JsonEncoder())); + $data = array('title' => 'foo', 'numbers' => array(5, 3)); + $this->serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json'); + } + + /** + * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException + */ + public function testDeserializeNoEncoder() + { + $this->serializer = new Serializer(array(), array()); + $data = array('title' => 'foo', 'numbers' => array(5, 3)); + $this->serializer->deserialize(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json'); + } + + public function testDeserializeSupported() + { + $this->serializer = new Serializer(array(new GetSetMethodNormalizer()), array()); + $data = array('title' => 'foo', 'numbers' => array(5, 3)); + $this->assertTrue($this->serializer->supportsDenormalization(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json')); + } + + public function testDeserializeNotSupported() + { + $this->serializer = new Serializer(array(new GetSetMethodNormalizer()), array()); + $data = array('title' => 'foo', 'numbers' => array(5, 3)); + $this->assertFalse($this->serializer->supportsDenormalization(json_encode($data), 'stdClass', 'json')); + } + + public function testDeserializeNotSupportedMissing() + { + $this->serializer = new Serializer(array(), array()); + $data = array('title' => 'foo', 'numbers' => array(5, 3)); + $this->assertFalse($this->serializer->supportsDenormalization(json_encode($data), '\Symfony\Component\Serializer\Tests\Model', 'json')); + } + + public function testEncode() + { + $this->serializer = new Serializer(array(), array('json' => new JsonEncoder())); + $data = array('foo', array(5, 3)); + $result = $this->serializer->encode($data, 'json'); + $this->assertEquals(json_encode($data), $result); + } + + public function testDecode() + { + $this->serializer = new Serializer(array(), array('json' => new JsonEncoder())); + $data = array('foo', array(5, 3)); + $result = $this->serializer->decode(json_encode($data), 'json'); + $this->assertEquals($data, $result); + } +} + +class Model +{ + private $title; + private $numbers; + + public static function fromArray($array) + { + $model = new self(); + if (isset($array['title'])) { + $model->setTitle($array['title']); + } + if (isset($array['numbers'])) { + $model->setNumbers($array['numbers']); + } + + return $model; + } + + public function getTitle() + { + return $this->title; + } + + public function setTitle($title) + { + $this->title = $title; + } + + public function getNumbers() + { + return $this->numbers; + } + + public function setNumbers($numbers) + { + $this->numbers = $numbers; + } + + public function toArray() + { + return array('title' => $this->title, 'numbers' => $this->numbers); + } + +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/bootstrap.php b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/bootstrap.php new file mode 100644 index 0000000..3b0e811 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/Tests/bootstrap.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +spl_autoload_register(function ($class) { + if (0 === strpos(ltrim($class, '/'), 'Symfony\Component\Serializer')) { + if (file_exists($file = __DIR__.'/../'.substr(str_replace('\\', '/', $class), strlen('Symfony\Component\Serializer')).'.php')) { + require_once $file; + } + } +}); diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/composer.json b/core/vendor/symfony/serializer/Symfony/Component/Serializer/composer.json new file mode 100644 index 0000000..1c8feb3 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/composer.json @@ -0,0 +1,31 @@ +{ + "name": "symfony/serializer", + "type": "library", + "description": "Symfony Serializer Component", + "keywords": [], + "homepage": "http://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "require": { + "php": ">=5.3.3" + }, + "autoload": { + "psr-0": { "Symfony\\Component\\Serializer": "" } + }, + "target-dir": "Symfony/Component/Serializer", + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + } +} diff --git a/core/vendor/symfony/serializer/Symfony/Component/Serializer/phpunit.xml.dist b/core/vendor/symfony/serializer/Symfony/Component/Serializer/phpunit.xml.dist new file mode 100644 index 0000000..c85ffa7 --- /dev/null +++ b/core/vendor/symfony/serializer/Symfony/Component/Serializer/phpunit.xml.dist @@ -0,0 +1,29 @@ + + + + + + ./Tests/ + + + + + + ./ + + ./vendor + ./Tests + + + +