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

/Classes/ViewHelpers/Form/SelectViewHelper.php

https://github.com/dcballs/vhs
PHP | 257 lines | 155 code | 20 blank | 82 comment | 41 complexity | 816aa49afb2a5a13ec3d8dd165743c49 MD5 | raw file
  1. <?php
  2. /***************************************************************
  3. * Copyright notice
  4. *
  5. * (c) 2012 Claus Due <claus@wildside.dk>, Wildside A/S
  6. *
  7. * All rights reserved
  8. *
  9. * This script is part of the TYPO3 project. The TYPO3 project is
  10. * free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * The GNU General Public License can be found at
  16. * http://www.gnu.org/copyleft/gpl.html.
  17. *
  18. * This script is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * This copyright notice MUST APPEAR in all copies of the script!
  24. * ************************************************************* */
  25. /**
  26. * Select ViewHelper (with support for Optgroup and Option subnodes)
  27. *
  28. * @author Claus Due <claus@wildside.dk>, Wildside A/S
  29. * @package Vhs
  30. * @subpackage ViewHelpers\Form
  31. */
  32. class Tx_Vhs_ViewHelpers_Form_SelectViewHelper extends Tx_Fluid_ViewHelpers_Form_AbstractFormFieldViewHelper {
  33. /**
  34. * @var string
  35. */
  36. protected $tagName = 'select';
  37. /**
  38. * @var mixed
  39. */
  40. protected $selectedValue = NULL;
  41. /**
  42. * Initialize arguments.
  43. *
  44. * @return void
  45. * @api
  46. */
  47. public function initializeArguments() {
  48. parent::initializeArguments();
  49. $this->registerUniversalTagAttributes();
  50. $this->registerTagAttribute('size', 'string', 'Size of input field');
  51. $this->registerTagAttribute('disabled', 'string', 'Specifies that the input element should be disabled when the page loads');
  52. $this->registerArgument('multiple', 'boolean', 'if set, multiple select field', FALSE, FALSE);
  53. $this->registerArgument('options', 'array', 'Associative array with internal IDs as key, and the values are displayed in the select box');
  54. $this->registerArgument('optionValueField', 'string', 'If specified, will call the appropriate getter on each object to determine the value.');
  55. $this->registerArgument('optionLabelField', 'string', 'If specified, will call the appropriate getter on each object to determine the label.');
  56. $this->registerArgument('sortByOptionLabel', 'boolean', 'If true, List will be sorted by label.', FALSE, FALSE);
  57. $this->registerArgument('selectAllByDefault', 'boolean', 'If specified options are selected if none was set before.', FALSE, FALSE);
  58. $this->registerArgument('errorClass', 'string', 'CSS class to set if there are errors for this view helper', FALSE, 'f3-form-error');
  59. }
  60. /**
  61. * Render the tag.
  62. *
  63. * @return string rendered tag.
  64. * @api
  65. */
  66. public function render() {
  67. $name = $this->getName();
  68. if (TRUE === (boolean) $this->arguments['multiple']) {
  69. $name .= '[]';
  70. }
  71. $this->tag->addAttribute('name', $name);
  72. if (TRUE === isset($this->arguments['options']) && FALSE === empty($this->arguments['options'])) {
  73. $options = $this->getOptions();
  74. if (TRUE === empty($options)) {
  75. $options = array('' => '');
  76. }
  77. $this->tag->setContent($this->renderOptionTags($options));
  78. } else {
  79. $this->viewHelperVariableContainer->add('Tx_Vhs_ViewHelpers_Form_SelectViewHelper', 'options', array());
  80. $this->viewHelperVariableContainer->add('Tx_Vhs_ViewHelpers_Form_SelectViewHelper', 'value', $this->getValue());
  81. $tagContent = $this->renderChildren();
  82. $options = $this->viewHelperVariableContainer->get('Tx_Vhs_ViewHelpers_Form_SelectViewHelper', 'options');
  83. $this->tag->setContent($tagContent);
  84. $this->viewHelperVariableContainer->remove('Tx_Vhs_ViewHelpers_Form_SelectViewHelper', 'options');
  85. if (TRUE === $this->viewHelperVariableContainer->exists('Tx_Vhs_ViewHelpers_Form_SelectViewHelper', 'value')) {
  86. $this->viewHelperVariableContainer->remove('Tx_Vhs_ViewHelpers_Form_SelectViewHelper', 'value');
  87. }
  88. }
  89. $this->setErrorClassAttribute();
  90. $content = '';
  91. // register field name for token generation.
  92. // in case it is a multi-select, we need to register the field name
  93. // as often as there are elements in the box
  94. if (TRUE === (boolean) $this->arguments['multiple']) {
  95. $content .= $this->renderHiddenFieldForEmptyValue();
  96. $length = count($options);
  97. for ($i = 0; $i < $length; $i++) {
  98. $this->registerFieldNameForFormTokenGeneration($name);
  99. }
  100. $this->tag->addAttribute('multiple', 'multiple');
  101. } else {
  102. $this->registerFieldNameForFormTokenGeneration($name);
  103. $this->tag->removeAttribute('multiple');
  104. }
  105. $content .= $this->tag->render();
  106. return $content;
  107. }
  108. /**
  109. * Render the option tags.
  110. *
  111. * @param array $options the options for the form.
  112. * @return string rendered tags.
  113. */
  114. protected function renderOptionTags($options) {
  115. $output = '';
  116. foreach ($options as $value => $label) {
  117. $isSelected = $this->isSelected($value);
  118. $output .= $this->renderOptionTag($value, $label, $isSelected) . chr(10);
  119. }
  120. return $output;
  121. }
  122. /**
  123. * Render the option tags.
  124. *
  125. * @throws Tx_Fluid_Core_ViewHelper_Exception
  126. * @return array
  127. */
  128. protected function getOptions() {
  129. if (FALSE === is_array($this->arguments['options']) && FALSE === ($this->arguments['options'] instanceof Traversable)) {
  130. return array();
  131. }
  132. $options = array();
  133. $optionsArgument = $this->arguments['options'];
  134. foreach ($optionsArgument as $key => $value) {
  135. if (is_object($value)) {
  136. if (TRUE === isset($this->arguments['optionValueField']) && FALSE === empty($this->arguments['optionValueField'])) {
  137. $key = Tx_Extbase_Reflection_ObjectAccess::getProperty($value, $this->arguments['optionValueField']);
  138. if (TRUE === is_object($key)) {
  139. if (TRUE === method_exists($key, '__toString')) {
  140. $key = (string) $key;
  141. } else {
  142. throw new Tx_Fluid_Core_ViewHelper_Exception('Identifying value for object of class "' . get_class($value) . '" was an object.', 1247827428);
  143. }
  144. }
  145. } elseif (NULL !== $this->persistenceManager->getBackend()->getIdentifierByObject($value)) {
  146. $key = $this->persistenceManager->getBackend()->getIdentifierByObject($value);
  147. } elseif (TRUE === method_exists($value, '__toString')) {
  148. $key = (string) $value;
  149. } else {
  150. throw new Tx_Fluid_Core_ViewHelper_Exception('No identifying value for object of class "' . get_class($value) . '" found.', 1247826696);
  151. }
  152. if (TRUE === isset($this->arguments['optionLabelField']) && FALSE === empty($this->arguments['optionLabelField'])) {
  153. $value = Tx_Extbase_Reflection_ObjectAccess::getProperty($value, $this->arguments['optionLabelField']);
  154. if (TRUE === is_object($value)) {
  155. if (TRUE === method_exists($value, '__toString')) {
  156. $value = (string) $value;
  157. } else {
  158. throw new Tx_Fluid_Core_ViewHelper_Exception('Label value for object of class "' . get_class($value) . '" was an object without a __toString() method.', 1247827553);
  159. }
  160. }
  161. } elseif (TRUE === method_exists($value, '__toString')) {
  162. $value = (string) $value;
  163. } elseif (NULL !== $this->persistenceManager->getBackend()->getIdentifierByObject($value)) {
  164. $value = $this->persistenceManager->getBackend()->getIdentifierByObject($value);
  165. }
  166. }
  167. $options[$key] = $value;
  168. }
  169. if (TRUE === isset($this->arguments['sortByOptionLabel']) && FALSE === empty($this->arguments['sortByOptionLabel'])) {
  170. asort($options);
  171. }
  172. return $options;
  173. }
  174. /**
  175. * Render the option tags.
  176. *
  177. * @param mixed $value Value to check for
  178. * @return boolean TRUE if the value should be marked a s selected; FALSE otherwise
  179. */
  180. protected function isSelected($value) {
  181. $selectedValue = $this->getSelectedValue();
  182. if ($value === $selectedValue || (string) value === $selectedValue) {
  183. return TRUE;
  184. }
  185. if (TRUE === isset($this->arguments['multiple']) && FALSE === empty($this->arguments['multiple'])) {
  186. if (TRUE === is_null($selectedValue) && TRUE === (boolean) $this->arguments['selectAllByDefault']) {
  187. return TRUE;
  188. } elseif (TRUE === is_array($selectedValue) && TRUE === in_array($value, $selectedValue)) {
  189. return TRUE;
  190. }
  191. }
  192. return FALSE;
  193. }
  194. /**
  195. * Retrieves the selected value(s)
  196. *
  197. * @return mixed value string or an array of strings
  198. */
  199. protected function getSelectedValue() {
  200. $value = $this->getValue();
  201. if (FALSE === isset($this->arguments['optionValueField']) || TRUE === empty($this->arguments['optionValueField'])) {
  202. return $value;
  203. }
  204. if (FALSE === is_array($value) && FALSE === ($value instanceof Iterator)) {
  205. if (TRUE === is_object($value)) {
  206. return Tx_Extbase_Reflection_ObjectAccess::getProperty($value, $this->arguments['optionValueField']);
  207. } else {
  208. return $value;
  209. }
  210. }
  211. $selectedValues = array();
  212. foreach ($value as $selectedValueElement) {
  213. if (TRUE === is_object($selectedValueElement)) {
  214. $selectedValues[] = Tx_Extbase_Reflection_ObjectAccess::getProperty($selectedValueElement, $this->arguments['optionValueField']);
  215. } else {
  216. $selectedValues[] = $selectedValueElement;
  217. }
  218. }
  219. return $selectedValues;
  220. }
  221. /**
  222. * Render one option tag
  223. *
  224. * @param string $value value attribute of the option tag (will be escaped)
  225. * @param string $label content of the option tag (will be escaped)
  226. * @param boolean $isSelected specifies wheter or not to add selected attribute
  227. * @return string the rendered option tag
  228. */
  229. protected function renderOptionTag($value, $label, $isSelected) {
  230. $output = '<option value="' . htmlspecialchars($value) . '"';
  231. if (TRUE === (boolean) $isSelected) {
  232. $output .= ' selected="selected"';
  233. }
  234. $output .= '>' . htmlspecialchars($label) . '</option>';
  235. return $output;
  236. }
  237. }