ModelsToArrayTransformer.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. <?php
  2. /*
  3. * This file is part of the Sonata Project package.
  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\AdminBundle\Form\DataTransformer;
  11. use Doctrine\Common\Util\ClassUtils;
  12. use Sonata\AdminBundle\Form\ChoiceList\ModelChoiceList;
  13. use Sonata\AdminBundle\Form\ChoiceList\ModelChoiceLoader;
  14. use Sonata\AdminBundle\Model\ModelManagerInterface;
  15. use Sonata\CoreBundle\Model\Adapter\AdapterInterface;
  16. use Symfony\Component\Form\ChoiceList\LazyChoiceList;
  17. use Symfony\Component\Form\DataTransformerInterface;
  18. use Symfony\Component\Form\Exception\RuntimeException;
  19. use Symfony\Component\Form\Exception\TransformationFailedException;
  20. use Symfony\Component\Form\Exception\UnexpectedTypeException;
  21. /**
  22. * @author Thomas Rabaix <thomas.rabaix@sonata-project.org>
  23. */
  24. class ModelsToArrayTransformer implements DataTransformerInterface
  25. {
  26. /**
  27. * @var ModelManagerInterface
  28. */
  29. protected $modelManager;
  30. /**
  31. * @var string
  32. */
  33. protected $class;
  34. /**
  35. * @var ModelChoiceList
  36. *
  37. * @deprecated since 3.12, to be removed in 4.0
  38. * NEXT_MAJOR: remove this property
  39. */
  40. protected $choiceList;
  41. /**
  42. * ModelsToArrayTransformer constructor.
  43. *
  44. * @param ModelChoiceList|LazyChoiceList|ModelChoiceLoader $choiceList
  45. * @param ModelManagerInterface $modelManager
  46. * @param $class
  47. *
  48. * @throws RuntimeException
  49. */
  50. public function __construct($choiceList, $modelManager, $class = null)
  51. {
  52. /*
  53. NEXT_MAJOR: Remove condition , magic methods, legacyConstructor() method, $choiceList property and argument
  54. __construct() signature should be : public function __construct(ModelManager $modelManager, $class)
  55. */
  56. $args = func_get_args();
  57. if (func_num_args() == 3) {
  58. $this->legacyConstructor($args);
  59. } else {
  60. $this->modelManager = $args[0];
  61. $this->class = $args[1];
  62. }
  63. }
  64. /**
  65. * @internal
  66. */
  67. public function __get($name)
  68. {
  69. if ('choiceList' === $name) {
  70. $this->triggerDeprecation();
  71. }
  72. return $this->$name;
  73. }
  74. /**
  75. * @internal
  76. */
  77. public function __set($name, $value)
  78. {
  79. if ('choiceList' === $name) {
  80. $this->triggerDeprecation();
  81. }
  82. $this->$name = $value;
  83. }
  84. /**
  85. * @internal
  86. */
  87. public function __isset($name)
  88. {
  89. if ('choiceList' === $name) {
  90. $this->triggerDeprecation();
  91. }
  92. return isset($this->$name);
  93. }
  94. /**
  95. * @internal
  96. */
  97. public function __unset($name)
  98. {
  99. if ('choiceList' === $name) {
  100. $this->triggerDeprecation();
  101. }
  102. unset($this->$name);
  103. }
  104. /**
  105. * {@inheritdoc}
  106. */
  107. public function transform($collection)
  108. {
  109. if (null === $collection) {
  110. return array();
  111. }
  112. $array = array();
  113. foreach ($collection as $key => $entity) {
  114. $id = implode(AdapterInterface::ID_SEPARATOR, $this->getIdentifierValues($entity));
  115. $array[] = $id;
  116. }
  117. return $array;
  118. }
  119. /**
  120. * {@inheritdoc}
  121. */
  122. public function reverseTransform($keys)
  123. {
  124. if (!is_array($keys)) {
  125. throw new UnexpectedTypeException($keys, 'array');
  126. }
  127. $collection = $this->modelManager->getModelCollectionInstance($this->class);
  128. $notFound = array();
  129. // optimize this into a SELECT WHERE IN query
  130. foreach ($keys as $key) {
  131. if ($entity = $this->modelManager->find($this->class, $key)) {
  132. $collection[] = $entity;
  133. } else {
  134. $notFound[] = $key;
  135. }
  136. }
  137. if (count($notFound) > 0) {
  138. throw new TransformationFailedException(sprintf('The entities with keys "%s" could not be found', implode('", "', $notFound)));
  139. }
  140. return $collection;
  141. }
  142. /**
  143. * Simulates the old constructor for BC.
  144. *
  145. * @param array $args
  146. *
  147. * @throws RuntimeException
  148. */
  149. private function legacyConstructor($args)
  150. {
  151. $choiceList = $args[0];
  152. if (!$choiceList instanceof ModelChoiceList
  153. && !$choiceList instanceof ModelChoiceLoader
  154. && !$choiceList instanceof LazyChoiceList) {
  155. throw new RuntimeException('First param passed to ModelsToArrayTransformer should be instance of
  156. ModelChoiceLoader or ModelChoiceList or LazyChoiceList');
  157. }
  158. $this->choiceList = $choiceList;
  159. $this->modelManager = $args[1];
  160. $this->class = $args[2];
  161. }
  162. /**
  163. * @param object $entity
  164. *
  165. * @return array
  166. */
  167. private function getIdentifierValues($entity)
  168. {
  169. try {
  170. return $this->modelManager->getIdentifierValues($entity);
  171. } catch (\Exception $e) {
  172. throw new \InvalidArgumentException(sprintf('Unable to retrieve the identifier values for entity %s', ClassUtils::getClass($entity)), 0, $e);
  173. }
  174. }
  175. /**
  176. * @internal
  177. */
  178. private function triggerDeprecation()
  179. {
  180. @trigger_error(sprintf(
  181. 'Using the "%s::$choiceList" property is deprecated since version 3.12 and will be removed in 4.0.',
  182. __CLASS__),
  183. E_USER_DEPRECATED)
  184. ;
  185. }
  186. }