[BUGFIX] Prevent notice in SelectMultipleSideBySideElement
[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\GeneralUtility;
20 use TYPO3\CMS\Core\Utility\MathUtility;
21 use TYPO3\CMS\Core\Utility\StringUtility;
22
23 /**
24 * Render a widget with two boxes side by side.
25 *
26 * This is rendered for config type=select, maxitems > 1, no other renderMode set
27 */
28 class SelectMultipleSideBySideElement extends AbstractFormElement {
29
30 /**
31 * Render side by side element.
32 *
33 * @return array As defined in initializeResultArray() of AbstractNode
34 */
35 public function render() {
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($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 "removeItems":
63 $removeItems = GeneralUtility::trimExplode(',', $parameterArray['fieldTSConfig']['removeItems'], TRUE);
64 // Get the array with selected items:
65 $itemsArray = $parameterArray['itemFormElValue'];
66
67 // Perform modification of the selected items array:
68 // @todo: this part should probably be moved to TcaSelectItems provider?!
69 foreach ($itemsArray as $itemNumber => $itemValue) {
70 $itemArray = array(
71 0 => $itemValue,
72 1 => '',
73 );
74 $itemIcon = NULL;
75 $isRemoved = in_array($itemValue, $removeItems)
76 || $config['type'] == 'select' && $config['authMode']
77 && !$this->getBackendUserAuthentication()->checkAuthMode($table, $field, $itemValue, $config['authMode']);
78 if ($isRemoved && !$parameterArray['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) {
79 $itemArray[1] = rawurlencode(@sprintf($noMatchingLabel, $itemValue));
80 } else {
81 if (isset($parameterArray['fieldTSConfig']['altLabels.'][$itemValue])) {
82 $itemArray[1] = rawurlencode($this->getLanguageService()->sL($parameterArray['fieldTSConfig']['altLabels.'][$itemValue]));
83 }
84 if (isset($parameterArray['fieldTSConfig']['altIcons.'][$itemValue])) {
85 $itemArray[2] = $parameterArray['fieldTSConfig']['altIcons.'][$itemValue];
86 }
87 }
88 if ($itemArray[1] === '') {
89 foreach ($selItems as $selItem) {
90 if ($selItem[1] == $itemValue) {
91 $itemArray[1] = $selItem[0];
92 break;
93 }
94 }
95 }
96 $itemsArray[$itemNumber] = implode('|', $itemArray);
97 }
98
99 // size must be at least two, as there are always maxitems > 1 (see parent function)
100 if (isset($config['size'])) {
101 $size = (int)$config['size'];
102 } else {
103 $size = 2;
104 }
105 $size = $config['autoSizeMax'] ? MathUtility::forceIntegerInRange(count($itemsArray) + 1, MathUtility::forceIntegerInRange($size, 1), $config['autoSizeMax']) : $size;
106
107 $itemsToSelect = [];
108 $filterTextfield = [];
109 $filterSelectbox = '';
110 if (!$disabled) {
111 // Create option tags:
112 $opt = array();
113 foreach ($selItems as $p) {
114 $opt[] = '<option value="' . htmlspecialchars($p[1]) . '" title="' . $p[0] . '">' . $p[0] . '</option>';
115 }
116 // Put together the selector box:
117 $selector_itemListStyle = isset($config['itemListStyle'])
118 ? ' style="' . htmlspecialchars($config['itemListStyle']) . '"'
119 : '';
120 $sOnChange = implode('', $parameterArray['fieldChangeFunc']);
121
122 $multiSelectId = StringUtility::getUniqueId('tceforms-multiselect-');
123 $itemsToSelect[] = '<select data-relatedfieldname="' . htmlspecialchars($parameterArray['itemFormElName']) . '" '
124 . 'data-exclusivevalues="' . htmlspecialchars($config['exclusiveKeys']) . '" '
125 . 'id="' . $multiSelectId . '" '
126 . 'data-formengine-input-name="' . htmlspecialchars($parameterArray['itemFormElName']) . '" '
127 . 'class="form-control t3js-formengine-select-itemstoselect" '
128 . ($size ? ' size="' . $size . '" ' : '')
129 . 'onchange="' . htmlspecialchars($sOnChange) . '" '
130 . $parameterArray['onFocus']
131 . $this->getValidationDataAsDataAttribute($config)
132 . $selector_itemListStyle
133 . '>';
134 $itemsToSelect[] = implode(LF, $opt);
135 $itemsToSelect[] = '</select>';
136
137 // enable filter functionality via a text field
138 if ($config['enableMultiSelectFilterTextfield']) {
139 $filterTextfield[] = '<span class="input-group input-group-sm">';
140 $filterTextfield[] = '<span class="input-group-addon">';
141 $filterTextfield[] = '<span class="fa fa-filter"></span>';
142 $filterTextfield[] = '</span>';
143 $filterTextfield[] = '<input class="t3js-formengine-multiselect-filter-textfield form-control" value="">';
144 $filterTextfield[] = '</span>';
145 }
146
147 // enable filter functionality via a select
148 if (isset($config['multiSelectFilterItems']) && is_array($config['multiSelectFilterItems']) && count($config['multiSelectFilterItems']) > 1) {
149 $filterDropDownOptions = array();
150 foreach ($config['multiSelectFilterItems'] as $optionElement) {
151 $optionValue = $this->getLanguageService()->sL(isset($optionElement[1]) && $optionElement[1] != '' ? $optionElement[1]
152 : $optionElement[0]);
153 $filterDropDownOptions[] = '<option value="' . htmlspecialchars($this->getLanguageService()->sL($optionElement[0])) . '">'
154 . htmlspecialchars($optionValue) . '</option>';
155 }
156 $filterSelectbox = '<select class="form-control input-sm t3js-formengine-multiselect-filter-dropdown">'
157 . implode(LF, $filterDropDownOptions) . '</select>';
158 }
159 }
160
161 if (!empty(trim($filterSelectbox)) && !empty($filterTextfield)) {
162 $filterSelectbox = '<div class="form-multigroup-item form-multigroup-element">' . $filterSelectbox . '</div>';
163 $filterTextfield = '<div class="form-multigroup-item form-multigroup-element">' . implode(LF, $filterTextfield) . '</div>';
164 $selectBoxFilterContents = '<div class="t3js-formengine-multiselect-filter-container form-multigroup-wrap">' . $filterSelectbox . $filterTextfield . '</div>';
165 } else {
166 $selectBoxFilterContents = trim($filterSelectbox . ' ' . implode(LF, $filterTextfield));
167 }
168
169 // Pass to "dbFileIcons" function:
170 $params = array(
171 'size' => $size,
172 'autoSizeMax' => MathUtility::forceIntegerInRange($config['autoSizeMax'], 0),
173 'style' => isset($config['selectedListStyle'])
174 ? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"'
175 : '',
176 'dontShowMoveIcons' => $maxitems <= 1,
177 'maxitems' => $maxitems,
178 'info' => '',
179 'headers' => array(
180 'selector' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.selected'),
181 'items' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.items'),
182 'selectorbox' => $selectBoxFilterContents,
183 ),
184 'noBrowser' => 1,
185 'rightbox' => implode(LF, $itemsToSelect),
186 'readOnly' => $disabled
187 );
188 $html .= $this->dbFileIcons($parameterArray['itemFormElName'], '', '', $itemsArray, '', $params, $parameterArray['onFocus']);
189
190 // Wizards:
191 if (!$disabled) {
192 $html = $this->renderWizards(
193 array($html),
194 $config['wizards'],
195 $table,
196 $this->data['databaseRow'],
197 $field,
198 $parameterArray,
199 $parameterArray['itemFormElName'],
200 BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras'])
201 );
202 }
203
204 $resultArray = $this->initializeResultArray();
205 $resultArray['html'] = $html;
206 return $resultArray;
207 }
208
209 /**
210 * @return BackendUserAuthentication
211 */
212 protected function getBackendUserAuthentication() {
213 return $GLOBALS['BE_USER'];
214 }
215 }