[Serializer] Refactoring of metadata

This commit is contained in:
Kévin Dunglas 2015-02-25 23:32:01 +01:00
parent 37e0fa18c6
commit 8534505db5
26 changed files with 666 additions and 164 deletions

View File

@ -0,0 +1,94 @@
<?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\Mapping;
/**
* {@inheritdoc}
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class AttributeMetadata implements AttributeMetadataInterface
{
/**
* @var string
*
* @internal This property is public in order to reduce the size of the
* class' serialized representation. Do not access it. Use
* {@link getName()} instead.
*/
public $name;
/**
* @var array
*
* @internal This property is public in order to reduce the size of the
* class' serialized representation. Do not access it. Use
* {@link getGroups()} instead.
*/
public $groups = array();
/**
* Constructs a metadata for the given attribute.
*
* @param string $name
*/
public function __construct($name)
{
$this->name = $name;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->name;
}
/**
* {@inheritdoc}
*/
public function addGroup($group)
{
if (!in_array($group, $this->groups)) {
$this->groups[] = $group;
}
}
/**
* {@inheritdoc}
*/
public function getGroups()
{
return $this->groups;
}
/**
* {@inheritdoc}
*/
public function merge(AttributeMetadataInterface $attributeMetadata)
{
foreach ($attributeMetadata->getGroups() as $group) {
$this->addGroup($group);
}
}
/**
* Returns the names of the properties that should be serialized.
*
* @return string[]
*/
public function __sleep()
{
return array('name', 'groups');
}
}

View File

@ -0,0 +1,50 @@
<?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\Mapping;
/**
* Stores metadata needed for serializing and deserializing attributes.
*
* Primarily, the metadata stores serialization groups.
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
interface AttributeMetadataInterface
{
/**
* Gets the attribute name.
*
* @return string
*/
public function getName();
/**
* Adds this attribute to the given group.
*
* @param string $group
*/
public function addGroup($group);
/**
* Gets groups of this attribute.
*
* @return string[]
*/
public function getGroups();
/**
* Merges an {@see AttributeMetadataInterface} with in the current one.
*
* @param AttributeMetadataInterface $attributeMetadata
*/
public function merge(AttributeMetadataInterface $attributeMetadata);
}

View File

