TYPO3 CMS  TYPO3_7-6
SelectViewHelper.php
Go to the documentation of this file.
1 <?php
3 
4 /* *
5  * This script is backported from the TYPO3 Flow 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  * */
59 {
63  protected $tagName = 'select';
64 
68  protected $selectedValue = null;
69 
76  public function initializeArguments()
77  {
78  parent::initializeArguments();
80  $this->registerTagAttribute('size', 'string', 'Size of input field');
81  $this->registerTagAttribute('disabled', 'string', 'Specifies that the input element should be disabled when the page loads');
82  $this->registerArgument('options', 'array', 'Associative array with internal IDs as key, and the values are displayed in the select box', true);
83  $this->registerArgument('optionValueField', 'string', 'If specified, will call the appropriate getter on each object to determine the value.');
84  $this->registerArgument('optionLabelField', 'string', 'If specified, will call the appropriate getter on each object to determine the label.');
85  $this->registerArgument('sortByOptionLabel', 'boolean', 'If true, List will be sorted by label.', false, false);
86  $this->registerArgument('selectAllByDefault', 'boolean', 'If specified options are selected if none was set before.', false, false);
87  $this->registerArgument('errorClass', 'string', 'CSS class to set if there are errors for this view helper', false, 'f3-form-error');
88  $this->registerArgument('prependOptionLabel', 'string', 'If specified, will provide an option at first position with the specified label.');
89  $this->registerArgument('prependOptionValue', 'string', 'If specified, will provide an option at first position with the specified value.');
90  $this->registerArgument('multiple', 'boolean', 'If set multiple options may be selected.', false, false);
91  }
92 
99  public function render()
100  {
101  $name = $this->getName();
102  if ($this->arguments['multiple']) {
103  $this->tag->addAttribute('multiple', 'multiple');
104  $name .= '[]';
105  }
106  $this->tag->addAttribute('name', $name);
107  $options = $this->getOptions();
108  if (empty($options)) {
109  $options = ['' => ''];
110  }
111  $this->tag->setContent($this->renderOptionTags($options));
113  $this->setErrorClassAttribute();
114  $content = '';
115  // register field name for token generation.
116  // in case it is a multi-select, we need to register the field name
117  // as often as there are elements in the box
118  if ($this->arguments['multiple']) {
119  $content .= $this->renderHiddenFieldForEmptyValue();
120  for ($i = 0; $i < count($options); $i++) {
122  }
123  } else {
125  }
126  $content .= $this->tag->render();
127  return $content;
128  }
129 
136  protected function renderOptionTags($options)
137  {
138  $output = '';
139  if ($this->hasArgument('prependOptionLabel')) {
140  $value = $this->hasArgument('prependOptionValue') ? $this->arguments['prependOptionValue'] : '';
141  $label = $this->arguments['prependOptionLabel'];
142  $output .= $this->renderOptionTag($value, $label, false) . LF;
143  }
144  foreach ($options as $value => $label) {
145  $isSelected = $this->isSelected($value);
146  $output .= $this->renderOptionTag($value, $label, $isSelected) . LF;
147  }
148  return $output;
149  }
150 
156  protected function getOptions()
157  {
158  if (!is_array($this->arguments['options']) && !$this->arguments['options'] instanceof \Traversable) {
159  return [];
160  }
161  $options = [];
162  $optionsArgument = $this->arguments['options'];
163  foreach ($optionsArgument as $key => $value) {
164  if (is_object($value) || is_array($value)) {
165  if ($this->hasArgument('optionValueField')) {
166  $key = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getPropertyPath($value, $this->arguments['optionValueField']);
167  if (is_object($key)) {
168  if (method_exists($key, '__toString')) {
169  $key = (string)$key;
170  } else {
171  throw new \TYPO3\CMS\Fluid\Core\ViewHelper\Exception('Identifying value for object of class "' . get_class($value) . '" was an object.', 1247827428);
172  }
173  }
174  // @todo use $this->persistenceManager->isNewObject() once it is implemented
175  } elseif ($this->persistenceManager->getIdentifierByObject($value) !== null) {
176  $key = $this->persistenceManager->getIdentifierByObject($value);
177  } elseif (method_exists($value, '__toString')) {
178  $key = (string)$value;
179  } else {
180  throw new \TYPO3\CMS\Fluid\Core\ViewHelper\Exception('No identifying value for object of class "' . get_class($value) . '" found.', 1247826696);
181  }
182  if ($this->hasArgument('optionLabelField')) {
183  $value = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getPropertyPath($value, $this->arguments['optionLabelField']);
184  if (is_object($value)) {
185  if (method_exists($value, '__toString')) {
186  $value = (string)$value;
187  } else {
188  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);
189  }
190  }
191  } elseif (method_exists($value, '__toString')) {
192  $value = (string)$value;
193  // @todo use $this->persistenceManager->isNewObject() once it is implemented
194  } elseif ($this->persistenceManager->getIdentifierByObject($value) !== null) {
195  $value = $this->persistenceManager->getIdentifierByObject($value);
196  }
197  }
198  $options[$key] = $value;
199  }
200  if ($this->arguments['sortByOptionLabel']) {
201  asort($options, SORT_LOCALE_STRING);
202  }
203  return $options;
204  }
205 
212  protected function isSelected($value)
213  {
214  $selectedValue = $this->getSelectedValue();
215  if ($value === $selectedValue || (string)$value === $selectedValue) {
216  return true;
217  }
218  if ($this->hasArgument('multiple')) {
219  if (is_null($selectedValue) && $this->arguments['selectAllByDefault'] === true) {
220  return true;
221  } elseif (is_array($selectedValue) && in_array($value, $selectedValue)) {
222  return true;
223  }
224  }
225  return false;
226  }
227 
233  protected function getSelectedValue()
234  {
235  $this->setRespectSubmittedDataValue(true);
236  $value = $this->getValueAttribute();
237  if (!is_array($value) && !$value instanceof \Traversable) {
238  return $this->getOptionValueScalar($value);
239  }
240  $selectedValues = [];
241  foreach ($value as $selectedValueElement) {
242  $selectedValues[] = $this->getOptionValueScalar($selectedValueElement);
243  }
244  return $selectedValues;
245  }
246 
253  protected function getOptionValueScalar($valueElement)
254  {
255  if (is_object($valueElement)) {
256  if ($this->hasArgument('optionValueField')) {
257  return \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getPropertyPath($valueElement, $this->arguments['optionValueField']);
258  } else {
259  // @todo use $this->persistenceManager->isNewObject() once it is implemented
260  if ($this->persistenceManager->getIdentifierByObject($valueElement) !== null) {
261  return $this->persistenceManager->getIdentifierByObject($valueElement);
262  } else {
263  return (string)$valueElement;
264  }
265  }
266  } else {
267  return $valueElement;
268  }
269  }
270 
279  protected function renderOptionTag($value, $label, $isSelected)
280  {
281  $output = '<option value="' . htmlspecialchars($value) . '"';
282  if ($isSelected) {
283  $output .= ' selected="selected"';
284  }
285  $output .= '>' . htmlspecialchars($label) . '</option>';
286  return $output;
287  }
288 }
registerArgument($name, $type, $description, $required=false, $defaultValue=null)
registerTagAttribute($name, $type, $description, $required=false, $default=null)
static getPropertyPath($subject, $propertyPath)