PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/symfony/src/Symfony/Bundle/TwigBundle/Extension/FormExtension.php

https://github.com/casoetan/ServerGroveLiveChat
PHP | 295 lines | 183 code | 20 blank | 92 comment | 2 complexity | 555f9db6d36a90c8887c83caa0689fd9 MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-3.0, ISC, BSD-3-Clause
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien.potencier@symfony-project.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\Bundle\TwigBundle\Extension;
  11. use Symfony\Component\Form\Form;
  12. use Symfony\Component\Form\FormInterface;
  13. use Symfony\Component\Form\FieldInterface;
  14. use Symfony\Component\Form\CollectionField;
  15. use Symfony\Component\Form\HybridField;
  16. use Symfony\Bundle\TwigBundle\TokenParser\FormThemeTokenParser;
  17. /**
  18. * FormExtension extends Twig with form capabilities.
  19. *
  20. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  21. * @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
  22. */
  23. class FormExtension extends \Twig_Extension
  24. {
  25. protected $resources;
  26. protected $templates;
  27. protected $environment;
  28. protected $themes;
  29. public function __construct(array $resources = array())
  30. {
  31. $this->themes = new \SplObjectStorage();
  32. $this->resources = $resources;
  33. }
  34. /**
  35. * {@inheritdoc}
  36. */
  37. public function initRuntime(\Twig_Environment $environment)
  38. {
  39. $this->environment = $environment;
  40. }
  41. /**
  42. * Sets a theme for a given field.
  43. *
  44. * @param FieldInterface $field A FieldInterface instance
  45. * @param array $resources An array of resources
  46. */
  47. public function setTheme(FieldInterface $field, array $resources)
  48. {
  49. $this->themes->attach($field, $resources);
  50. }
  51. /**
  52. * Returns the token parser instance to add to the existing list.
  53. *
  54. * @return array An array of Twig_TokenParser instances
  55. */
  56. public function getTokenParsers()
  57. {
  58. return array(
  59. // {% form_theme form "SomeBungle::widgets.twig" %}
  60. new FormThemeTokenParser(),
  61. );
  62. }
  63. public function getFunctions()
  64. {
  65. return array(
  66. 'form_enctype' => new \Twig_Function_Method($this, 'renderEnctype', array('is_safe' => array('html'))),
  67. 'form_field' => new \Twig_Function_Method($this, 'renderField', array('is_safe' => array('html'))),
  68. 'form_hidden' => new \Twig_Function_Method($this, 'renderHidden', array('is_safe' => array('html'))),
  69. 'form_errors' => new \Twig_Function_Method($this, 'renderErrors', array('is_safe' => array('html'))),
  70. 'form_label' => new \Twig_Function_Method($this, 'renderLabel', array('is_safe' => array('html'))),
  71. 'form_data' => new \Twig_Function_Method($this, 'renderData', array('is_safe' => array('html'))),
  72. 'form_row' => new \Twig_Function_Method($this, 'renderRow', array('is_safe' => array('html'))),
  73. );
  74. }
  75. /**
  76. * Renders the HTML enctype in the form tag, if necessary
  77. *
  78. * Example usage in Twig templates:
  79. *
  80. * <form action="..." method="post" {{ form_enctype(form) }}>
  81. *
  82. * @param Form $form The form for which to render the encoding type
  83. */
  84. public function renderEnctype(Form $form)
  85. {
  86. return $form->isMultipart() ? 'enctype="multipart/form-data"' : '';
  87. }
  88. /**
  89. * Renders a field row.
  90. *
  91. * @param FieldInterface $field The field to render as a row
  92. */
  93. public function renderRow(FieldInterface $field)
  94. {
  95. return $this->render($field, 'field_row', array(
  96. 'child' => $field,
  97. ));
  98. }
  99. /**
  100. * Renders the HTML for an individual form field
  101. *
  102. * Example usage in Twig:
  103. *
  104. * {{ form_field(field) }}
  105. *
  106. * You can pass attributes element during the call:
  107. *
  108. * {{ form_field(field, {'class': 'foo'}) }}
  109. *
  110. * Some fields also accept additional variables as parameters:
  111. *
  112. * {{ form_field(field, {}, {'separator': '+++++'}) }}
  113. *
  114. * @param FieldInterface $field The field to render
  115. * @param array $params Additional variables passed to the template
  116. * @param string $resources
  117. */
  118. public function renderField(FieldInterface $field, array $attributes = array(), array $parameters = array(), $resources = null)
  119. {
  120. return $this->render($field, 'field', array(
  121. 'field' => $field,
  122. 'attr' => $attributes,
  123. 'params' => $parameters,
  124. ), $resources);
  125. }
  126. /**
  127. * Renders all hidden fields of the given field group
  128. *
  129. * @param FormInterface $group The field group
  130. * @param array $params Additional variables passed to the
  131. * template
  132. */
  133. public function renderHidden(FormInterface $group, array $parameters = array())
  134. {
  135. return $this->render($group, 'hidden', array(
  136. 'field' => $group,
  137. 'params' => $parameters,
  138. ));
  139. }
  140. /**
  141. * Renders the errors of the given field
  142. *
  143. * @param FieldInterface $field The field to render the errors for
  144. * @param array $params Additional variables passed to the template
  145. */
  146. public function renderErrors(FieldInterface $field, array $parameters = array())
  147. {
  148. return $this->render($field, 'errors', array(
  149. 'field' => $field,
  150. 'params' => $parameters,
  151. ));
  152. }
  153. /**
  154. * Renders the label of the given field
  155. *
  156. * @param FieldInterface $field The field to render the label for
  157. * @param array $params Additional variables passed to the template
  158. */
  159. public function renderLabel(FieldInterface $field, $label = null, array $parameters = array())
  160. {
  161. return $this->render($field, 'label', array(
  162. 'field' => $field,
  163. 'params' => $parameters,
  164. 'label' => null !== $label ? $label : ucfirst(strtolower(str_replace('_', ' ', $field->getKey()))),
  165. ));
  166. }
  167. /**
  168. * Renders the widget data of the given field
  169. *
  170. * @param FieldInterface $field The field to render the data for
  171. */
  172. public function renderData(FieldInterface $field)
  173. {
  174. return $field->getData();
  175. }
  176. protected function render(FieldInterface $field, $name, array $arguments, $resources = null)
  177. {
  178. if ('field' === $name) {
  179. list($name, $template) = $this->getWidget($field, $resources);
  180. } else {
  181. $template = $this->getTemplate($field, $name);
  182. }
  183. return $template->renderBlock($name, $arguments);
  184. }
  185. /**
  186. * @param FieldInterface $field The field to get the widget for
  187. * @param array $resources An array of template resources
  188. * @return array
  189. */
  190. protected function getWidget(FieldInterface $field, array $resources = null)
  191. {
  192. $class = get_class($field);
  193. $templates = $this->getTemplates($field, $resources);
  194. // find a template for the given class or one of its parents
  195. do {
  196. $parts = explode('\\', $class);
  197. $c = array_pop($parts);
  198. // convert the base class name (e.g. TextareaField) to underscores (e.g. textarea_field)
  199. $underscore = strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), strtr($c, '_', '.')));
  200. if (isset($templates[$underscore])) {
  201. return array($underscore, $templates[$underscore]);
  202. }
  203. } while (false !== $class = get_parent_class($class));
  204. throw new \RuntimeException(sprintf('Unable to render the "%s" field.', $field->getKey()));
  205. }
  206. protected function getTemplate(FieldInterface $field, $name, array $resources = null)
  207. {
  208. $templates = $this->getTemplates($field, $resources);
  209. return $templates[$name];
  210. }
  211. protected function getTemplates(FieldInterface $field, array $resources = null)
  212. {
  213. // templates are looked for in the following resources:
  214. // * resources provided directly into the function call
  215. // * resources from the themes (and its parents)
  216. // * default resources
  217. // defaults
  218. $all = $this->resources;
  219. // themes
  220. $parent = $field;
  221. do {
  222. if (isset($this->themes[$parent])) {
  223. $all = array_merge($all, $this->themes[$parent]);
  224. }
  225. } while ($parent = $parent->getParent());
  226. // local
  227. $all = array_merge($all, null !== $resources ? (array) $resources : array());
  228. $templates = array();
  229. foreach ($all as $resource) {
  230. if (!$resource instanceof \Twig_Template) {
  231. $resource = $this->environment->loadTemplate($resource);
  232. }
  233. $blocks = array();
  234. foreach ($this->getBlockNames($resource) as $name) {
  235. $blocks[$name] = $resource;
  236. }
  237. $templates = array_replace($templates, $blocks);
  238. }
  239. return $templates;
  240. }
  241. protected function getBlockNames($resource)
  242. {
  243. $names = $resource->getBlockNames();
  244. $parent = $resource;
  245. while (false !== $parent = $parent->getParent(array())) {
  246. $names = array_merge($names, $parent->getBlockNames());
  247. }
  248. return array_unique($names);
  249. }
  250. /**
  251. * Returns the name of the extension.
  252. *
  253. * @return string The extension name
  254. */
  255. public function getName()
  256. {
  257. return 'form';
  258. }
  259. }