@ -12,31 +12,29 @@
namespace Symfony\Component\Serializer\Mapping; namespace Symfony\Component\Serializer\Mapping;
/** /**
* Stores all metadata needed for serializing objects of specific class. * {@inheritdoc}
*
* Primarily, the metadata stores serialization groups.
* *
* @author Kévin Dunglas <dunglas@gmail.com> * @author Kévin Dunglas <dunglas@gmail.com>
*/ */
class ClassMetadata class ClassMetadata implements ClassMetadataInterface
{ {
/** /**
* @var string * @var string
* *
* @internal This property is public in order to reduce the size of the * @internal This property is public in order to reduce the size of the
* class' serialized representation. Do not access it. Use * class' serialized representation. Do not access it. Use
* {@link getClassName()} instead. * {@link getName()} instead.
*/ */
public $name; public $name;
/** /**
* @var array * @var AttributeMetadataInterface[]
* *
* @internal This property is public in order to reduce the size of the * @internal This property is public in order to reduce the size of the
* class' serialized representation. Do not access it. Use * class' serialized representation. Do not access it. Use
* {@link getGroups()} instead. * {@link getAttributesMetadata()} instead.
*/ */
public $attributesGroups = array(); public $attributesMetadata = array();
/** /**
* @var \ReflectionClass * @var \ReflectionClass
@ -54,66 +52,50 @@ class ClassMetadata
} }
/** /**
* Returns the name of the backing PHP class. * {@inheritdoc}
*
* @return string The name of the backing class.
*/ */
public function getClassName() public function getName()
{ {
return $this->name; return $this->name;
} }
/** /**
* Gets serialization groups. * {@inheritdoc}
*
* @return array
*/ */
public function getAttributesGroups() public function addAttributeMetadata(AttributeMetadataInterface $attributeMetadata)
{ {
return $this->attributesGroups; $this->attributesMetadata[$attributeMetadata->getName()] = $attributeMetadata;
} }
/** /**
* Adds an attribute to a serialization group * {@inheritdoc}
*
* @param string $attribute
* @param string $group
* @throws \InvalidArgumentException
*/ */
public function addAttributeGroup($attribute, $group) public function getAttributesMetadata()
{ {
if (!is_string($attribute) || !is_string($group)) { return $this->attributesMetadata;
throw new \InvalidArgumentException('Arguments must be strings.');
}
if (!isset($this->groups[$group]) || !in_array($attribute, $this->attributesGroups[$group])) {
$this->attributesGroups[$group][] = $attribute;
}
} }
/** /**
* Merges attributes' groups. * {@inheritdoc}
*
* @param ClassMetadata $classMetadata
*/ */
public function mergeAttributesGroups(ClassMetadata $classMetadata) public function merge(ClassMetadataInterface $classMetadata)
{ {
foreach ($classMetadata->getAttributesGroups() as $group => $attributes) { foreach ($classMetadata->getAttributesMetadata() as $attributeMetadata) {
foreach ($attributes as $attribute) { if (isset($this->attributesMetadata[$attributeMetadata->getName()])) {
$this->addAttributeGroup($attribute, $group); $this->attributesMetadata[$attributeMetadata->getName()]->merge($attributeMetadata);
} else {
$this->addAttributeMetadata($attributeMetadata);
} }
} }
} }
/** /**
* Returns a ReflectionClass instance for this class. * {@inheritdoc}
*
* @return \ReflectionClass
*/ */
public function getReflectionClass() public function getReflectionClass()
{ {
if (!$this->reflClass) { if (!$this->reflClass) {
$this->reflClass = new \ReflectionClass($this->getClassName()); $this->reflClass = new \ReflectionClass($this->getName());
} }
return $this->reflClass; return $this->reflClass;
@ -128,7 +110,7 @@ class ClassMetadata
{ {
return array( return array(
'name', 'name',
'attributesGroups', 'attributes',
); );
} }
} }

View File

@ -0,0 +1,57 @@
<?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\Mapping;
/**
* Stores metadata needed for serializing and deserializing objects of specific class.
*
* Primarily, the metadata stores the list of attributes to serialize or deserialize.
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
interface ClassMetadataInterface
{
/**
* Returns the name of the backing PHP class.
*
* @return string The name of the backing class.
*/
public function getName();
/**
* Adds an {@link AttributeMetadataInterface}.
*
* @param AttributeMetadataInterface $attributeMetadata
*/
public function addAttributeMetadata(AttributeMetadataInterface $attributeMetadata);
/**
* Gets the list of {@link AttributeMetadataInterface}.
*
* @return AttributeMetadataInterface[]
*/
public function getAttributesMetadata();
/**
* Merges a {@link ClassMetadataInterface} in the current one.
*
* @param ClassMetadataInterface $classMetadata
*/
public function merge(ClassMetadataInterface $classMetadata);
/**
* Returns a {@link \ReflectionClass} instance for this class.
*
* @return \ReflectionClass
*/
public function getReflectionClass();
}

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Serializer\Mapping\Factory; namespace Symfony\Component\Serializer\Mapping\Factory;
use Doctrine\Common\Cache\Cache; use Doctrine\Common\Cache\Cache;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
use Symfony\Component\Serializer\Mapping\ClassMetadata; use Symfony\Component\Serializer\Mapping\ClassMetadata;
use Symfony\Component\Serializer\Mapping\Loader\LoaderInterface; use Symfony\Component\Serializer\Mapping\Loader\LoaderInterface;
@ -20,7 +21,7 @@ use Symfony\Component\Serializer\Mapping\Loader\LoaderInterface;
* *
* @author Kévin Dunglas <dunglas@gmail.com> * @author Kévin Dunglas <dunglas@gmail.com>
*/ */
class ClassMetadataFactory class ClassMetadataFactory implements ClassMetadataFactoryInterface
{ {
/** /**
* @var LoaderInterface * @var LoaderInterface
@ -46,29 +47,13 @@ class ClassMetadataFactory
} }
/** /**
* If the method was called with the same class name (or an object of that * {@inheritdoc}
* class) before, the same metadata instance is returned.
*
* If the factory was configured with a cache, this method will first look
* for an existing metadata instance in the cache. If an existing instance
* is found, it will be returned without further ado.
*
* Otherwise, a new metadata instance is created. If the factory was
* configured with a loader, the metadata is passed to the
* {@link LoaderInterface::loadClassMetadata()} method for further
* configuration. At last, the new object is returned.
*
* @param string|object $value
*
* @return ClassMetadata
*
* @throws \InvalidArgumentException
*/ */
public function getMetadataFor($value) public function getMetadataFor($value)
{ {
$class = $this->getClass($value); $class = $this->getClass($value);
if (!$class) { if (!$class) {
throw new \InvalidArgumentException(sprintf('Cannot create metadata for non-objects. Got: %s', gettype($value))); throw new InvalidArgumentException(sprintf('Cannot create metadata for non-objects. Got: "%s"', gettype($value)));
} }
if (isset($this->loadedClasses[$class])) { if (isset($this->loadedClasses[$class])) {
@ -80,40 +65,33 @@ class ClassMetadataFactory
} }
if (!class_exists($class) && !interface_exists($class)) { if (!class_exists($class) && !interface_exists($class)) {
throw new \InvalidArgumentException(sprintf('The class or interface "%s" does not exist.', $class)); throw new InvalidArgumentException(sprintf('The class or interface "%s" does not exist.', $class));
} }
$metadata = new ClassMetadata($class); $classMetadata = new ClassMetadata($class);
$this->loader->loadClassMetadata($classMetadata);
$reflClass = $metadata->getReflectionClass(); $reflectionClass = $classMetadata->getReflectionClass();
// Include groups from the parent class // Include metadata from the parent class
if ($parent = $reflClass->getParentClass()) { if ($parent = $reflectionClass->getParentClass()) {
$metadata->mergeAttributesGroups($this->getMetadataFor($parent->name)); $classMetadata->merge($this->getMetadataFor($parent->name));
} }
// Include groups from all implemented interfaces // Include metadata from all implemented interfaces
foreach ($reflClass->getInterfaces() as $interface) { foreach ($reflectionClass->getInterfaces() as $interface) {
$metadata->mergeAttributesGroups($this->getMetadataFor($interface->name)); $classMetadata->merge($this->getMetadataFor($interface->name));
}
if ($this->loader) {
$this->loader->loadClassMetadata($metadata);
} }
if ($this->cache) { if ($this->cache) {
$this->cache->save($class, $metadata); $this->cache->save($class, $classMetadata);
} }
return $this->loadedClasses[$class] = $metadata; return $this->loadedClasses[$class] = $classMetadata;
} }
/** /**
* Checks if class has metadata. * {@inheritdoc}
*
* @param mixed $value
*
* @return bool
*/ */
public function hasMetadataFor($value) public function hasMetadataFor($value)
{ {

View File

@ -0,0 +1,53 @@
<?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\Mapping\Factory;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
use Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
/**
* Returns a {@see ClassMetadataInterface}.
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
interface ClassMetadataFactoryInterface
{
/**
* If the method was called with the same class name (or an object of that
* class) before, the same metadata instance is returned.
*
* If the factory was configured with a cache, this method will first look
* for an existing metadata instance in the cache. If an existing instance
* is found, it will be returned without further ado.
*
* Otherwise, a new metadata instance is created. If the factory was
* configured with a loader, the metadata is passed to the
* {@link LoaderInterface::loadClassMetadata()} method for further
* configuration. At last, the new object is returned.
*
* @param string|object $value
*
* @return ClassMetadataInterface
*
* @throws InvalidArgumentException
*/
public function getMetadataFor($value);
/**
* Checks if class has metadata.
*
* @param mixed $value
*
* @return bool
*/
public function hasMetadataFor($value);
}

View File

@ -14,7 +14,8 @@ namespace Symfony\Component\Serializer\Mapping\Loader;
use Doctrine\Common\Annotations\Reader; use Doctrine\Common\Annotations\Reader;
use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Exception\MappingException; use Symfony\Component\Serializer\Exception\MappingException;
use Symfony\Component\Serializer\Mapping\ClassMetadata; use Symfony\Component\Serializer\Mapping\AttributeMetadata;
use Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
/** /**
* Annotation loader. * Annotation loader.
@ -39,18 +40,25 @@ class AnnotationLoader implements LoaderInterface
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function loadClassMetadata(ClassMetadata $metadata) public function loadClassMetadata(ClassMetadataInterface $classMetadata)
{ {
$reflClass = $metadata->getReflectionClass(); $reflectionClass = $classMetadata->getReflectionClass();
$className = $reflClass->name; $className = $reflectionClass->name;
$loaded = false; $loaded = false;
foreach ($reflClass->getProperties() as $property) { $attributesMetadata = $classMetadata->getAttributesMetadata();
if ($property->getDeclaringClass()->name === $className) {
foreach ($reflectionClass->getProperties() as $property) {
if (!isset($attributeMetadata[$property->name])) {
$attributesMetadata[$property->name] = new AttributeMetadata($property->name);
$classMetadata->addAttributeMetadata($attributesMetadata[$property->name]);
}
if ($property->getDeclaringClass()->name == $className) {
foreach ($this->reader->getPropertyAnnotations($property) as $groups) { foreach ($this->reader->getPropertyAnnotations($property) as $groups) {
if ($groups instanceof Groups) { if ($groups instanceof Groups) {
foreach ($groups->getGroups() as $group) { foreach ($groups->getGroups() as $group) {
$metadata->addAttributeGroup($property->name, $group); $attributesMetadata[$property->name]->addGroup($group);
} }
} }
@ -59,13 +67,22 @@ class AnnotationLoader implements LoaderInterface
} }
} }
foreach ($reflClass->getMethods() as $method) { foreach ($reflectionClass->getMethods() as $method) {
if ($method->getDeclaringClass()->name === $className) { if ($method->getDeclaringClass()->name == $className) {
foreach ($this->reader->getMethodAnnotations($method) as $groups) { foreach ($this->reader->getMethodAnnotations($method) as $groups) {
if ($groups instanceof Groups) { if ($groups instanceof Groups) {
if (preg_match('/^(get|is)(.+)$/i', $method->name, $matches)) { if (preg_match('/^(get|is)(.+)$/i', $method->name, $matches)) {
$attributeName = lcfirst($matches[2]);
if (isset($attributesMetadata[$attributeName])) {
$attributeMetadata = $attributesMetadata[$attributeName];
} else {
$attributesMetadata[$attributeName] = $attributeMetadata = new AttributeMetadata($attributeName);
$classMetadata->addAttributeMetadata($attributeMetadata);
}
foreach ($groups->getGroups() as $group) { foreach ($groups->getGroups() as $group) {
$metadata->addAttributeGroup(lcfirst($matches[2]), $group); $attributeMetadata->addGroup($group);
} }
} else { } else {
throw new MappingException(sprintf('Groups on "%s::%s" cannot be added. Groups can only be added on methods beginning with "get" or "is".', $className, $method->name)); throw new MappingException(sprintf('Groups on "%s::%s" cannot be added. Groups can only be added on methods beginning with "get" or "is".', $className, $method->name));

View File

@ -13,8 +13,16 @@ namespace Symfony\Component\Serializer\Mapping\Loader;
use Symfony\Component\Serializer\Exception\MappingException; use Symfony\Component\Serializer\Exception\MappingException;
/**
* Base class for all file based loaders.
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
abstract class FileLoader implements LoaderInterface abstract class FileLoader implements LoaderInterface
{ {
/**
* @var string
*/
protected $file; protected $file;
/** /**
@ -22,8 +30,7 @@ abstract class FileLoader implements LoaderInterface
* *
* @param string $file The mapping file to load * @param string $file The mapping file to load
* *
* @throws MappingException if the mapping file does not exist * @throws MappingException if the mapping file does not exist or is not readable
* @throws MappingException if the mapping file is not readable
*/ */
public function __construct($file) public function __construct($file)
{ {

View File

@ -12,24 +12,28 @@
namespace Symfony\Component\Serializer\Mapping\Loader; namespace Symfony\Component\Serializer\Mapping\Loader;
use Symfony\Component\Serializer\Exception\MappingException; use Symfony\Component\Serializer\Exception\MappingException;
use Symfony\Component\Serializer\Mapping\ClassMetadata; use Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
/** /**
* Calls multiple LoaderInterface instances in a chain * Calls multiple {@link LoaderInterface} instances in a chain.
* *
* This class accepts multiple instances of LoaderInterface to be passed to the * This class accepts multiple instances of LoaderInterface to be passed to the
* constructor. When loadClassMetadata() is called, the same method is called * constructor. When {@link loadClassMetadata()} is called, the same method is called
* in <em>all</em> of these loaders, regardless of whether any of them was * in <em>all</em> of these loaders, regardless of whether any of them was
* successful or not. * successful or not.
* *
* @author Bernhard Schussek <bschussek@gmail.com> * @author Bernhard Schussek <bschussek@gmail.com>
* @author Kévin Dunglas <dunglas@gmail.com>
*/ */
class LoaderChain implements LoaderInterface class LoaderChain implements LoaderInterface
{ {
protected $loaders; /**
* @var LoaderInterface[]
*/
private $loaders;
/** /**
* Accepts a list of LoaderInterface instances * Accepts a list of LoaderInterface instances.
* *
* @param LoaderInterface[] $loaders An array of LoaderInterface instances * @param LoaderInterface[] $loaders An array of LoaderInterface instances
* *
@ -49,7 +53,7 @@ class LoaderChain implements LoaderInterface
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function loadClassMetadata(ClassMetadata $metadata) public function loadClassMetadata(ClassMetadataInterface $metadata)
{ {
$success = false; $success = false;

View File

@ -11,10 +11,10 @@
namespace Symfony\Component\Serializer\Mapping\Loader; namespace Symfony\Component\Serializer\Mapping\Loader;
use Symfony\Component\Serializer\Mapping\ClassMetadata; use Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
/** /**
* Loads class metadata. * Loads {@link ClassMetadataInterface}.
* *
* @author Kévin Dunglas <dunglas@gmail.com> * @author Kévin Dunglas <dunglas@gmail.com>
*/ */
@ -23,9 +23,9 @@ interface LoaderInterface
/** /**
* Load class metadata. * Load class metadata.
* *
* @param ClassMetadata $metadata A metadata * @param ClassMetadataInterface $classMetadata A metadata
* *
* @return bool * @return bool
*/ */
public function loadClassMetadata(ClassMetadata $metadata); public function loadClassMetadata(ClassMetadataInterface $classMetadata);
} }

View File

@ -13,7 +13,8 @@ namespace Symfony\Component\Serializer\Mapping\Loader;
use Symfony\Component\Config\Util\XmlUtils; use Symfony\Component\Config\Util\XmlUtils;
use Symfony\Component\Serializer\Exception\MappingException; use Symfony\Component\Serializer\Exception\MappingException;
use Symfony\Component\Serializer\Mapping\ClassMetadata; use Symfony\Component\Serializer\Mapping\AttributeMetadata;
use Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
/** /**
* Loads XML mapping files. * Loads XML mapping files.
@ -23,7 +24,7 @@ use Symfony\Component\Serializer\Mapping\ClassMetadata;
class XmlFileLoader extends FileLoader class XmlFileLoader extends FileLoader
{ {
/** /**
* An array of SimpleXMLElement instances. * An array of {@class \SimpleXMLElement} instances.
* *
* @var \SimpleXMLElement[]|null * @var \SimpleXMLElement[]|null
*/ */
@ -32,7 +33,7 @@ class XmlFileLoader extends FileLoader
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function loadClassMetadata(ClassMetadata $metadata) public function loadClassMetadata(ClassMetadataInterface $classMetadata)
{ {
if (null === $this->classes) { if (null === $this->classes) {
$this->classes = array(); $this->classes = array();
@ -43,12 +44,23 @@ class XmlFileLoader extends FileLoader
} }
} }
if (isset($this->classes[$metadata->getClassName()])) { $attributesMetadata = $classMetadata->getAttributesMetadata();
$xml = $this->classes[$metadata->getClassName()];
if (isset($this->classes[$classMetadata->getName()])) {
$xml = $this->classes[$classMetadata->getName()];
foreach ($xml->attribute as $attribute) { foreach ($xml->attribute as $attribute) {
$attributeName = (string) $attribute['name'];
if (isset($attributesMetadata[$attributeName])) {
$attributeMetadata = $attributesMetadata[$attributeName];
} else {
$attributeMetadata = new AttributeMetadata($attributeName);
$classMetadata->addAttributeMetadata($attributeMetadata);
}
foreach ($attribute->group as $group) { foreach ($attribute->group as $group) {
$metadata->addAttributeGroup((string) $attribute['name'], (string) $group); $attributeMetadata->addGroup((string) $group);
} }
} }
@ -59,7 +71,7 @@ class XmlFileLoader extends FileLoader
} }
/** /**
* Parse a XML File. * Parses a XML File.
* *
* @param string $file Path of file * @param string $file Path of file
* *

View File

@ -12,11 +12,12 @@
namespace Symfony\Component\Serializer\Mapping\Loader; namespace Symfony\Component\Serializer\Mapping\Loader;
use Symfony\Component\Serializer\Exception\MappingException; use Symfony\Component\Serializer\Exception\MappingException;
use Symfony\Component\Serializer\Mapping\ClassMetadata; use Symfony\Component\Serializer\Mapping\AttributeMetadata;
use Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
use Symfony\Component\Yaml\Parser; use Symfony\Component\Yaml\Parser;
/** /**
* YAML File Loader * YAML File Loader.
* *
* @author Kévin Dunglas <dunglas@gmail.com> * @author Kévin Dunglas <dunglas@gmail.com>
*/ */
@ -34,7 +35,7 @@ class YamlFileLoader extends FileLoader
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function loadClassMetadata(ClassMetadata $metadata) public function loadClassMetadata(ClassMetadataInterface $classMetadata)
{ {
if (null === $this->classes) { if (null === $this->classes) {
if (!stream_is_local($this->file)) { if (!stream_is_local($this->file)) {
@ -59,14 +60,22 @@ class YamlFileLoader extends FileLoader
$this->classes = $classes; $this->classes = $classes;
} }
if (isset($this->classes[$metadata->getClassName()])) { if (isset($this->classes[$classMetadata->getName()])) {
$yaml = $this->classes[$metadata->getClassName()]; $yaml = $this->classes[$classMetadata->getName()];
if (isset($yaml['attributes']) && is_array($yaml['attributes'])) { if (isset($yaml['attributes']) && is_array($yaml['attributes'])) {
$attributesMetadata = $classMetadata->getAttributesMetadata();
foreach ($yaml['attributes'] as $attribute => $data) { foreach ($yaml['attributes'] as $attribute => $data) {
if (isset($attributesMetadata[$attribute])) {
$attributeMetadata = $attributesMetadata[$attribute];
} else {
$attributeMetadata = new AttributeMetadata($attribute);
$classMetadata->addAttributeMetadata($attributeMetadata);
}
if (isset($data['groups'])) { if (isset($data['groups'])) {
foreach ($data['groups'] as $group) { foreach ($data['groups'] as $group) {
$metadata->addAttributeGroup($attribute, $group); $attributeMetadata->addGroup($group);
} }
} }
} }

View File

@ -15,7 +15,8 @@ use Symfony\Component\Serializer\Exception\CircularReferenceException;
use Symfony\Component\Serializer\Exception\InvalidArgumentException; use Symfony\Component\Serializer\Exception\InvalidArgumentException;
use Symfony\Component\Serializer\Exception\LogicException; use Symfony\Component\Serializer\Exception\LogicException;
use Symfony\Component\Serializer\Exception\RuntimeException; use Symfony\Component\Serializer\Exception\RuntimeException;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
use Symfony\Component\Serializer\Mapping\AttributeMetadataInterface;
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface; use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
@ -26,21 +27,42 @@ use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
*/ */
abstract class AbstractNormalizer extends SerializerAwareNormalizer implements NormalizerInterface, DenormalizerInterface abstract class AbstractNormalizer extends SerializerAwareNormalizer implements NormalizerInterface, DenormalizerInterface
{ {
/**
* @var int
*/
protected $circularReferenceLimit = 1; protected $circularReferenceLimit = 1;
/**
* @var callable
*/
protected $circularReferenceHandler; protected $circularReferenceHandler;
/**
* @var ClassMetadataFactoryInterface|null
*/
protected $classMetadataFactory; protected $classMetadataFactory;
/**
* @var NameConverterInterface|null
*/
protected $nameConverter; protected $nameConverter;
/**
* @var array
*/
protected $callbacks = array(); protected $callbacks = array();
/**
* @var array
*/
protected $ignoredAttributes = array(); protected $ignoredAttributes = array();
/**
* @var array
*/
protected $camelizedAttributes = array(); protected $camelizedAttributes = array();
/** /**
* Sets the {@link ClassMetadataFactory} to use. * Sets the {@link ClassMetadataFactoryInterface} to use.
* *
* @param ClassMetadataFactory|null $classMetadataFactory * @param ClassMetadataFactoryInterface|null $classMetadataFactory
* @param NameConverterInterface|null $nameConverter * @param NameConverterInterface|null $nameConverter
*/ */
public function __construct(ClassMetadataFactory $classMetadataFactory = null, NameConverterInterface $nameConverter = null) public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null)
{ {
$this->classMetadataFactory = $classMetadataFactory; $this->classMetadataFactory = $classMetadataFactory;
$this->nameConverter = $nameConverter; $this->nameConverter = $nameConverter;
@ -219,19 +241,21 @@ abstract class AbstractNormalizer extends SerializerAwareNormalizer implements N
* Gets attributes to normalize using groups. * Gets attributes to normalize using groups.
* *
* @param string|object $classOrObject * @param string|object $classOrObject
* @param array $context * @param array $context
* @return array|bool * @param bool $attributesAsString If false, return an array of {@link AttributeMetadataInterface}
*
* @return string[]|AttributeMetadataInterface[]|bool
*/ */
protected function getAllowedAttributes($classOrObject, array $context) protected function getAllowedAttributes($classOrObject, array $context, $attributesAsString = false)
{ {
if (!$this->classMetadataFactory || !isset($context['groups']) || !is_array($context['groups'])) { if (!$this->classMetadataFactory || !isset($context['groups']) || !is_array($context['groups'])) {
return false; return false;
} }
$allowedAttributes = array(); $allowedAttributes = array();
foreach ($this->classMetadataFactory->getMetadataFor($classOrObject)->getAttributesGroups() as $group => $attributes) { foreach ($this->classMetadataFactory->getMetadataFor($classOrObject)->getAttributesMetadata() as $attributeMetadata) {
if (in_array($group, $context['groups'])) { if (count(array_intersect($attributeMetadata->getGroups(), $context['groups']))) {
$allowedAttributes = array_merge($allowedAttributes, $attributes); $allowedAttributes[] = $attributesAsString ? $attributeMetadata->getName() : $attributeMetadata;
} }
} }

View File

@ -52,7 +52,7 @@ class GetSetMethodNormalizer extends AbstractNormalizer
$reflectionObject = new \ReflectionObject($object); $reflectionObject = new \ReflectionObject($object);
$reflectionMethods = $reflectionObject->getMethods(\ReflectionMethod::IS_PUBLIC); $reflectionMethods = $reflectionObject->getMethods(\ReflectionMethod::IS_PUBLIC);
$allowedAttributes = $this->getAllowedAttributes($object, $context); $allowedAttributes = $this->getAllowedAttributes($object, $context, true);
$attributes = array(); $attributes = array();
foreach ($reflectionMethods as $method) { foreach ($reflectionMethods as $method) {
@ -97,7 +97,7 @@ class GetSetMethodNormalizer extends AbstractNormalizer
*/ */
public function denormalize($data, $class, $format = null, array $context = array()) public function denormalize($data, $class, $format = null, array $context = array())
{ {
$allowedAttributes = $this->getAllowedAttributes($class, $context); $allowedAttributes = $this->getAllowedAttributes($class, $context, true);
$normalizedData = $this->prepareForDenormalization($data); $normalizedData = $this->prepareForDenormalization($data);
$reflectionClass = new \ReflectionClass($class); $reflectionClass = new \ReflectionClass($class);

View File

@ -46,7 +46,7 @@ class PropertyNormalizer extends AbstractNormalizer
$reflectionObject = new \ReflectionObject($object); $reflectionObject = new \ReflectionObject($object);
$attributes = array(); $attributes = array();
$allowedAttributes = $this->getAllowedAttributes($object, $context); $allowedAttributes = $this->getAllowedAttributes($object, $context, true);
foreach ($reflectionObject->getProperties() as $property) { foreach ($reflectionObject->getProperties() as $property) {
if (in_array($property->name, $this->ignoredAttributes)) { if (in_array($property->name, $this->ignoredAttributes)) {
@ -89,7 +89,7 @@ class PropertyNormalizer extends AbstractNormalizer
*/ */
public function denormalize($data, $class, $format = null, array $context = array()) public function denormalize($data, $class, $format = null, array $context = array())
{ {
$allowedAttributes = $this->getAllowedAttributes($class, $context); $allowedAttributes = $this->getAllowedAttributes($class, $context, true);
$data = $this->prepareForDenormalization($data); $data = $this->prepareForDenormalization($data);
$reflectionClass = new \ReflectionClass($class); $reflectionClass = new \ReflectionClass($class);

View File

@ -0,0 +1,57 @@
<?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\Tests\Mapping;
use Symfony\Component\Serializer\Mapping\AttributeMetadata;
/**
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class AttributeMetadataTest extends \PHPUnit_Framework_TestCase
{
public function testInterface()
{
$attributeMetadata = new AttributeMetadata('name');
$this->assertInstanceOf('Symfony\Component\Serializer\Mapping\AttributeMetadataInterface', $attributeMetadata);
}
public function testGetName()
{
$attributeMetadata = new AttributeMetadata('name');
$this->assertEquals('name', $attributeMetadata->getName());
}
public function testGroups()
{
$attributeMetadata = new AttributeMetadata('group');
$attributeMetadata->addGroup('a');
$attributeMetadata->addGroup('a');
$attributeMetadata->addGroup('b');
$this->assertEquals(array('a', 'b'), $attributeMetadata->getGroups());
}
public function testMerge()
{
$attributeMetadata1 = new AttributeMetadata('a1');
$attributeMetadata1->addGroup('a');
$attributeMetadata1->addGroup('b');
$attributeMetadata2 = new AttributeMetadata('a2');
$attributeMetadata2->addGroup('a');
$attributeMetadata2->addGroup('c');
$attributeMetadata1->merge($attributeMetadata2);
$this->assertEquals(array('a', 'b', 'c'), $attributeMetadata1->getGroups());
}
}

View File

@ -0,0 +1,65 @@
<?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\Tests\Mapping;
use Symfony\Component\Serializer\Mapping\ClassMetadata;
/**
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class ClassMetadataTest extends \PHPUnit_Framework_TestCase
{
public function testInterface()
{
$classMetadata = new ClassMetadata('name');
$this->assertInstanceOf('Symfony\Component\Serializer\Mapping\ClassMetadataInterface', $classMetadata);
}
public function testAttributeMetadata()
{
$classMetadata = new ClassMetadata('c');
$a1 = $this->getMock('Symfony\Component\Serializer\Mapping\AttributeMetadataInterface');
$a1->method('getName')->willReturn('a1');
$a2 = $this->getMock('Symfony\Component\Serializer\Mapping\AttributeMetadataInterface');
$a2->method('getName')->willReturn('a2');
$classMetadata->addAttributeMetadata($a1);
$classMetadata->addAttributeMetadata($a2);
$this->assertEquals(array('a1' => $a1, 'a2' => $a2), $classMetadata->getAttributesMetadata());
}
public function testMerge()
{
$classMetadata1 = new ClassMetadata('c1');
$classMetadata2 = new ClassMetadata('c2');
$ac1 = $this->getMock('Symfony\Component\Serializer\Mapping\AttributeMetadataInterface');
$ac1->method('getName')->willReturn('a1');
$ac1->method('getGroups')->willReturn(array('a', 'b'));
$ac2 = $this->getMock('Symfony\Component\Serializer\Mapping\AttributeMetadataInterface');
$ac2->method('getName')->willReturn('a1');
$ac2->method('getGroups')->willReturn(array('b', 'c'));
$classMetadata1->addAttributeMetadata($ac1);
$classMetadata2->addAttributeMetadata($ac2);
$classMetadata1->merge($classMetadata2);
$ac1->method('getGroups')->willReturn('a', 'b', 'c');
$this->assertEquals(array('a1' => $ac1), $classMetadata2->getAttributesMetadata());
}
}

View File

@ -14,21 +14,26 @@ namespace Symfony\Component\Serializer\Tests\Mapping\Factory;
use Doctrine\Common\Annotations\AnnotationReader; use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Serializer\Mapping\Loader\LoaderChain;
use Symfony\Component\Serializer\Tests\Mapping\TestClassMetadataFactory; use Symfony\Component\Serializer\Tests\Mapping\TestClassMetadataFactory;
require_once __DIR__.'/../../../Annotation/Groups.php';
/** /**
* @author Kévin Dunglas <dunglas@gmail.com> * @author Kévin Dunglas <dunglas@gmail.com>
*/ */
class ClassMetadataFactoryTest extends \PHPUnit_Framework_TestCase class ClassMetadataFactoryTest extends \PHPUnit_Framework_TestCase
{ {
public function testInterface()
{
$classMetadata = new ClassMetadataFactory(new LoaderChain(array()));
$this->assertInstanceOf('Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory', $classMetadata);
}
public function testGetMetadataFor() public function testGetMetadataFor()
{ {
$factory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())); $factory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$metadata = $factory->getMetadataFor('Symfony\Component\Serializer\Tests\Fixtures\GroupDummy'); $classMetadata = $factory->getMetadataFor('Symfony\Component\Serializer\Tests\Fixtures\GroupDummy');
$this->assertEquals(TestClassMetadataFactory::createClassMetadata(true, true), $metadata); $this->assertEquals(TestClassMetadataFactory::createClassMetadata(true, true), $classMetadata);
} }
public function testHasMetadataFor() public function testHasMetadataFor()

View File

@ -16,42 +16,51 @@ use Symfony\Component\Serializer\Mapping\ClassMetadata;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Serializer\Tests\Mapping\TestClassMetadataFactory; use Symfony\Component\Serializer\Tests\Mapping\TestClassMetadataFactory;
require_once __DIR__.'/../../../Annotation/Groups.php';
/** /**
* @author Kévin Dunglas <dunglas@gmail.com> * @author Kévin Dunglas <dunglas@gmail.com>
*/ */
class AnnotationLoaderTest extends \PHPUnit_Framework_TestCase class AnnotationLoaderTest extends \PHPUnit_Framework_TestCase
{ {
/**
* @var AnnotationLoader
*/
private $loader;
protected function setUp()
{
$this->loader = new AnnotationLoader(new AnnotationReader());
}
public function testInterface()
{
$this->assertInstanceOf('Symfony\Component\Serializer\Mapping\Loader\LoaderInterface', $this->loader);
}
public function testLoadClassMetadataReturnsTrueIfSuccessful() public function testLoadClassMetadataReturnsTrueIfSuccessful()
{ {
$loader = new AnnotationLoader(new AnnotationReader()); $classMetadata = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\GroupDummy');
$metadata = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\GroupDummy');
$this->assertTrue($loader->loadClassMetadata($metadata)); $this->assertTrue($this->loader->loadClassMetadata($classMetadata));
} }
public function testLoadClassMetadata() public function testLoadClassMetadata()
{ {
$loader = new AnnotationLoader(new AnnotationReader()); $classMetadata = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\GroupDummy');
$metadata = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\GroupDummy'); $this->loader->loadClassMetadata($classMetadata);
$loader->loadClassMetadata($metadata); $this->assertEquals(TestClassMetadataFactory::createClassMetadata(), $classMetadata);
$this->assertEquals(TestClassMetadataFactory::createClassMetadata(), $metadata);
} }
public function testLoadClassMetadataAndMerge() public function testLoadClassMetadataAndMerge()
{ {
$loader = new AnnotationLoader(new AnnotationReader()); $classMetadata = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\GroupDummy');
$metadata = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\GroupDummy'); $parentClassMetadata = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\GroupDummyParent');
$parentMetadata = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\GroupDummyParent');
$loader->loadClassMetadata($parentMetadata); $this->loader->loadClassMetadata($parentClassMetadata);
$metadata->mergeAttributesGroups($parentMetadata); $classMetadata->merge($parentClassMetadata);
$loader->loadClassMetadata($metadata); $this->loader->loadClassMetadata($classMetadata);
$this->assertEquals(TestClassMetadataFactory::createClassMetadata(true), $metadata); $this->assertEquals(TestClassMetadataFactory::createClassMetadata(true), $classMetadata);
} }
} }

View File

@ -20,7 +20,13 @@ use Symfony\Component\Serializer\Tests\Mapping\TestClassMetadataFactory;
*/ */
class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase
{ {
/**
* @var XmlFileLoader
*/
private $loader; private $loader;
/**
* @var ClassMetadata
*/
private $metadata; private $metadata;
public function setUp() public function setUp()
@ -29,6 +35,11 @@ class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase
$this->metadata = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\GroupDummy'); $this->metadata = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\GroupDummy');
} }
public function testInterface()
{
$this->assertInstanceOf('Symfony\Component\Serializer\Mapping\Loader\LoaderInterface', $this->loader);
}
public function testLoadClassMetadataReturnsTrueIfSuccessful() public function testLoadClassMetadataReturnsTrueIfSuccessful()
{ {
$this->assertTrue($this->loader->loadClassMetadata($this->metadata)); $this->assertTrue($this->loader->loadClassMetadata($this->metadata));

View File

@ -20,7 +20,13 @@ use Symfony\Component\Serializer\Tests\Mapping\TestClassMetadataFactory;
*/ */
class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
{ {
/**
* @var YamlFileLoader
*/
private $loader; private $loader;
/**
* @var ClassMetadata
*/
private $metadata; private $metadata;
public function setUp() public function setUp()
@ -29,6 +35,11 @@ class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
$this->metadata = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\GroupDummy'); $this->metadata = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\GroupDummy');
} }
public function testInterface()
{
$this->assertInstanceOf('Symfony\Component\Serializer\Mapping\Loader\LoaderInterface', $this->loader);
}
public function testLoadClassMetadataReturnsTrueIfSuccessful() public function testLoadClassMetadataReturnsTrueIfSuccessful()
{ {
$this->assertTrue($this->loader->loadClassMetadata($this->metadata)); $this->assertTrue($this->loader->loadClassMetadata($this->metadata));

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\Serializer\Tests\Mapping; namespace Symfony\Component\Serializer\Tests\Mapping;
use Symfony\Component\Serializer\Mapping\AttributeMetadata;
use Symfony\Component\Serializer\Mapping\ClassMetadata; use Symfony\Component\Serializer\Mapping\ClassMetadata;
/** /**
@ -22,22 +23,38 @@ class TestClassMetadataFactory
{ {
$expected = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\GroupDummy'); $expected = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\GroupDummy');
$foo = new AttributeMetadata('foo');
$foo->addGroup('a');
$expected->addAttributeMetadata($foo);
$bar = new AttributeMetadata('bar');
$bar->addGroup('b');
$bar->addGroup('c');
$expected->addAttributeMetadata($bar);
$fooBar = new AttributeMetadata('fooBar');
$fooBar->addGroup('a');
$fooBar->addGroup('b');
$expected->addAttributeMetadata($fooBar);
$symfony = new AttributeMetadata('symfony');
$expected->addAttributeMetadata($symfony);
if ($withParent) { if ($withParent) {
$expected->addAttributeGroup('kevin', 'a'); $kevin = new AttributeMetadata('kevin');
$expected->addAttributeGroup('coopTilleuls', 'a'); $kevin->addGroup('a');
$expected->addAttributeGroup('coopTilleuls', 'b'); $expected->addAttributeMetadata($kevin);
$coopTilleuls = new AttributeMetadata('coopTilleuls');
$coopTilleuls->addGroup('a');
$coopTilleuls->addGroup('b');
$expected->addAttributeMetadata($coopTilleuls);
} }
if ($withInterface) { if ($withInterface) {
$expected->addAttributeGroup('symfony', 'a'); $symfony->addGroup('a');
} }
$expected->addAttributeGroup('foo', 'a');
$expected->addAttributeGroup('bar', 'b');
$expected->addAttributeGroup('bar', 'c');
$expected->addAttributeGroup('fooBar', 'a');
$expected->addAttributeGroup('fooBar', 'b');
// load reflection class so that the comparison passes // load reflection class so that the comparison passes
$expected->getReflectionClass(); $expected->getReflectionClass();
@ -47,9 +64,15 @@ class TestClassMetadataFactory
public static function createXmlCLassMetadata() public static function createXmlCLassMetadata()
{ {
$expected = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\GroupDummy'); $expected = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\GroupDummy');
$expected->addAttributeGroup('foo', 'group1');
$expected->addAttributeGroup('foo', 'group2'); $foo = new AttributeMetadata('foo');
$expected->addAttributeGroup('bar', 'group2'); $foo->addGroup('group1');
$foo->addGroup('group2');
$expected->addAttributeMetadata($foo);
$bar = new AttributeMetadata('bar');
$bar->addGroup('group2');
$expected->addAttributeMetadata($bar);
return $expected; return $expected;
} }

View File

@ -18,6 +18,12 @@ use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter
*/ */
class CamelCaseToSnakeCaseNameConverterTest extends \PHPUnit_Framework_TestCase class CamelCaseToSnakeCaseNameConverterTest extends \PHPUnit_Framework_TestCase
{ {
public function testInterface()
{
$attributeMetadata = new CamelCaseToSnakeCaseNameConverter();
$this->assertInstanceOf('Symfony\Component\Serializer\NameConverter\NameConverterInterface', $attributeMetadata);
}
/** /**
* @dataProvider attributeProvider * @dataProvider attributeProvider
*/ */

View File

@ -17,12 +17,23 @@ use Symfony\Component\Serializer\Serializer;
class CustomNormalizerTest extends \PHPUnit_Framework_TestCase class CustomNormalizerTest extends \PHPUnit_Framework_TestCase
{ {
/**
* @var CustomNormalizer
*/
private $normalizer;
protected function setUp() protected function setUp()
{ {
$this->normalizer = new CustomNormalizer(); $this->normalizer = new CustomNormalizer();
$this->normalizer->setSerializer(new Serializer()); $this->normalizer->setSerializer(new Serializer());
} }
public function testInterface()
{
$this->assertInstanceOf('Symfony\Component\Serializer\Normalizer\NormalizerInterface', $this->normalizer);
$this->assertInstanceOf('Symfony\Component\Serializer\Normalizer\DenormalizerInterface', $this->normalizer);
}
public function testSerialize() public function testSerialize()
{ {
$obj = new ScalarDummy(); $obj = new ScalarDummy();

View File

@ -40,6 +40,12 @@ class GetSetMethodNormalizerTest extends \PHPUnit_Framework_TestCase
$this->normalizer->setSerializer($this->serializer); $this->normalizer->setSerializer($this->serializer);
} }
public function testInterface()
{
$this->assertInstanceOf('Symfony\Component\Serializer\Normalizer\NormalizerInterface', $this->normalizer);
$this->assertInstanceOf('Symfony\Component\Serializer\Normalizer\DenormalizerInterface', $this->normalizer);
}
public function testNormalize() public function testNormalize()
{ {
$obj = new GetSetDummy(); $obj = new GetSetDummy();

View File

@ -22,6 +22,17 @@ use Symfony\Component\Serializer\Tests\Normalizer\TestDenormalizer;
class SerializerTest extends \PHPUnit_Framework_TestCase class SerializerTest extends \PHPUnit_Framework_TestCase
{ {
public function testInterface()
{
$serializer = new Serializer();
$this->assertInstanceOf('Symfony\Component\Serializer\SerializerInterface', $serializer);
$this->assertInstanceOf('Symfony\Component\Serializer\Normalizer\NormalizerInterface', $serializer);
$this->assertInstanceOf('Symfony\Component\Serializer\Normalizer\DenormalizerInterface', $serializer);
$this->assertInstanceOf('Symfony\Component\Serializer\Encoder\EncoderInterface', $serializer);
$this->assertInstanceOf('Symfony\Component\Serializer\Encoder\DecoderInterface', $serializer);
}
/** /**
* @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException
*/ */