ArrayToObjectTransformer.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. <?php
  2. /*
  3. * This file is part of the Sonata project.
  4. *
  5. * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
  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 Sonata\BaseApplicationBundle\Form\ValueTransformer;
  11. use Symfony\Component\Form\ValueTransformer\ValueTransformerInterface;
  12. use Symfony\Component\Form\ValueTransformer\TransformationFailedException;
  13. use Symfony\Component\Form\Configurable;
  14. use Symfony\Component\Form\Exception\InvalidPropertyException;
  15. use Symfony\Component\Form\Exception\PropertyAccessDeniedException;
  16. class ArrayToObjectTransformer extends Configurable implements ValueTransformerInterface
  17. {
  18. protected function configure()
  19. {
  20. $this->addRequiredOption('em');
  21. $this->addRequiredOption('className');
  22. parent::configure();
  23. }
  24. /**
  25. * @param array $ids
  26. * @param Collection $collection
  27. */
  28. public function reverseTransform($array)
  29. {
  30. $class = $this->getOption('className');
  31. $metadata = $this->getOption('em')->getClassMetadata($class);
  32. // when the object is created the form return an array
  33. // one the object is persisted, the edit $array is the user instance
  34. if ($array instanceof $class)
  35. {
  36. return $array;
  37. }
  38. $instance = new $class;
  39. if (!is_array($array)) {
  40. return $instance;
  41. }
  42. $reflClass = $metadata->reflClass;
  43. foreach ($array as $name => $value) {
  44. $reflection_property = false;
  45. // property or association ?
  46. if (array_key_exists($name, $metadata->fieldMappings)) {
  47. $property = $metadata->fieldMappings[$name]['fieldName'];
  48. $reflection_property = $metadata->reflFields[$name];
  49. } else if (array_key_exists($name, $metadata->associationMappings)) {
  50. $property = $metadata->associationMappings[$name]['fieldName'];
  51. } else {
  52. $property = $name;
  53. }
  54. $setter = 'set'.$this->camelize($name);
  55. if ($reflClass->hasMethod($setter)) {
  56. if (!$reflClass->getMethod($setter)->isPublic()) {
  57. throw new PropertyAccessDeniedException(sprintf('Method "%s()" is not public in class "%s"', $setter, $reflClass->getName()));
  58. }
  59. $instance->$setter($value);
  60. } else if ($reflClass->hasMethod('__set')) {
  61. // needed to support magic method __set
  62. $instance->$property = $value;
  63. } else if ($reflClass->hasProperty($property)) {
  64. if (!$reflClass->getProperty($property)->isPublic()) {
  65. throw new PropertyAccessDeniedException(sprintf('Property "%s" is not public in class "%s". Maybe you should create the method "set%s()"?', $property, $reflClass->getName(), ucfirst($property)));
  66. }
  67. $instance->$property = $value;
  68. } else if ($reflection_property) {
  69. $reflection_property->setValue($instance, $value);
  70. }
  71. }
  72. return $instance;
  73. }
  74. /**
  75. * @param Collection $value
  76. */
  77. public function transform($value)
  78. {
  79. return $value;
  80. }
  81. /**
  82. * method taken from PropertyPath
  83. *
  84. * @param $property
  85. * @return mixed
  86. */
  87. protected function camelize($property)
  88. {
  89. return preg_replace(array('/(^|_)+(.)/e', '/\.(.)/e'), array("strtoupper('\\2')", "'_'.strtoupper('\\1')"), $property);
  90. }
  91. }