AdminHelper.php 5.5 KB

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