/library/Zend/Form/View/Helper/FormCollection.php

https://bitbucket.org/gencer/zf2 · PHP · 387 lines · 173 code · 49 blank · 165 comment · 16 complexity · 29cd8ee644f4aa9af99bc09bdb9dd12c MD5 · raw file

  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. */
  9. namespace Zend\Form\View\Helper;
  10. use RuntimeException;
  11. use Zend\Form\Element;
  12. use Zend\Form\ElementInterface;
  13. use Zend\Form\Element\Collection as CollectionElement;
  14. use Zend\Form\FieldsetInterface;
  15. use Zend\Form\LabelAwareInterface;
  16. use Zend\View\Helper\AbstractHelper as BaseAbstractHelper;
  17. class FormCollection extends AbstractHelper
  18. {
  19. /**
  20. * If set to true, collections are automatically wrapped around a fieldset
  21. *
  22. * @var bool
  23. */
  24. protected $shouldWrap = true;
  25. /**
  26. * This is the default wrapper that the collection is wrapped into
  27. *
  28. * @var string
  29. */
  30. protected $wrapper = '<fieldset%4$s>%2$s%1$s%3$s</fieldset>';
  31. /**
  32. * This is the default label-wrapper
  33. *
  34. * @var string
  35. */
  36. protected $labelWrapper = '<legend>%s</legend>';
  37. /**
  38. * Where shall the template-data be inserted into
  39. *
  40. * @var string
  41. */
  42. protected $templateWrapper = '<span data-template="%s"></span>';
  43. /**
  44. * The name of the default view helper that is used to render sub elements.
  45. *
  46. * @var string
  47. */
  48. protected $defaultElementHelper = 'formrow';
  49. /**
  50. * The view helper used to render sub elements.
  51. *
  52. * @var AbstractHelper
  53. */
  54. protected $elementHelper;
  55. /**
  56. * The view helper used to render sub fieldsets.
  57. *
  58. * @var AbstractHelper
  59. */
  60. protected $fieldsetHelper;
  61. /**
  62. * Invoke helper as function
  63. *
  64. * Proxies to {@link render()}.
  65. *
  66. * @param ElementInterface|null $element
  67. * @param bool $wrap
  68. * @return string|FormCollection
  69. */
  70. public function __invoke(ElementInterface $element = null, $wrap = true)
  71. {
  72. if (!$element) {
  73. return $this;
  74. }
  75. $this->setShouldWrap($wrap);
  76. return $this->render($element);
  77. }
  78. /**
  79. * Render a collection by iterating through all fieldsets and elements
  80. *
  81. * @param ElementInterface $element
  82. * @return string
  83. */
  84. public function render(ElementInterface $element)
  85. {
  86. $renderer = $this->getView();
  87. if (!method_exists($renderer, 'plugin')) {
  88. // Bail early if renderer is not pluggable
  89. return '';
  90. }
  91. $markup = '';
  92. $templateMarkup = '';
  93. $elementHelper = $this->getElementHelper();
  94. $fieldsetHelper = $this->getFieldsetHelper();
  95. if ($element instanceof CollectionElement && $element->shouldCreateTemplate()) {
  96. $templateMarkup = $this->renderTemplate($element);
  97. }
  98. foreach ($element->getIterator() as $elementOrFieldset) {
  99. if ($elementOrFieldset instanceof FieldsetInterface) {
  100. $markup .= $fieldsetHelper($elementOrFieldset);
  101. } elseif ($elementOrFieldset instanceof ElementInterface) {
  102. $markup .= $elementHelper($elementOrFieldset);
  103. }
  104. }
  105. // Every collection is wrapped by a fieldset if needed
  106. if ($this->shouldWrap) {
  107. $attributes = $element->getAttributes();
  108. unset($attributes['name']);
  109. $attributesString = count($attributes) ? ' ' . $this->createAttributesString($attributes) : '';
  110. $label = $element->getLabel();
  111. $legend = '';
  112. if (!empty($label)) {
  113. if (null !== ($translator = $this->getTranslator())) {
  114. $label = $translator->translate(
  115. $label,
  116. $this->getTranslatorTextDomain()
  117. );
  118. }
  119. if (! $element instanceof LabelAwareInterface || ! $element->getLabelOption('disable_html_escape')) {
  120. $escapeHtmlHelper = $this->getEscapeHtmlHelper();
  121. $label = $escapeHtmlHelper($label);
  122. }
  123. $legend = sprintf(
  124. $this->labelWrapper,
  125. $label
  126. );
  127. }
  128. $markup = sprintf(
  129. $this->wrapper,
  130. $markup,
  131. $legend,
  132. $templateMarkup,
  133. $attributesString
  134. );
  135. } else {
  136. $markup .= $templateMarkup;
  137. }
  138. return $markup;
  139. }
  140. /**
  141. * Only render a template
  142. *
  143. * @param CollectionElement $collection
  144. * @return string
  145. */
  146. public function renderTemplate(CollectionElement $collection)
  147. {
  148. $elementHelper = $this->getElementHelper();
  149. $escapeHtmlAttribHelper = $this->getEscapeHtmlAttrHelper();
  150. $fieldsetHelper = $this->getFieldsetHelper();
  151. $templateMarkup = '';
  152. $elementOrFieldset = $collection->getTemplateElement();
  153. if ($elementOrFieldset instanceof FieldsetInterface) {
  154. $templateMarkup .= $fieldsetHelper($elementOrFieldset);
  155. } elseif ($elementOrFieldset instanceof ElementInterface) {
  156. $templateMarkup .= $elementHelper($elementOrFieldset);
  157. }
  158. return sprintf(
  159. $this->templateWrapper,
  160. $escapeHtmlAttribHelper($templateMarkup)
  161. );
  162. }
  163. /**
  164. * If set to true, collections are automatically wrapped around a fieldset
  165. *
  166. * @param bool $wrap
  167. * @return FormCollection
  168. */
  169. public function setShouldWrap($wrap)
  170. {
  171. $this->shouldWrap = (bool) $wrap;
  172. return $this;
  173. }
  174. /**
  175. * Get wrapped
  176. *
  177. * @return bool
  178. */
  179. public function shouldWrap()
  180. {
  181. return $this->shouldWrap;
  182. }
  183. /**
  184. * Sets the name of the view helper that should be used to render sub elements.
  185. *
  186. * @param string $defaultSubHelper The name of the view helper to set.
  187. * @return FormCollection
  188. */
  189. public function setDefaultElementHelper($defaultSubHelper)
  190. {
  191. $this->defaultElementHelper = $defaultSubHelper;
  192. return $this;
  193. }
  194. /**
  195. * Gets the name of the view helper that should be used to render sub elements.
  196. *
  197. * @return string
  198. */
  199. public function getDefaultElementHelper()
  200. {
  201. return $this->defaultElementHelper;
  202. }
  203. /**
  204. * Sets the element helper that should be used by this collection.
  205. *
  206. * @param AbstractHelper $elementHelper The element helper to use.
  207. * @return FormCollection
  208. */
  209. public function setElementHelper(AbstractHelper $elementHelper)
  210. {
  211. $this->elementHelper = $elementHelper;
  212. return $this;
  213. }
  214. /**
  215. * Retrieve the element helper.
  216. *
  217. * @return AbstractHelper
  218. * @throws RuntimeException
  219. */
  220. protected function getElementHelper()
  221. {
  222. if ($this->elementHelper) {
  223. return $this->elementHelper;
  224. }
  225. if (method_exists($this->view, 'plugin')) {
  226. $this->elementHelper = $this->view->plugin($this->getDefaultElementHelper());
  227. }
  228. if (!$this->elementHelper instanceof BaseAbstractHelper) {
  229. // @todo Ideally the helper should implement an interface.
  230. throw new RuntimeException('Invalid element helper set in FormCollection. The helper must be an instance of AbstractHelper.');
  231. }
  232. return $this->elementHelper;
  233. }
  234. /**
  235. * Sets the fieldset helper that should be used by this collection.
  236. *
  237. * @param AbstractHelper $fieldsetHelper The fieldset helper to use.
  238. * @return FormCollection
  239. */
  240. public function setFieldsetHelper(AbstractHelper $fieldsetHelper)
  241. {
  242. $this->fieldsetHelper = $fieldsetHelper;
  243. return $this;
  244. }
  245. /**
  246. * Retrieve the fieldset helper.
  247. *
  248. * @return FormCollection
  249. */
  250. protected function getFieldsetHelper()
  251. {
  252. if ($this->fieldsetHelper) {
  253. return $this->fieldsetHelper;
  254. }
  255. return $this;
  256. }
  257. /**
  258. * Get the wrapper for the collection
  259. *
  260. * @return string
  261. */
  262. public function getWrapper()
  263. {
  264. return $this->wrapper;
  265. }
  266. /**
  267. * Set the wrapper for this collection
  268. *
  269. * The string given will be passed through sprintf with the following three
  270. * replacements:
  271. *
  272. * 1. The content of the collection
  273. * 2. The label of the collection. If no label is given this will be an empty
  274. * string
  275. * 3. The template span-tag. This might also be an empty string
  276. *
  277. * The preset default is <pre><fieldset>%2$s%1$s%3$s</fieldset></pre>
  278. *
  279. * @param string $wrapper
  280. *
  281. * @return self
  282. */
  283. public function setWrapper($wrapper)
  284. {
  285. $this->wrapper = $wrapper;
  286. return $this;
  287. }
  288. /**
  289. * Set the label-wrapper
  290. * The string will be passed through sprintf with the label as single
  291. * parameter
  292. * This defaults to '<legend>%s</legend>'
  293. *
  294. * @param string $labelWrapper
  295. *
  296. * @return self
  297. */
  298. public function setLabelWrapper($labelWrapper)
  299. {
  300. $this->labelWrapper = $labelWrapper;
  301. return $this;
  302. }
  303. /**
  304. * Get the wrapper for the label
  305. *
  306. * @return string
  307. */
  308. public function getLabelWrapper()
  309. {
  310. return $this->labelWrapper;
  311. }
  312. /**
  313. * Ge the wrapper for the template
  314. *
  315. * @return string
  316. */
  317. public function getTemplateWrapper()
  318. {
  319. return $this->templateWrapper;
  320. }
  321. /**
  322. * Set the string where the template will be inserted into
  323. *
  324. * This string will be passed through sprintf and has the template as single
  325. * parameter
  326. *
  327. * THis defaults to '<span data-template="%s"></span>'
  328. *
  329. * @param string $templateWrapper
  330. *
  331. * @return self
  332. */
  333. public function setTemplateWrapper($templateWrapper)
  334. {
  335. $this->templateWrapper = $templateWrapper;
  336. return $this;
  337. }
  338. }