Don't like ads? PRO users don't see any ads ;-)
Guest

Flow3 FLUID SelectViewHelper with Append and Prepend

By: a guest on May 21st, 2012  |  syntax: PHP  |  size: 10.75 KB  |  hits: 47  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. <?php
  2. namespace TYPO3\Fluid\ViewHelpers\Form;
  3.  
  4. /*                                                                        *
  5.  * This script belongs to the FLOW3 package "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. /**
  15.  * Modified by Michel Albers 21.05.2012
  16.  * Added prepend and append arguments
  17.  */
  18.  
  19. /**
  20.  * This view helper generates a <select> dropdown list for the use with a form.
  21.  *
  22.  * = Basic usage =
  23.  *
  24.  * The most straightforward way is to supply an associative array as the "options" parameter.
  25.  * The array key is used as option key, and the value is used as human-readable name.
  26.  *
  27.  * <code title="Basic usage">
  28.  * <f:form.select name="paymentOptions" options="{payPal: 'PayPal International Services', visa: 'VISA Card'}" />
  29.  * </code>
  30.  *
  31.  * = Pre-select a value =
  32.  *
  33.  * To pre-select a value, set "value" to the option key which should be selected.
  34.  * <code title="Default value">
  35.  * <f:form.select name="paymentOptions" options="{payPal: 'PayPal International Services', visa: 'VISA Card'}" value="visa" />
  36.  * </code>
  37.  * Generates a dropdown box like above, except that "VISA Card" is selected.
  38.  *
  39.  * If the select box is a multi-select box (multiple="true"), then "value" can be an array as well.
  40.  *
  41.  * = Usage on domain objects =
  42.  *
  43.  * If you want to output domain objects, you can just pass them as array into the "options" parameter.
  44.  * To define what domain object value should be used as option key, use the "optionValueField" variable. Same goes for optionLabelField.
  45.  * If neither is given, the Identifier (UUID/uid) and the __toString() method are tried as fallbacks.
  46.  *
  47.  * If the optionValueField variable is set, the getter named after that value is used to retrieve the option key.
  48.  * If the optionLabelField variable is set, the getter named after that value is used to retrieve the option value.
  49.  *
  50.  * <code title="Domain objects">
  51.  * <f:form.select name="users" options="{userArray}" optionValueField="id" optionLabelField="firstName" />
  52.  * </code>
  53.  * In the above example, the userArray is an array of "User" domain objects, with no array key specified.
  54.  *
  55.  * 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.
  56.  *
  57.  * The "value" property now expects a domain object, and tests for object equivalence.
  58.  *
  59.  * @api
  60.  */
  61. class TbselectViewHelper extends \TYPO3\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper {
  62.  
  63.         /**
  64.          * @var string
  65.          */
  66.         protected $tagName = 'select';
  67.  
  68.         /**
  69.          * @var mixed
  70.          */
  71.         protected $selectedValue = NULL;
  72.  
  73.         /**
  74.          * Initialize arguments.
  75.          *
  76.          * @return void
  77.          * @api
  78.          */
  79.         public function initializeArguments() {
  80.                 parent::initializeArguments();
  81.                 $this->registerUniversalTagAttributes();
  82.                 $this->registerTagAttribute('multiple', 'string', 'if set, multiple select field');
  83.                 $this->registerTagAttribute('size', 'string', 'Size of input field');
  84.                 $this->registerTagAttribute('disabled', 'string', 'Specifies that the input element should be disabled when the page loads');
  85.                 $this->registerArgument('prepend','array','Values before options list',FALSE);         
  86.                 $this->registerArgument('append','array','Values after options list',FALSE);           
  87.                 $this->registerArgument('options', 'array', 'Associative array with internal IDs as key, and the values are displayed in the select box', TRUE);
  88.                 $this->registerArgument('optionValueField', 'string', 'If specified, will call the appropriate getter on each object to determine the value.');
  89.                 $this->registerArgument('optionLabelField', 'string', 'If specified, will call the appropriate getter on each object to determine the label.');
  90.                 $this->registerArgument('sortByOptionLabel', 'boolean', 'If true, List will be sorted by label.', FALSE, FALSE);
  91.                 $this->registerArgument('selectAllByDefault', 'boolean', 'If specified options are selected if none was set before.', FALSE, FALSE);
  92.                 $this->registerArgument('errorClass', 'string', 'CSS class to set if there are errors for this view helper', FALSE, 'f3-form-error');
  93.         }
  94.  
  95.         /**
  96.          * Render the tag.
  97.          *
  98.          * @return string rendered tag.
  99.          * @api
  100.          */
  101.         public function render() {
  102.                 $name = $this->getName();
  103.                 if ($this->hasArgument('multiple')) {
  104.                         $name .= '[]';
  105.                 }
  106.  
  107.                 $this->tag->addAttribute('name', $name);
  108.  
  109.                 $options = $this->getOptions();
  110.                 if (empty($options)) {
  111.                         $options = array('' => '');
  112.                 }
  113.                 $this->tag->setContent($this->renderOptionTags($options));
  114.  
  115.                 $this->setErrorClassAttribute();
  116.  
  117.                 $content = '';
  118.  
  119.                         // register field name for token generation.
  120.                         // in case it is a multi-select, we need to register the field name
  121.                         // as often as there are elements in the box
  122.                 if ($this->hasArgument('multiple') && $this->arguments['multiple'] !== '') {
  123.                         $content .= $this->renderHiddenFieldForEmptyValue();
  124.                         for ($i=0; $i<count($options); $i++) {
  125.                                 $this->registerFieldNameForFormTokenGeneration($name);
  126.                         }
  127.                 } else {
  128.                         $this->registerFieldNameForFormTokenGeneration($name);
  129.                 }
  130.  
  131.                 $content .= $this->tag->render();
  132.                 return $content;
  133.         }
  134.  
  135.         /**
  136.          * Render the option tags.
  137.          *
  138.          * @param array $options the options for the form.
  139.          * @return string rendered tags.
  140.          */
  141.         protected function renderOptionTags($options) {
  142.                 $output = '';
  143.  
  144.                 foreach ($options as $value => $label) {
  145.                         $isSelected = $this->isSelected($value);
  146.                         $output.= $this->renderOptionTag($value, $label, $isSelected) . chr(10);
  147.                 }
  148.                 return $output;
  149.         }
  150.  
  151.         /**
  152.          * Render the option tags.
  153.          *
  154.          * @return array an associative array of options, key will be the value of the option tag
  155.          */
  156.         protected function getOptions() {
  157.                 if (!is_array($this->arguments['options']) && !($this->arguments['options'] instanceof \Traversable)) {
  158.                         return array();
  159.                 }
  160.                 $options = array();
  161.                 $optionsArgument = $this->arguments['options'];
  162.                 foreach ($optionsArgument as $key => $value) {
  163.                         if (is_object($value)) {
  164.  
  165.                                 if ($this->hasArgument('optionValueField')) {
  166.                                         $key = \TYPO3\FLOW3\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\Fluid\Core\ViewHelper\Exception('Identifying value for object of class "' . get_class($value) . '" was an object.' , 1247827428);
  172.                                                 }
  173.                                         }
  174.                                 } elseif ($this->persistenceManager->getIdentifierByObject($value) !== NULL) {
  175.                                         $key = $this->persistenceManager->getIdentifierByObject($value);
  176.                                 } elseif (method_exists($value, '__toString')) {
  177.                                         $key = (string)$value;
  178.                                 } else {
  179.                                         throw new \TYPO3\Fluid\Core\ViewHelper\Exception('No identifying value for object of class "' . get_class($value) . '" found.' , 1247826696);
  180.                                 }
  181.  
  182.                                 if ($this->hasArgument('optionLabelField')) {
  183.                                         $value = \TYPO3\FLOW3\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\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.                                 } elseif ($this->persistenceManager->getIdentifierByObject($value) !== NULL) {
  194.                                         $value = $this->persistenceManager->getIdentifierByObject($value);
  195.                                 }
  196.                         }
  197.                         $options[$key] = $value;
  198.                 }
  199.                 if ($this->arguments['sortByOptionLabel']) {
  200.                         asort($options);
  201.                 }
  202.                
  203.                 /* Prepend and Append */
  204.                 if(!empty($this->arguments['prepend'])) {
  205.                         $options = array_merge($this->arguments['prepend'],$options);  
  206.                 }
  207.                
  208.                 if(!empty($this->arguments['append'])) {
  209.                         $options = array_merge($options,$this->arguments['append']);
  210.                 }
  211.  
  212.                 return $options;
  213.         }
  214.        
  215.         /**
  216.          * Render the option tags.
  217.          *
  218.          * @param mixed $value Value to check for
  219.          * @return boolean TRUE if the value should be marked a s selected; FALSE otherwise
  220.          */
  221.         protected function isSelected($value) {
  222.                 $selectedValue = $this->getSelectedValue();
  223.                 if ($value === $selectedValue || (string)$value === $selectedValue) {
  224.                         return TRUE;
  225.                 }
  226.                 if ($this->hasArgument('multiple')) {
  227.                         if (is_null($selectedValue) && $this->arguments['selectAllByDefault'] === TRUE) {
  228.                                 return TRUE;
  229.                         } elseif (is_array($selectedValue) && in_array($value, $selectedValue)) {
  230.                                 return TRUE;
  231.                         }
  232.                 }
  233.                 return FALSE;
  234.         }
  235.  
  236.         /**
  237.          * Retrieves the selected value(s)
  238.          *
  239.          * @return mixed value string or an array of strings
  240.          */
  241.         protected function getSelectedValue() {
  242.                 $value = $this->getValue();
  243.                 if (!is_array($value) && !($value instanceof  \Traversable)) {
  244.                         return $this->getOptionValueScalar($value);
  245.                 }
  246.                 $selectedValues = array();
  247.                 foreach($value as $selectedValueElement) {
  248.                         $selectedValues[] = $this->getOptionValueScalar($selectedValueElement);
  249.                 }
  250.                 return $selectedValues;
  251.         }
  252.  
  253.         /**
  254.          * Get the option value for an object
  255.          *
  256.          * @param mixed $valueElement
  257.          * @return string
  258.          */
  259.         protected function getOptionValueScalar($valueElement) {
  260.                 if (is_object($valueElement)) {
  261.                         if ($this->hasArgument('optionValueField')) {
  262.                                 return \TYPO3\FLOW3\Reflection\ObjectAccess::getPropertyPath($valueElement, $this->arguments['optionValueField']);
  263.                         } else if ($this->persistenceManager->getIdentifierByObject($valueElement) !== NULL){
  264.                                 return $this->persistenceManager->getIdentifierByObject($valueElement);
  265.                         } else {
  266.                                 return (string)$valueElement;
  267.                         }
  268.                 } else {
  269.                         return $valueElement;
  270.                 }
  271.         }
  272.  
  273.         /**
  274.          * Render one option tag
  275.          *
  276.          * @param string $value value attribute of the option tag (will be escaped)
  277.          * @param string $label content of the option tag (will be escaped)
  278.          * @param boolean $isSelected specifies wheter or not to add selected attribute
  279.          * @return string the rendered option tag
  280.          */
  281.         protected function renderOptionTag($value, $label, $isSelected) {
  282.                 if($value != "NULL") {
  283.                         $output = '<option value="' . htmlspecialchars($value) . '"';
  284.                 } else {
  285.                         $output = '<option value=""';
  286.                 }
  287.                 if ($isSelected) {
  288.                         $output= ' selected="selected"';
  289.                 }
  290.                 $output.= '>' . htmlspecialchars($label) . '</option>';
  291.  
  292.                 return $output;
  293.         }
  294. }
  295.  
  296. ?>