[!!!][TASK] TCA: Remove wizard _HIDDENFIELD and hideParent
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Form / Element / SelectSingleBoxElement.php
1 <?php
2 namespace TYPO3\CMS\Backend\Form\Element;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Utility\GeneralUtility;
18 use TYPO3\CMS\Core\Utility\MathUtility;
19 use TYPO3\CMS\Backend\Utility\IconUtility;
20 use TYPO3\CMS\Backend\Utility\BackendUtility;
21 use TYPO3\CMS\Backend\Form\Utility\FormEngineUtility;
22
23 /**
24 * Create a widget with a select box where multiple items can be selected
25 *
26 * This is rendered for config type=select, maxitems > 1, renderMode=singlebox
27 */
28 class SelectSingleBoxElement extends AbstractFormElement {
29
30 /**
31 * @var array Result array given returned by render() - This property is a helper until class is properly refactored
32 */
33 protected $resultArray = array();
34
35 /**
36 * This will render a selector box element, or possibly a special construction with two selector boxes.
37 *
38 * @return array As defined in initializeResultArray() of AbstractNode
39 */
40 public function render() {
41 $table = $this->globalOptions['table'];
42 $field = $this->globalOptions['fieldName'];
43 $row = $this->globalOptions['databaseRow'];
44 $parameterArray = $this->globalOptions['parameterArray'];
45 // Field configuration from TCA:
46 $config = $parameterArray['fieldConf']['config'];
47 $disabled = '';
48 if ($this->isGlobalReadonly() || $config['readOnly']) {
49 $disabled = ' disabled="disabled"';
50 }
51 $this->resultArray = $this->initializeResultArray();
52 // "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist.
53 $specConf = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
54 $selItems = FormEngineUtility::getSelectItems($table, $field, $row, $parameterArray);
55
56 // Creating the label for the "No Matching Value" entry.
57 $noMatchingLabel = isset($parameterArray['fieldTSConfig']['noMatchingValue_label'])
58 ? $this->getLanguageService()->sL($parameterArray['fieldTSConfig']['noMatchingValue_label'])
59 : '[ ' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.noMatchingValue') . ' ]';
60
61 $html = $this->getSingleField_typeSelect_singlebox($table, $field, $row, $parameterArray, $config, $selItems, $noMatchingLabel);
62
63 // Wizards:
64 if (!$disabled) {
65 $html = $this->renderWizards(array($html), $config['wizards'], $table, $row, $field, $parameterArray, $parameterArray['itemFormElName'], $specConf);
66 }
67 $this->resultArray['html'] = $html;
68 return $this->resultArray;
69 }
70
71 /**
72 * Creates a selectorbox list (renderMode = "singlebox")
73 *
74 * @param string $table See getSingleField_typeSelect()
75 * @param string $field See getSingleField_typeSelect()
76 * @param array $row See getSingleField_typeSelect()
77 * @param array $parameterArray See getSingleField_typeSelect()
78 * @param array $config (Redundant) content of $PA['fieldConf']['config'] (for convenience)
79 * @param array $selItems Items available for selection
80 * @param string $noMatchingLabel Label for no-matching-value
81 * @return string The HTML code for the item
82 */
83 protected function getSingleField_typeSelect_singlebox($table, $field, $row, $parameterArray, $config, $selItems, $noMatchingLabel) {
84 $languageService = $this->getLanguageService();
85 // Get values in an array (and make unique, which is fine because there can be no duplicates anyway):
86 $itemArray = array_flip(FormEngineUtility::extractValuesOnlyFromValueLabelList($parameterArray['itemFormElValue']));
87 $item = '';
88 $disabled = '';
89 if ($this->isGlobalReadonly() || $config['readOnly']) {
90 $disabled = ' disabled="disabled"';
91 }
92 // Traverse the Array of selector box items:
93 $opt = array();
94 // Used to accumulate the JS needed to restore the original selection.
95 $restoreCmd = array();
96 $c = 0;
97 foreach ($selItems as $p) {
98 // Selected or not by default:
99 $sM = '';
100 if (isset($itemArray[$p[1]])) {
101 $sM = ' selected="selected"';
102 $restoreCmd[] = 'document.editform[' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName'] . '[]') . '].options[' . $c . '].selected=1;';
103 unset($itemArray[$p[1]]);
104 }
105 // Non-selectable element:
106 $nonSel = '';
107 if ((string)$p[1] === '--div--') {
108 $nonSel = ' onclick="this.selected=0;" class="formcontrol-select-divider"';
109 }
110 // Icon style for option tag:
111 $styleAttrValue = '';
112 if ($config['iconsInOptionTags']) {
113 $styleAttrValue = FormEngineUtility::optionTagStyle($p[2]);
114 }
115 // Compile <option> tag:
116 $opt[] = '<option value="' . htmlspecialchars($p[1]) . '"' . $sM . $nonSel
117 . ($styleAttrValue ? ' style="' . htmlspecialchars($styleAttrValue) . '"' : '') . '>'
118 . htmlspecialchars($p[0], ENT_COMPAT, 'UTF-8', FALSE) . '</option>';
119 $c++;
120 }
121 // Remaining values:
122 if (!empty($itemArray) && !$parameterArray['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) {
123 foreach ($itemArray as $theNoMatchValue => $temp) {
124 // Compile <option> tag:
125 array_unshift($opt, '<option value="' . htmlspecialchars($theNoMatchValue) . '" selected="selected">'
126 . htmlspecialchars(@sprintf($noMatchingLabel, $theNoMatchValue), ENT_COMPAT, 'UTF-8', FALSE) . '</option>');
127 }
128 }
129 // Compile selector box:
130 $sOnChange = implode('', $parameterArray['fieldChangeFunc']);
131 $selector_itemListStyle = isset($config['itemListStyle'])
132 ? ' style="' . htmlspecialchars($config['itemListStyle']) . '"'
133 : '';
134 $size = (int)$config['size'];
135 $cssPrefix = $size === 1 ? 'tceforms-select' : 'tceforms-multiselect';
136 $size = $config['autoSizeMax']
137 ? MathUtility::forceIntegerInRange(count($selItems) + 1, MathUtility::forceIntegerInRange($size, 1), $config['autoSizeMax'])
138 : $size;
139 $selectBox = '<select id="' . str_replace('.', '', uniqid($cssPrefix, TRUE)) . '" name="' . htmlspecialchars($parameterArray['itemFormElName']) . '[]" '
140 . 'class="form-control ' . $cssPrefix . '"' . ($size ? ' size="' . $size . '" ' : '')
141 . ' multiple="multiple" onchange="' . htmlspecialchars($sOnChange) . '"' . $parameterArray['onFocus']
142 . ' ' . $this->getValidationDataAsDataAttribute($config) . $selector_itemListStyle . $disabled . '>
143 ' . implode('
144 ', $opt) . '
145 </select>';
146 // Add an empty hidden field which will send a blank value if all items are unselected.
147 if (!$disabled) {
148 $item .= '<input type="hidden" name="' . htmlspecialchars($parameterArray['itemFormElName']) . '" value="" />';
149 }
150 // Put it all into a table:
151 $onClick = htmlspecialchars('document.editform[' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName'] . '[]') . '].selectedIndex=-1;' . implode('', $restoreCmd) . ' return false;');
152 $width = $this->formMaxWidth($this->defaultInputWidth);
153 $item .= '
154 <div class="form-control-wrap" ' . ($width ? ' style="max-width: ' . $width . 'px"' : '') . '>
155 <div class="form-wizards-wrap form-wizards-aside">
156 <div class="form-wizards-element">
157 ' . $selectBox . '
158 </div>
159 <div class="form-wizards-items">
160 <a href="#" class="btn btn-default" onclick="' . $onClick . '" title="' . htmlspecialchars($languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.revertSelection')) . '">'
161 . IconUtility::getSpriteIcon('actions-edit-undo') . '</a>
162 </div>
163 </div>
164 </div>
165 <p>
166 <em>' . htmlspecialchars($languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.holdDownCTRL')) . '</em>
167 </p>
168 ';
169 return $item;
170 }
171
172 }