2015-08-17 17:00:26 -07:00
< ? 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\Normalizer ;
use Symfony\Component\Serializer\Exception\CircularReferenceException ;
use Symfony\Component\Serializer\Exception\LogicException ;
use Symfony\Component\Serializer\Exception\RuntimeException ;
/**
* Converts between objects and arrays by mapping properties .
*
* The normalization process looks for all the object ' s properties ( public and private ) .
* The result is a map from property names 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
* property with the corresponding name exists . If found , the property gets the value .
*
* @ author Matthieu Napoli < matthieu @ mnapoli . fr >
* @ author Kévin Dunglas < dunglas @ gmail . com >
*/
class PropertyNormalizer extends AbstractNormalizer
{
/**
* { @ inheritdoc }
*
* @ throws CircularReferenceException
*/
public function normalize ( $object , $format = null , array $context = array ())
{
if ( $this -> isCircularReference ( $object , $context )) {
return $this -> handleCircularReference ( $object );
}
$reflectionObject = new \ReflectionObject ( $object );
$attributes = array ();
$allowedAttributes = $this -> getAllowedAttributes ( $object , $context , true );
foreach ( $reflectionObject -> getProperties () as $property ) {
2016-04-20 09:56:34 -07:00
if ( in_array ( $property -> name , $this -> ignoredAttributes ) || $property -> isStatic ()) {
2015-08-17 17:00:26 -07:00
continue ;
}
if ( false !== $allowedAttributes && ! in_array ( $property -> name , $allowedAttributes )) {
continue ;
}
// Override visibility
if ( ! $property -> isPublic ()) {
$property -> setAccessible ( true );
}
$attributeValue = $property -> getValue ( $object );
if ( isset ( $this -> callbacks [ $property -> name ])) {
$attributeValue = call_user_func ( $this -> callbacks [ $property -> name ], $attributeValue );
}
if ( null !== $attributeValue && ! is_scalar ( $attributeValue )) {
if ( ! $this -> serializer instanceof NormalizerInterface ) {
throw new LogicException ( sprintf ( 'Cannot normalize attribute "%s" because injected serializer is not a normalizer' , $property -> name ));
}
$attributeValue = $this -> serializer -> normalize ( $attributeValue , $format , $context );
}
$propertyName = $property -> name ;
if ( $this -> nameConverter ) {
$propertyName = $this -> nameConverter -> normalize ( $propertyName );
}
$attributes [ $propertyName ] = $attributeValue ;
}
return $attributes ;
}
/**
* { @ inheritdoc }
*
* @ throws RuntimeException
*/
public function denormalize ( $data , $class , $format = null , array $context = array ())
{
$allowedAttributes = $this -> getAllowedAttributes ( $class , $context , true );
$data = $this -> prepareForDenormalization ( $data );
$reflectionClass = new \ReflectionClass ( $class );
$object = $this -> instantiateObject ( $data , $class , $context , $reflectionClass , $allowedAttributes );
foreach ( $data as $propertyName => $value ) {
if ( $this -> nameConverter ) {
$propertyName = $this -> nameConverter -> denormalize ( $propertyName );
}
$allowed = $allowedAttributes === false || in_array ( $propertyName , $allowedAttributes );
$ignored = in_array ( $propertyName , $this -> ignoredAttributes );
if ( $allowed && ! $ignored && $reflectionClass -> hasProperty ( $propertyName )) {
$property = $reflectionClass -> getProperty ( $propertyName );
2016-04-20 09:56:34 -07:00
if ( $property -> isStatic ()) {
continue ;
}
2015-08-17 17:00:26 -07:00
// Override visibility
if ( ! $property -> isPublic ()) {
$property -> setAccessible ( true );
}
$property -> setValue ( $object , $value );
}
}
return $object ;
}
/**
* { @ inheritdoc }
*/
public function supportsNormalization ( $data , $format = null )
{
return is_object ( $data ) && ! $data instanceof \Traversable && $this -> supports ( get_class ( $data ));
}
/**
* { @ inheritdoc }
*/
public function supportsDenormalization ( $data , $type , $format = null )
{
2016-04-20 09:56:34 -07:00
return class_exists ( $type ) && $this -> supports ( $type );
2015-08-17 17:00:26 -07:00
}
/**
* Checks if the given class has any non - static property .
*
* @ param string $class
*
* @ return bool
*/
private function supports ( $class )
{
$class = new \ReflectionClass ( $class );
// We look for at least one non-static property
foreach ( $class -> getProperties () as $property ) {
if ( ! $property -> isStatic ()) {
return true ;
}
}
return false ;
}
}