TYPO3 API  SVNRelease
SelectViewHelper.php
Go to the documentation of this file.
00001 <?php
00002 
00003 /*                                                                        *
00004  * This script belongs to the FLOW3 package "Fluid".                      *
00005  *                                                                        *
00006  * It is free software; you can redistribute it and/or modify it under    *
00007  * the terms of the GNU Lesser General Public License as published by the *
00008  * Free Software Foundation, either version 3 of the License, or (at your *
00009  * option) any later version.                                             *
00010  *                                                                        *
00011  * This script is distributed in the hope that it will be useful, but     *
00012  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
00013  * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser       *
00014  * General Public License for more details.                               *
00015  *                                                                        *
00016  * You should have received a copy of the GNU Lesser General Public       *
00017  * License along with the script.                                         *
00018  * If not, see http://www.gnu.org/licenses/lgpl.html                      *
00019  *                                                                        *
00020  * The TYPO3 project - inspiring people to share!                         *
00021  *                                                                        */
00022 
00023 /**
00024  * This view helper generates a <select> dropdown list for the use with a form.
00025  *
00026  * = Basic usage =
00027  *
00028  * The most straightforward way is to supply an associative array as the "options" parameter.
00029  * The array key is used as option key, and the value is used as human-readable name.
00030  *
00031  * <code title="Basic usage">
00032  * <f:form.select name="paymentOptions" options="{payPal: 'PayPal International Services', visa: 'VISA Card'}" />
00033  * </code>
00034  *
00035  * = Pre-select a value =
00036  *
00037  * To pre-select a value, set "value" to the option key which should be selected.
00038  * <code title="Default value">
00039  * <f:form.select name="paymentOptions" options="{payPal: 'PayPal International Services', visa: 'VISA Card'}" value="visa" />
00040  * </code>
00041  * Generates a dropdown box like above, except that "VISA Card" is selected.
00042  *
00043  * If the select box is a multi-select box (multiple="true"), then "value" can be an array as well.
00044  *
00045  * = Usage on domain objects =
00046  *
00047  * If you want to output domain objects, you can just pass them as array into the "options" parameter.
00048  * To define what domain object value should be used as option key, use the "optionValueField" variable. Same goes for optionLabelField.
00049  * If neither is given, the Identifier (UID/uid) and the __toString() method are tried as fallbacks.
00050  *
00051  * If the optionValueField variable is set, the getter named after that value is used to retrieve the option key.
00052  * If the optionLabelField variable is set, the getter named after that value is used to retrieve the option value.
00053  *
00054  * <code title="Domain objects">
00055  * <f:form.select name="users" options="{userArray}" optionValueField="id" optionLabelField="firstName" />
00056  * </code>
00057  * In the above example, the userArray is an array of "User" domain objects, with no array key specified.
00058  *
00059  * 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.
00060  *
00061  * The "value" property now expects a domain object, and tests for object equivalence.
00062  *
00063  * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
00064  * @api
00065  */
00066 class Tx_Fluid_ViewHelpers_Form_SelectViewHelper extends Tx_Fluid_ViewHelpers_Form_AbstractFormFieldViewHelper {
00067 
00068     /**
00069      * @var string
00070      */
00071     protected $tagName = 'select';
00072 
00073     /**
00074      * @var mixed the selected value
00075      */
00076     protected $selectedValue = NULL;
00077 
00078     /**
00079      * Initialize arguments.
00080      *
00081      * @return void
00082      * @author Sebastian Kurfürst <sebastian@typo3.org>
00083      * @api
00084      */
00085     public function initializeArguments() {
00086         parent::initializeArguments();
00087         $this->registerUniversalTagAttributes();
00088         $this->registerTagAttribute('multiple', 'string', 'if set, multiple select field');
00089         $this->registerTagAttribute('size', 'string', 'Size of input field');
00090         $this->registerTagAttribute('disabled', 'string', 'Specifies that the input element should be disabled when the page loads');
00091         $this->registerArgument('options', 'array', 'Associative array with internal IDs as key, and the values are displayed in the select box', TRUE);
00092         $this->registerArgument('optionValueField', 'string', 'If specified, will call the appropriate getter on each object to determine the value.');
00093         $this->registerArgument('optionLabelField', 'string', 'If specified, will call the appropriate getter on each object to determine the label.');
00094         $this->registerArgument('sortByOptionLabel', 'boolean', 'If true, List will be sorted by label.', FALSE, FALSE);
00095         $this->registerArgument('selectAllByDefault', 'boolean', 'If specified options are selected if none was set before.', FALSE, FALSE);
00096         $this->registerArgument('errorClass', 'string', 'CSS class to set if there are errors for this view helper', FALSE, 'f3-form-error');
00097     }
00098 
00099     /**
00100      * Render the tag.
00101      *
00102      * @return string rendered tag.
00103      * @author Sebastian Kurfürst <sebastian@typo3.org>
00104      * @author Bastian Waidelich <bastian@typo3.org>
00105      * @api
00106      */
00107     public function render() {
00108         $name = $this->getName();
00109         if ($this->arguments->hasArgument('multiple')) {
00110             $name .= '[]';
00111         }
00112 
00113         $this->tag->addAttribute('name', $name);
00114 
00115         $options = $this->getOptions();
00116         if (empty($options)) {
00117             $options = array('' => '');
00118         }
00119         $this->tag->setContent($this->renderOptionTags($options));
00120 
00121         $this->setErrorClassAttribute();
00122 
00123         $content = '';
00124 
00125             // register field name for token generation.
00126             // in case it is a multi-select, we need to register the field name
00127             // as often as there are elements in the box
00128         if ($this->arguments->hasArgument('multiple') && $this->arguments['multiple'] !== '') {
00129             $content .= $this->renderHiddenFieldForEmptyValue();
00130             for ($i=0; $i<count($options); $i++) {
00131                 $this->registerFieldNameForFormTokenGeneration($name);
00132             }
00133         } else {
00134             $this->registerFieldNameForFormTokenGeneration($name);
00135         }
00136 
00137         $content .= $this->tag->render();
00138         return $content;
00139     }
00140 
00141     /**
00142      * Render the option tags.
00143      *
00144      * @param array $options the options for the form.
00145      * @return string rendered tags.
00146      * @author Bastian Waidelich <bastian@typo3.org>
00147      */
00148     protected function renderOptionTags($options) {
00149         $output = '';
00150 
00151         foreach ($options as $value => $label) {
00152             $isSelected = $this->isSelected($value);
00153             $output.= $this->renderOptionTag($value, $label, $isSelected) . chr(10);
00154         }
00155         return $output;
00156     }
00157 
00158     /**
00159      * Render the option tags.
00160      *
00161      * @return array an associative array of options, key will be the value of the option tag
00162      * @author Bastian Waidelich <bastian@typo3.org>
00163      * @author Karsten Dambekalns <karsten@typo3.org>
00164      */
00165     protected function getOptions() {
00166         if (!is_array($this->arguments['options']) && !($this->arguments['options'] instanceof Traversable)) {
00167             return array();
00168         }
00169         $options = array();
00170         $optionsArgument = $this->arguments['options'];
00171         foreach ($optionsArgument as $key => $value) {
00172             if (is_object($value)) {
00173 
00174                 if ($this->arguments->hasArgument('optionValueField')) {
00175                     $key = Tx_Extbase_Reflection_ObjectAccess::getProperty($value, $this->arguments['optionValueField']);
00176                     if (is_object($key)) {
00177                         if (method_exists($key, '__toString')) {
00178                             $key = (string)$key;
00179                         } else {
00180                             throw new Tx_Fluid_Core_ViewHelper_Exception('Identifying value for object of class "' . get_class($value) . '" was an object.' , 1247827428);
00181                         }
00182                     }
00183                 } elseif ($this->persistenceManager->getBackend()->getIdentifierByObject($value) !== NULL) {
00184                     $key = $this->persistenceManager->getBackend()->getIdentifierByObject($value);
00185                 } elseif (method_exists($value, '__toString')) {
00186                     $key = (string)$value;
00187                 } else {
00188                     throw new Tx_Fluid_Core_ViewHelper_Exception('No identifying value for object of class "' . get_class($value) . '" found.' , 1247826696);
00189                 }
00190 
00191                 if ($this->arguments->hasArgument('optionLabelField')) {
00192                     $value = Tx_Extbase_Reflection_ObjectAccess::getProperty($value, $this->arguments['optionLabelField']);
00193                     if (is_object($value)) {
00194                         if (method_exists($value, '__toString')) {
00195                             $value = (string)$value;
00196                         } else {
00197                             throw new Tx_Fluid_Core_ViewHelper_Exception('Label value for object of class "' . get_class($value) . '" was an object without a __toString() method.' , 1247827553);
00198                         }
00199                     }
00200                 } elseif (method_exists($value, '__toString')) {
00201                     $value = (string)$value;
00202                 } elseif ($this->persistenceManager->getBackend()->getIdentifierByObject($value) !== NULL) {
00203                     $value = $this->persistenceManager->getBackend()->getIdentifierByObject($value);
00204                 }
00205             }
00206             $options[$key] = $value;
00207         }
00208         if ($this->arguments['sortByOptionLabel']) {
00209             asort($options);
00210         }
00211         return $options;
00212     }
00213 
00214     /**
00215      * Render the option tags.
00216      *
00217      * @return boolean TRUE if the value should be marked a s selected; FALSE otherwise
00218      * @author Bastian Waidelich <bastian@typo3.org>
00219      * @author Jochen Rau <jochen.rau@typoplanet.de>
00220      */
00221     protected function isSelected($value) {
00222         $selectedValue = $this->getSelectedValue();
00223         if ($value === $selectedValue || (string)$value === $selectedValue) {
00224             return TRUE;
00225         }
00226         if ($this->arguments->hasArgument('multiple')) {
00227             if (is_null($selectedValue) && $this->arguments['selectAllByDefault'] === TRUE) {
00228                 return TRUE;
00229             } elseif (is_array($selectedValue) && in_array($value, $selectedValue)) {
00230                 return TRUE;
00231             }
00232         }
00233         return FALSE;
00234     }
00235 
00236     /**
00237      * Retrieves the selected value(s)
00238      *
00239      * @return mixed value string or an array of strings
00240      * @author Bastian Waidelich <bastian@typo3.org>
00241      */
00242     protected function getSelectedValue() {
00243         $value = $this->getValue();
00244         if (!$this->arguments->hasArgument('optionValueField')) {
00245             return $value;
00246         }
00247         if (!is_array($value) && !($value instanceof Iterator)) {
00248             if (is_object($value)) {
00249                 return Tx_Extbase_Reflection_ObjectAccess::getProperty($value, $this->arguments['optionValueField']);
00250             } else {
00251                 return $value;
00252             }
00253         }
00254         $selectedValues = array();
00255         foreach($value as $selectedValueElement) {
00256             if (is_object($selectedValueElement)) {
00257                 $selectedValues[] = Tx_Extbase_Reflection_ObjectAccess::getProperty($selectedValueElement, $this->arguments['optionValueField']);
00258             } else {
00259                 $selectedValues[] = $selectedValueElement;
00260             }
00261         }
00262         return $selectedValues;
00263     }
00264 
00265     /**
00266      * Render one option tag
00267      *
00268      * @param string $value value attribute of the option tag (will be escaped)
00269      * @param string $label content of the option tag (will be escaped)
00270      * @param boolean $isSelected specifies wheter or not to add selected attribute
00271      * @return string the rendered option tag
00272      * @author Bastian Waidelich <bastian@typo3.org>
00273      */
00274     protected function renderOptionTag($value, $label, $isSelected) {
00275         $output = '<option value="' . htmlspecialchars($value) . '"';
00276         if ($isSelected) {
00277             $output.= ' selected="selected"';
00278         }
00279         $output.= '>' . htmlspecialchars($label) . '</option>';
00280 
00281         return $output;
00282     }
00283 }
00284 
00285 ?>