AdminHelper.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <?php
  2. /*
  3. * This file is part of the Sonata 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\Admin;
  11. use Symfony\Component\Form\FormBuilder;
  12. use Symfony\Component\Form\FormView;
  13. use Sonata\AdminBundle\Exception\NoValueException;
  14. use Sonata\AdminBundle\Util\FormViewIterator;
  15. use Sonata\AdminBundle\Util\FormBuilderIterator;
  16. use Sonata\AdminBundle\Admin\BaseFieldDescription;
  17. class AdminHelper
  18. {
  19. protected $pool;
  20. /**
  21. * @param Pool $pool
  22. */
  23. public function __construct(Pool $pool)
  24. {
  25. $this->pool = $pool;
  26. }
  27. /**
  28. * @throws \RuntimeException
  29. *
  30. * @param \Symfony\Component\Form\FormBuilder $formBuilder
  31. * @param string $elementId
  32. *
  33. * @return \Symfony\Component\Form\FormBuilder
  34. */
  35. public function getChildFormBuilder(FormBuilder $formBuilder, $elementId)
  36. {
  37. foreach (new FormBuilderIterator($formBuilder) as $name => $formBuilder) {
  38. if ($name == $elementId) {
  39. return $formBuilder;
  40. }
  41. }
  42. return null;
  43. }
  44. /**
  45. * @param \Symfony\Component\Form\FormView $formView
  46. * @param string $elementId
  47. *
  48. * @return null|\Symfony\Component\Form\FormView
  49. */
  50. public function getChildFormView(FormView $formView, $elementId)
  51. {
  52. foreach (new \RecursiveIteratorIterator(new FormViewIterator($formView), \RecursiveIteratorIterator::SELF_FIRST) as $name => $formView) {
  53. if ($name === $elementId) {
  54. return $formView;
  55. }
  56. }
  57. return null;
  58. }
  59. /**
  60. * @deprecated
  61. *
  62. * @param string $code
  63. *
  64. * @return \Sonata\AdminBundle\Admin\AdminInterface
  65. */
  66. public function getAdmin($code)
  67. {
  68. return $this->pool->getInstance($code);
  69. }
  70. /**
  71. * Note:
  72. * This code is ugly, but there is no better way of doing it.
  73. * For now the append form element action used to add a new row works
  74. * only for direct FieldDescription (not nested one)
  75. *
  76. * @throws \RuntimeException
  77. *
  78. * @param \Sonata\AdminBundle\Admin\AdminInterface $admin
  79. * @param object $subject
  80. * @param string $elementId
  81. *
  82. * @return array
  83. */
  84. public function appendFormFieldElement(AdminInterface $admin, $subject, $elementId)
  85. {
  86. // retrieve the subject
  87. $formBuilder = $admin->getFormBuilder();
  88. $form = $formBuilder->getForm();
  89. $form->setData($subject);
  90. $form->bind($admin->getRequest());
  91. // get the field element
  92. $childFormBuilder = $this->getChildFormBuilder($formBuilder, $elementId);
  93. // retrieve the FieldDescription
  94. $fieldDescription = $admin->getFormFieldDescription($childFormBuilder->getName());
  95. try {
  96. $value = $fieldDescription->getValue($form->getData());
  97. } catch (NoValueException $e) {
  98. $value = null;
  99. }
  100. // retrieve the posted data
  101. $data = $admin->getRequest()->get($formBuilder->getName());
  102. if (!isset($data[$childFormBuilder->getName()])) {
  103. $data[$childFormBuilder->getName()] = array();
  104. }
  105. $objectCount = count($value);
  106. $postCount = count($data[$childFormBuilder->getName()]);
  107. $fields = array_keys($fieldDescription->getAssociationAdmin()->getFormFieldDescriptions());
  108. // for now, not sure how to do that
  109. $value = array();
  110. foreach ($fields as $name) {
  111. $value[$name] = '';
  112. }
  113. // add new elements to the subject
  114. while ($objectCount < $postCount) {
  115. // append a new instance into the object
  116. $this->addNewInstance($form->getData(), $fieldDescription);
  117. $objectCount++;
  118. }
  119. $this->addNewInstance($form->getData(), $fieldDescription);
  120. $data[$childFormBuilder->getName()][] = $value;
  121. $finalForm = $admin->getFormBuilder()->getForm();
  122. $finalForm->setData($subject);
  123. // bind the data
  124. $finalForm->setData($form->getData());
  125. return array($fieldDescription, $finalForm);
  126. }
  127. /**
  128. * Add a new instance to the related FieldDescriptionInterface value
  129. *
  130. * @param object $object
  131. * @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $fieldDescription
  132. *
  133. * @throws \RuntimeException
  134. */
  135. public function addNewInstance($object, FieldDescriptionInterface $fieldDescription)
  136. {
  137. $instance = $fieldDescription->getAssociationAdmin()->getNewInstance();
  138. $mapping = $fieldDescription->getAssociationMapping();
  139. $method = sprintf('add%s', $this->camelize($mapping['fieldName']));
  140. if (!method_exists($object, $method)) {
  141. $method = rtrim($method, 's');
  142. if (!method_exists($object, $method)) {
  143. throw new \RuntimeException(sprintf('Please add a method %s in the %s class!', $method, get_class($object)));
  144. }
  145. }
  146. $object->$method($instance);
  147. }
  148. /**
  149. * Camelize a string
  150. *
  151. * @static
  152. *
  153. * @param string $property
  154. *
  155. * @return string
  156. */
  157. public function camelize($property)
  158. {
  159. return BaseFieldDescription::camelize($property);
  160. }
  161. }