ObjectNormalizer.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Serializer\Normalizer;
  11. use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
  12. use Symfony\Component\PropertyAccess\PropertyAccess;
  13. use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
  14. use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
  15. use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
  16. use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
  17. /**
  18. * Converts between objects and arrays using the PropertyAccess component.
  19. *
  20. * @author Kévin Dunglas <dunglas@gmail.com>
  21. */
  22. class ObjectNormalizer extends AbstractObjectNormalizer
  23. {
  24. /**
  25. * @var PropertyAccessorInterface
  26. */
  27. protected $propertyAccessor;
  28. public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyAccessorInterface $propertyAccessor = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null)
  29. {
  30. parent::__construct($classMetadataFactory, $nameConverter, $propertyTypeExtractor);
  31. $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
  32. }
  33. /**
  34. * {@inheritdoc}
  35. */
  36. protected function extractAttributes($object, $format = null, array $context = array())
  37. {
  38. // If not using groups, detect manually
  39. $attributes = array();
  40. // methods
  41. $reflClass = new \ReflectionClass($object);
  42. foreach ($reflClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflMethod) {
  43. if (
  44. $reflMethod->getNumberOfRequiredParameters() !== 0 ||
  45. $reflMethod->isStatic() ||
  46. $reflMethod->isConstructor() ||
  47. $reflMethod->isDestructor()
  48. ) {
  49. continue;
  50. }
  51. $name = $reflMethod->name;
  52. $attributeName = null;
  53. if (0 === strpos($name, 'get') || 0 === strpos($name, 'has')) {
  54. // getters and hassers
  55. $attributeName = lcfirst(substr($name, 3));
  56. } elseif (strpos($name, 'is') === 0) {
  57. // issers
  58. $attributeName = lcfirst(substr($name, 2));
  59. }
  60. if (null !== $attributeName && $this->isAllowedAttribute($object, $attributeName, $format, $context)) {
  61. $attributes[$attributeName] = true;
  62. }
  63. }
  64. // properties
  65. foreach ($reflClass->getProperties(\ReflectionProperty::IS_PUBLIC) as $reflProperty) {
  66. if ($reflProperty->isStatic() || !$this->isAllowedAttribute($object, $reflProperty->name, $format, $context)) {
  67. continue;
  68. }
  69. $attributes[$reflProperty->name] = true;
  70. }
  71. return array_keys($attributes);
  72. }
  73. /**
  74. * {@inheritdoc}
  75. */
  76. protected function getAttributeValue($object, $attribute, $format = null, array $context = array())
  77. {
  78. return $this->propertyAccessor->getValue($object, $attribute);
  79. }
  80. /**
  81. * {@inheritdoc}
  82. */
  83. protected function setAttributeValue($object, $attribute, $value, $format = null, array $context = array())
  84. {
  85. try {
  86. $this->propertyAccessor->setValue($object, $attribute, $value);
  87. } catch (NoSuchPropertyException $exception) {
  88. // Properties not found are ignored
  89. }
  90. }
  91. }