FormHelper.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. <?php
  2. namespace Symfony\Bundle\FrameworkBundle\Templating\Helper;
  3. use Symfony\Component\Templating\Helper\Helper;
  4. use Symfony\Component\Form\FieldInterface;
  5. use Symfony\Component\Form\FieldGroupInterface;
  6. use Symfony\Bundle\FrameworkBundle\Templating\DelegatingEngine;
  7. /*
  8. * This file is part of the Symfony framework.
  9. *
  10. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  11. *
  12. * This source file is subject to the MIT license that is bundled
  13. * with this source code in the file LICENSE.
  14. */
  15. /**
  16. * Form is a factory that wraps Form instances.
  17. *
  18. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  19. * @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
  20. */
  21. class FormHelper extends Helper
  22. {
  23. static protected $cache = array();
  24. protected $engine;
  25. public function __construct(DelegatingEngine $engine)
  26. {
  27. $this->engine = $engine;
  28. }
  29. public function getName()
  30. {
  31. return 'form';
  32. }
  33. public function attributes($attributes)
  34. {
  35. if ($attributes instanceof \Traversable) {
  36. $attributes = iterator_to_array($attributes);
  37. }
  38. return implode('', array_map(array($this, 'attributesCallback'), array_keys($attributes), array_values($attributes)));
  39. }
  40. private function attribute($name, $value)
  41. {
  42. return sprintf('%s="%s"', $name, true === $value ? $name : $value);
  43. }
  44. /**
  45. * Prepares an attribute key and value for HTML representation.
  46. *
  47. * It removes empty attributes, except for the value one.
  48. *
  49. * @param string $name The attribute name
  50. * @param string $value The attribute value
  51. *
  52. * @return string The HTML representation of the HTML key attribute pair.
  53. */
  54. private function attributesCallback($name, $value)
  55. {
  56. if (false === $value || null === $value || ('' === $value && 'value' != $name)) {
  57. return '';
  58. } else {
  59. return ' '.$this->attribute($name, $value);
  60. }
  61. }
  62. /**
  63. * Renders the form tag.
  64. *
  65. * This method only renders the opening form tag.
  66. * You need to close it after the form rendering.
  67. *
  68. * This method takes into account the multipart widgets.
  69. *
  70. * @param string $url The URL for the action
  71. * @param array $attributes An array of HTML attributes
  72. *
  73. * @return string An HTML representation of the opening form tag
  74. */
  75. public function enctype(/*Form */$form)
  76. {
  77. return $form->isMultipart() ? ' enctype="multipart/form-data"' : '';
  78. }
  79. public function render(/*FieldInterface */$field, array $attributes = array(), array $parameters = array(), $template = null)
  80. {
  81. if (null === $template) {
  82. $template = $this->lookupTemplate($field);
  83. if (null === $template) {
  84. throw new \RuntimeException(sprintf('Unable to find a template to render the "%s" widget.', $field->getKey()));
  85. }
  86. }
  87. return trim($this->engine->render($template, array(
  88. 'field' => $field,
  89. 'attr' => $attributes,
  90. 'params' => $parameters,
  91. )));
  92. }
  93. /**
  94. * Renders the entire form field "row".
  95. *
  96. * @param FieldInterface $field
  97. * @return string
  98. */
  99. public function row(/*FieldInterface*/ $field, $template = null)
  100. {
  101. if (null === $template) {
  102. $template = 'FrameworkBundle:Form:field_row.php.html';
  103. }
  104. return $this->engine->render($template, array(
  105. 'field' => $field,
  106. ));
  107. }
  108. public function label(/*FieldInterface */$field, $label = false, array $parameters = array(), $template = null)
  109. {
  110. if (null === $template) {
  111. $template = 'FrameworkBundle:Form:label.php.html';
  112. }
  113. return $this->engine->render($template, array(
  114. 'field' => $field,
  115. 'params' => $parameters,
  116. 'label' => $label ? $label : ucfirst(strtolower(str_replace('_', ' ', $field->getKey())))
  117. ));
  118. }
  119. public function errors(/*FieldInterface */$field, array $parameters = array(), $template = null)
  120. {
  121. if (null === $template) {
  122. $template = 'FrameworkBundle:Form:errors.php.html';
  123. }
  124. return $this->engine->render($template, array(
  125. 'field' => $field,
  126. 'params' => $parameters,
  127. ));
  128. }
  129. public function hidden(/*FieldGroupInterface */$group, array $parameters = array(), $template = null)
  130. {
  131. if (null === $template) {
  132. $template = 'FrameworkBundle:Form:hidden.php.html';
  133. }
  134. return $this->engine->render($template, array(
  135. 'field' => $group,
  136. 'params' => $parameters,
  137. ));
  138. }
  139. protected function lookupTemplate(/*FieldInterface */$field)
  140. {
  141. $fqClassName = get_class($field);
  142. $template = null;
  143. if (isset(self::$cache[$fqClassName])) {
  144. return self::$cache[$fqClassName];
  145. }
  146. // find a template for the given class or one of its parents
  147. $currentFqClassName = $fqClassName;
  148. do {
  149. $parts = explode('\\', $currentFqClassName);
  150. $className = array_pop($parts);
  151. $underscoredName = strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), strtr($className, '_', '.')));
  152. if ($this->engine->exists($guess = 'FrameworkBundle:Form:'.$underscoredName.'.php.html')) {
  153. $template = $guess;
  154. }
  155. $currentFqClassName = get_parent_class($currentFqClassName);
  156. } while (null === $template && false !== $currentFqClassName);
  157. if (null === $template && $field instanceof FieldGroupInterface) {
  158. $template = 'FrameworkBundle:Form:field_group.php.html';
  159. }
  160. self::$cache[$fqClassName] = $template;
  161. return $template;
  162. }
  163. }