vendor/symfony/form/ResolvedFormType.php line 131

Open in your IDE?
  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\Form;
  11. use Symfony\Component\EventDispatcher\EventDispatcher;
  12. use Symfony\Component\Form\Exception\UnexpectedTypeException;
  13. use Symfony\Component\OptionsResolver\Exception\ExceptionInterface;
  14. use Symfony\Component\OptionsResolver\OptionsResolver;
  15. /**
  16. * A wrapper for a form type and its extensions.
  17. *
  18. * @author Bernhard Schussek <bschussek@gmail.com>
  19. */
  20. class ResolvedFormType implements ResolvedFormTypeInterface
  21. {
  22. /**
  23. * @var FormTypeInterface
  24. */
  25. private $innerType;
  26. /**
  27. * @var FormTypeExtensionInterface[]
  28. */
  29. private $typeExtensions;
  30. /**
  31. * @var ResolvedFormTypeInterface|null
  32. */
  33. private $parent;
  34. /**
  35. * @var OptionsResolver
  36. */
  37. private $optionsResolver;
  38. /**
  39. * @param FormTypeExtensionInterface[] $typeExtensions
  40. */
  41. public function __construct(FormTypeInterface $innerType, array $typeExtensions = [], ?ResolvedFormTypeInterface $parent = null)
  42. {
  43. foreach ($typeExtensions as $extension) {
  44. if (!$extension instanceof FormTypeExtensionInterface) {
  45. throw new UnexpectedTypeException($extension, FormTypeExtensionInterface::class);
  46. }
  47. }
  48. $this->innerType = $innerType;
  49. $this->typeExtensions = $typeExtensions;
  50. $this->parent = $parent;
  51. }
  52. /**
  53. * {@inheritdoc}
  54. */
  55. public function getBlockPrefix()
  56. {
  57. return $this->innerType->getBlockPrefix();
  58. }
  59. /**
  60. * {@inheritdoc}
  61. */
  62. public function getParent()
  63. {
  64. return $this->parent;
  65. }
  66. /**
  67. * {@inheritdoc}
  68. */
  69. public function getInnerType()
  70. {
  71. return $this->innerType;
  72. }
  73. /**
  74. * {@inheritdoc}
  75. */
  76. public function getTypeExtensions()
  77. {
  78. return $this->typeExtensions;
  79. }
  80. /**
  81. * {@inheritdoc}
  82. */
  83. public function createBuilder(FormFactoryInterface $factory, string $name, array $options = [])
  84. {
  85. try {
  86. $options = $this->getOptionsResolver()->resolve($options);
  87. } catch (ExceptionInterface $e) {
  88. throw new $e(sprintf('An error has occurred resolving the options of the form "%s": ', get_debug_type($this->getInnerType())).$e->getMessage(), $e->getCode(), $e);
  89. }
  90. // Should be decoupled from the specific option at some point
  91. $dataClass = $options['data_class'] ?? null;
  92. $builder = $this->newBuilder($name, $dataClass, $factory, $options);
  93. $builder->setType($this);
  94. return $builder;
  95. }
  96. /**
  97. * {@inheritdoc}
  98. */
  99. public function createView(FormInterface $form, ?FormView $parent = null)
  100. {
  101. return $this->newView($parent);
  102. }
  103. /**
  104. * {@inheritdoc}
  105. */
  106. public function buildForm(FormBuilderInterface $builder, array $options)
  107. {
  108. if (null !== $this->parent) {
  109. $this->parent->buildForm($builder, $options);
  110. }
  111. $this->innerType->buildForm($builder, $options);
  112. foreach ($this->typeExtensions as $extension) {
  113. $extension->buildForm($builder, $options);
  114. }
  115. }
  116. /**
  117. * {@inheritdoc}
  118. */
  119. public function buildView(FormView $view, FormInterface $form, array $options)
  120. {
  121. if (null !== $this->parent) {
  122. $this->parent->buildView($view, $form, $options);
  123. }
  124. $this->innerType->buildView($view, $form, $options);
  125. foreach ($this->typeExtensions as $extension) {
  126. $extension->buildView($view, $form, $options);
  127. }
  128. }
  129. /**
  130. * {@inheritdoc}
  131. */
  132. public function finishView(FormView $view, FormInterface $form, array $options)
  133. {
  134. if (null !== $this->parent) {
  135. $this->parent->finishView($view, $form, $options);
  136. }
  137. $this->innerType->finishView($view, $form, $options);
  138. foreach ($this->typeExtensions as $extension) {
  139. /* @var FormTypeExtensionInterface $extension */
  140. $extension->finishView($view, $form, $options);
  141. }
  142. }
  143. /**
  144. * {@inheritdoc}
  145. */
  146. public function getOptionsResolver()
  147. {
  148. if (null === $this->optionsResolver) {
  149. if (null !== $this->parent) {
  150. $this->optionsResolver = clone $this->parent->getOptionsResolver();
  151. } else {
  152. $this->optionsResolver = new OptionsResolver();
  153. }
  154. $this->innerType->configureOptions($this->optionsResolver);
  155. foreach ($this->typeExtensions as $extension) {
  156. $extension->configureOptions($this->optionsResolver);
  157. }
  158. }
  159. return $this->optionsResolver;
  160. }
  161. /**
  162. * Creates a new builder instance.
  163. *
  164. * Override this method if you want to customize the builder class.
  165. *
  166. * @return FormBuilderInterface
  167. */
  168. protected function newBuilder(string $name, ?string $dataClass, FormFactoryInterface $factory, array $options)
  169. {
  170. if ($this->innerType instanceof ButtonTypeInterface) {
  171. return new ButtonBuilder($name, $options);
  172. }
  173. if ($this->innerType instanceof SubmitButtonTypeInterface) {
  174. return new SubmitButtonBuilder($name, $options);
  175. }
  176. return new FormBuilder($name, $dataClass, new EventDispatcher(), $factory, $options);
  177. }
  178. /**
  179. * Creates a new view instance.
  180. *
  181. * Override this method if you want to customize the view class.
  182. *
  183. * @return FormView
  184. */
  185. protected function newView(?FormView $parent = null)
  186. {
  187. return new FormView($parent);
  188. }
  189. }