[TASK] Remove superfluous parenthesis in sysexts
[Packages/TYPO3.CMS.git] / typo3 / sysext / fluid / Classes / ViewHelpers / Form / SelectViewHelper.php
1 <?php
2 namespace TYPO3\CMS\Fluid\ViewHelpers\Form;
3
4 /* *
5 * This script is backported from the FLOW3 package "TYPO3.Fluid". *
6 * *
7 * It is free software; you can redistribute it and/or modify it under *
8 * the terms of the GNU Lesser General Public License, either version 3 *
9 * of the License, or (at your option) any later version. *
10 * *
11 * The TYPO3 project - inspiring people to share! *
12 * */
13 /**
14 * This view helper generates a <select> dropdown list for the use with a form.
15 *
16 * = Basic usage =
17 *
18 * The most straightforward way is to supply an associative array as the "options" parameter.
19 * The array key is used as option key, and the value is used as human-readable name.
20 *
21 * <code title="Basic usage">
22 * <f:form.select name="paymentOptions" options="{payPal: 'PayPal International Services', visa: 'VISA Card'}" />
23 * </code>
24 *
25 * = Pre-select a value =
26 *
27 * To pre-select a value, set "value" to the option key which should be selected.
28 * <code title="Default value">
29 * <f:form.select name="paymentOptions" options="{payPal: 'PayPal International Services', visa: 'VISA Card'}" value="visa" />
30 * </code>
31 * Generates a dropdown box like above, except that "VISA Card" is selected.
32 *
33 * If the select box is a multi-select box (multiple="true"), then "value" can be an array as well.
34 *
35 * = Usage on domain objects =
36 *
37 * If you want to output domain objects, you can just pass them as array into the "options" parameter.
38 * To define what domain object value should be used as option key, use the "optionValueField" variable. Same goes for optionLabelField.
39 * If neither is given, the Identifier (UID/uid) and the __toString() method are tried as fallbacks.
40 *
41 * If the optionValueField variable is set, the getter named after that value is used to retrieve the option key.
42 * If the optionLabelField variable is set, the getter named after that value is used to retrieve the option value.
43 *
44 * <code title="Domain objects">
45 * <f:form.select name="users" options="{userArray}" optionValueField="id" optionLabelField="firstName" />
46 * </code>
47 * In the above example, the userArray is an array of "User" domain objects, with no array key specified.
48 *
49 * So, in the above example, the method $user->getId() is called to retrieve the key, and $user->getFirstName() to retrieve the displayed value of each entry.
50 *
51 * The "value" property now expects a domain object, and tests for object equivalence.
52 *
53 * @api
54 */
55 class SelectViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper {
56
57 /**
58 * @var string
59 */
60 protected $tagName = 'select';
61
62 /**
63 * @var mixed
64 */
65 protected $selectedValue = NULL;
66
67 /**
68 * Initialize arguments.
69 *
70 * @return void
71 * @api
72 */
73 public function initializeArguments() {
74 parent::initializeArguments();
75 $this->registerUniversalTagAttributes();
76 $this->registerTagAttribute('multiple', 'string', 'if set, multiple select field');
77 $this->registerTagAttribute('size', 'string', 'Size of input field');
78 $this->registerTagAttribute('disabled', 'string', 'Specifies that the input element should be disabled when the page loads');
79 $this->registerArgument('options', 'array', 'Associative array with internal IDs as key, and the values are displayed in the select box', TRUE);
80 $this->registerArgument('optionValueField', 'string', 'If specified, will call the appropriate getter on each object to determine the value.');
81 $this->registerArgument('optionLabelField', 'string', 'If specified, will call the appropriate getter on each object to determine the label.');
82 $this->registerArgument('sortByOptionLabel', 'boolean', 'If true, List will be sorted by label.', FALSE, FALSE);
83 $this->registerArgument('selectAllByDefault', 'boolean', 'If specified options are selected if none was set before.', FALSE, FALSE);
84 $this->registerArgument('errorClass', 'string', 'CSS class to set if there are errors for this view helper', FALSE, 'f3-form-error');
85 }
86
87 /**
88 * Render the tag.
89 *
90 * @return string rendered tag.
91 * @api
92 */
93 public function render() {
94 $name = $this->getName();
95 if ($this->hasArgument('multiple')) {
96 $name .= '[]';
97 }
98 $this->tag->addAttribute('name', $name);
99 $options = $this->getOptions();
100 if (empty($options)) {
101 $options = array('' => '');
102 }
103 $this->tag->setContent($this->renderOptionTags($options));
104 $this->setErrorClassAttribute();
105 $content = '';
106 // register field name for token generation.
107 // in case it is a multi-select, we need to register the field name
108 // as often as there are elements in the box
109 if ($this->hasArgument('multiple') && $this->arguments['multiple'] !== '') {
110 $content .= $this->renderHiddenFieldForEmptyValue();
111 for ($i = 0; $i < count($options); $i++) {
112 $this->registerFieldNameForFormTokenGeneration($name);
113 }
114 } else {
115 $this->registerFieldNameForFormTokenGeneration($name);
116 }
117 $content .= $this->tag->render();
118 return $content;
119 }
120
121 /**
122 * Render the option tags.
123 *
124 * @param array $options the options for the form.
125 * @return string rendered tags.
126 */
127 protected function renderOptionTags($options) {
128 $output = '';
129 foreach ($options as $value => $label) {
130 $isSelected = $this->isSelected($value);
131 $output .= $this->renderOptionTag($value, $label, $isSelected) . chr(10);
132 }
133 return $output;
134 }
135
136 /**
137 * Render the option tags.
138 *
139 * @return array an associative array of options, key will be the value of the option tag
140 */
141 protected function getOptions() {
142 if (!is_array($this->arguments['options']) && !$this->arguments['options'] instanceof \Traversable) {
143 return array();
144 }
145 $options = array();
146 $optionsArgument = $this->arguments['options'];
147 foreach ($optionsArgument as $key => $value) {
148 if (is_object($value)) {
149 if ($this->hasArgument('optionValueField')) {
150 $key = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getPropertyPath($value, $this->arguments['optionValueField']);
151 if (is_object($key)) {
152 if (method_exists($key, '__toString')) {
153 $key = (string) $key;
154 } else {
155 throw new \TYPO3\CMS\Fluid\Core\ViewHelper\Exception('Identifying value for object of class "' . get_class($value) . '" was an object.', 1247827428);
156 }
157 }
158 } elseif ($this->persistenceManager->getBackend()->getIdentifierByObject($value) !== NULL) {
159 $key = $this->persistenceManager->getBackend()->getIdentifierByObject($value);
160 } elseif (method_exists($value, '__toString')) {
161 $key = (string) $value;
162 } else {
163 throw new \TYPO3\CMS\Fluid\Core\ViewHelper\Exception('No identifying value for object of class "' . get_class($value) . '" found.', 1247826696);
164 }
165 if ($this->hasArgument('optionLabelField')) {
166 $value = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getPropertyPath($value, $this->arguments['optionLabelField']);
167 if (is_object($value)) {
168 if (method_exists($value, '__toString')) {
169 $value = (string) $value;
170 } else {
171 throw new \TYPO3\CMS\Fluid\Core\ViewHelper\Exception('Label value for object of class "' . get_class($value) . '" was an object without a __toString() method.', 1247827553);
172 }
173 }
174 } elseif (method_exists($value, '__toString')) {
175 $value = (string) $value;
176 } elseif ($this->persistenceManager->getBackend()->getIdentifierByObject($value) !== NULL) {
177 $value = $this->persistenceManager->getBackend()->getIdentifierByObject($value);
178 }
179 }
180 $options[$key] = $value;
181 }
182 if ($this->arguments['sortByOptionLabel']) {
183 asort($options);
184 }
185 return $options;
186 }
187
188 /**
189 * Render the option tags.
190 *
191 * @param mixed $value Value to check for
192 * @return boolean TRUE if the value should be marked a s selected; FALSE otherwise
193 */
194 protected function isSelected($value) {
195 $selectedValue = $this->getSelectedValue();
196 if ($value === $selectedValue || (string) $value === $selectedValue) {
197 return TRUE;
198 }
199 if ($this->hasArgument('multiple')) {
200 if (is_null($selectedValue) && $this->arguments['selectAllByDefault'] === TRUE) {
201 return TRUE;
202 } elseif (is_array($selectedValue) && in_array($value, $selectedValue)) {
203 return TRUE;
204 }
205 }
206 return FALSE;
207 }
208
209 /**
210 * Retrieves the selected value(s)
211 *
212 * @return mixed value string or an array of strings
213 */
214 protected function getSelectedValue() {
215 $value = $this->getValue();
216 if (!is_array($value) && !$value instanceof \Traversable) {
217 return $this->getOptionValueScalar($value);
218 }
219 $selectedValues = array();
220 foreach ($value as $selectedValueElement) {
221 $selectedValues[] = $this->getOptionValueScalar($selectedValueElement);
222 }
223 return $selectedValues;
224 }
225
226 /**
227 * Get the option value for an object
228 *
229 * @param mixed $valueElement
230 * @return string
231 */
232 protected function getOptionValueScalar($valueElement) {
233 if (is_object($valueElement)) {
234 if ($this->hasArgument('optionValueField')) {
235 return \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getPropertyPath($valueElement, $this->arguments['optionValueField']);
236 } else {
237 if ($this->persistenceManager->getBackend()->getIdentifierByObject($valueElement) !== NULL) {
238 return $this->persistenceManager->getBackend()->getIdentifierByObject($valueElement);
239 } else {
240 return (string) $valueElement;
241 }
242 }
243 } else {
244 return $valueElement;
245 }
246 }
247
248 /**
249 * Render one option tag
250 *
251 * @param string $value value attribute of the option tag (will be escaped)
252 * @param string $label content of the option tag (will be escaped)
253 * @param boolean $isSelected specifies wheter or not to add selected attribute
254 * @return string the rendered option tag
255 */
256 protected function renderOptionTag($value, $label, $isSelected) {
257 $output = '<option value="' . htmlspecialchars($value) . '"';
258 if ($isSelected) {
259 $output .= ' selected="selected"';
260 }
261 $output .= '>' . htmlspecialchars($label) . '</option>';
262 return $output;
263 }
264
265 }
266
267
268 ?>