8beb33bd69e74b08d7dee219201d7756dccf9375
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Form / Element / SelectMultipleSideBySideElement.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\Backend\Utility\BackendUtility;
18 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
19 use TYPO3\CMS\Core\Utility\MathUtility;
20 use TYPO3\CMS\Core\Utility\StringUtility;
21
22 /**
23 * Render a widget with two boxes side by side.
24 *
25 * This is rendered for config type=select, maxitems > 1, renderType=selectMultipleSideBySide set
26 */
27 class SelectMultipleSideBySideElement extends AbstractFormElement
28 {
29 /**
30 * Render side by side element.
31 *
32 * @return array As defined in initializeResultArray() of AbstractNode
33 */
34 public function render()
35 {
36 $table = $this->data['tableName'];
37 $field = $this->data['fieldName'];
38 $parameterArray = $this->data['parameterArray'];
39 // Field configuration from TCA:
40 $config = $parameterArray['fieldConf']['config'];
41
42 // Creating the label for the "No Matching Value" entry.
43 $noMatchingLabel = isset($parameterArray['fieldTSConfig']['noMatchingValue_label'])
44 ? $this->getLanguageService()->sL(trim($parameterArray['fieldTSConfig']['noMatchingValue_label']))
45 : '[ ' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.noMatchingValue') . ' ]';
46
47 $selItems = $config['items'];
48 $html = '';
49 $disabled = '';
50 if ($config['readOnly']) {
51 $disabled = ' disabled="disabled"';
52 }
53 // Setting this hidden field (as a flag that JavaScript can read out)
54 if (!$disabled) {
55 $html .= '<input type="hidden" data-formengine-input-name="' . htmlspecialchars($parameterArray['itemFormElName']) . '" value="' . ($config['multiple'] ? 1 : 0) . '" />';
56 }
57 // Set max and min items:
58 $maxitems = MathUtility::forceIntegerInRange($config['maxitems'], 0);
59 if (!$maxitems) {
60 $maxitems = 100000;
61 }
62 // Get the array with selected items:
63 $itemsArray = $parameterArray['itemFormElValue'] ?: [];
64
65 // Perform modification of the selected items array:
66 foreach ($itemsArray as $itemNumber => $itemValue) {
67 $itemArray = array(
68 0 => $itemValue,
69 1 => '',
70 );
71
72 if (isset($parameterArray['fieldTSConfig']['altIcons.'][$itemValue])) {
73 $itemArray[2] = $parameterArray['fieldTSConfig']['altIcons.'][$itemValue];
74 }
75
76 foreach ($selItems as $selItem) {
77 if ($selItem[1] == $itemValue) {
78 $itemArray[1] = $selItem[0];
79 break;
80 }
81 }
82 $itemsArray[$itemNumber] = implode('|', $itemArray);
83 }
84
85 // size must be at least two, as there are always maxitems > 1 (see parent function)
86 if (isset($config['size'])) {
87 $size = (int)$config['size'];
88 } else {
89 $size = 2;
90 }
91 $size = $config['autoSizeMax'] ? MathUtility::forceIntegerInRange(count($itemsArray) + 1, MathUtility::forceIntegerInRange($size, 1), $config['autoSizeMax']) : $size;
92
93 $itemsToSelect = [];
94 $filterTextfield = [];
95 $filterSelectbox = '';
96 if (!$disabled) {
97 // Create option tags:
98 $opt = array();
99 foreach ($selItems as $p) {
100 $opt[] = '<option value="' . htmlspecialchars($p[1]) . '" title="' . $p[0] . '">' . $p[0] . '</option>';
101 }
102 // Put together the selector box:
103 $selector_itemListStyle = isset($config['itemListStyle'])
104 ? ' style="' . htmlspecialchars($config['itemListStyle']) . '"'
105 : '';
106 $sOnChange = implode('', $parameterArray['fieldChangeFunc']);
107
108 $multiSelectId = StringUtility::getUniqueId('tceforms-multiselect-');
109 $itemsToSelect[] = '<select data-relatedfieldname="' . htmlspecialchars($parameterArray['itemFormElName']) . '" '
110 . 'data-exclusivevalues="' . htmlspecialchars($config['exclusiveKeys']) . '" '
111 . 'id="' . $multiSelectId . '" '
112 . 'data-formengine-input-name="' . htmlspecialchars($parameterArray['itemFormElName']) . '" '
113 . 'class="form-control t3js-formengine-select-itemstoselect" '
114 . ($size ? ' size="' . $size . '" ' : '')
115 . 'onchange="' . htmlspecialchars($sOnChange) . '" '
116 . $this->getValidationDataAsDataAttribute($config)
117 . $selector_itemListStyle
118 . '>';
119 $itemsToSelect[] = implode(LF, $opt);
120 $itemsToSelect[] = '</select>';
121
122 // enable filter functionality via a text field
123 if ($config['enableMultiSelectFilterTextfield']) {
124 $filterTextfield[] = '<span class="input-group input-group-sm">';
125 $filterTextfield[] = '<span class="input-group-addon">';
126 $filterTextfield[] = '<span class="fa fa-filter"></span>';
127 $filterTextfield[] = '</span>';
128 $filterTextfield[] = '<input class="t3js-formengine-multiselect-filter-textfield form-control" value="">';
129 $filterTextfield[] = '</span>';
130 }
131
132 // enable filter functionality via a select
133 if (isset($config['multiSelectFilterItems']) && is_array($config['multiSelectFilterItems']) && count($config['multiSelectFilterItems']) > 1) {
134 $filterDropDownOptions = array();
135 foreach ($config['multiSelectFilterItems'] as $optionElement) {
136 $optionValue = $this->getLanguageService()->sL(isset($optionElement[1]) && trim($optionElement[1]) !== '' ? trim($optionElement[1])
137 : trim($optionElement[0]));
138 $filterDropDownOptions[] = '<option value="' . htmlspecialchars($this->getLanguageService()->sL(trim($optionElement[0]))) . '">'
139 . htmlspecialchars($optionValue) . '</option>';
140 }
141 $filterSelectbox = '<select class="form-control input-sm t3js-formengine-multiselect-filter-dropdown">'
142 . implode(LF, $filterDropDownOptions) . '</select>';
143 }
144 }
145
146 if (!empty(trim($filterSelectbox)) && !empty($filterTextfield)) {
147 $filterSelectbox = '<div class="form-multigroup-item form-multigroup-element">' . $filterSelectbox . '</div>';
148 $filterTextfield = '<div class="form-multigroup-item form-multigroup-element">' . implode(LF, $filterTextfield) . '</div>';
149 $selectBoxFilterContents = '<div class="t3js-formengine-multiselect-filter-container form-multigroup-wrap">' . $filterSelectbox . $filterTextfield . '</div>';
150 } else {
151 $selectBoxFilterContents = trim($filterSelectbox . ' ' . implode(LF, $filterTextfield));
152 }
153
154 // Pass to "dbFileIcons" function:
155 $params = array(
156 'size' => $size,
157 'autoSizeMax' => MathUtility::forceIntegerInRange($config['autoSizeMax'], 0),
158 'style' => isset($config['selectedListStyle'])
159 ? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"'
160 : '',
161 'dontShowMoveIcons' => $maxitems <= 1,
162 'maxitems' => $maxitems,
163 'info' => '',
164 'headers' => array(
165 'selector' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.selected'),
166 'items' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.items'),
167 'selectorbox' => $selectBoxFilterContents,
168 ),
169 'noBrowser' => 1,
170 'rightbox' => implode(LF, $itemsToSelect),
171 'readOnly' => $disabled
172 );
173 $html .= $this->dbFileIcons($parameterArray['itemFormElName'], '', '', $itemsArray, '', $params);
174
175 // Wizards:
176 if (!$disabled) {
177 $html = $this->renderWizards(
178 array($html),
179 $config['wizards'],
180 $table,
181 $this->data['databaseRow'],
182 $field,
183 $parameterArray,
184 $parameterArray['itemFormElName'],
185 BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras'])
186 );
187 }
188
189 $resultArray = $this->initializeResultArray();
190 $resultArray['html'] = $html;
191 return $resultArray;
192 }
193
194 /**
195 * @return BackendUserAuthentication
196 */
197 protected function getBackendUserAuthentication()
198 {
199 return $GLOBALS['BE_USER'];
200 }
201 }