[BUGFIX] Fix several typos in php comments
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Form / Element / SelectCheckBoxElement.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\Form\Utility\FormEngineUtility;
18 use TYPO3\CMS\Backend\Utility\BackendUtility;
19 use TYPO3\CMS\Core\Imaging\Icon;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21 use TYPO3\CMS\Core\Utility\StringUtility;
22
23 /**
24 * Creates a widget with check box elements.
25 *
26 * This is rendered for config type=select, renderType=selectCheckBox
27 */
28 class SelectCheckBoxElement extends AbstractFormElement
29 {
30 /**
31 * Default field information enabled for this element.
32 *
33 * @var array
34 */
35 protected $defaultFieldInformation = [
36 'tcaDescription' => [
37 'renderType' => 'tcaDescription',
38 ],
39 ];
40
41 /**
42 * Default field wizards enabled for this element.
43 *
44 * @var array
45 */
46 protected $defaultFieldWizard = [
47 'localizationStateSelector' => [
48 'renderType' => 'localizationStateSelector',
49 ],
50 'otherLanguageContent' => [
51 'renderType' => 'otherLanguageContent',
52 'after' => [
53 'localizationStateSelector'
54 ],
55 ],
56 'defaultLanguageDifferences' => [
57 'renderType' => 'defaultLanguageDifferences',
58 'after' => [
59 'otherLanguageContent',
60 ],
61 ],
62 ];
63
64 /**
65 * Render check boxes
66 *
67 * @return array As defined in initializeResultArray() of AbstractNode
68 */
69 public function render()
70 {
71 $resultArray = $this->initializeResultArray();
72
73 $html = [];
74 // Field configuration from TCA:
75 $parameterArray = $this->data['parameterArray'];
76 $config = $parameterArray['fieldConf']['config'];
77 $disabled = !empty($config['readOnly']);
78
79 $selItems = $config['items'];
80 if (!empty($selItems)) {
81 // Get values in an array (and make unique, which is fine because there can be no duplicates anyway):
82 $itemArray = array_flip($parameterArray['itemFormElValue']);
83
84 // Traverse the Array of selector box items:
85 $groups = [];
86 $currentGroup = 0;
87 $c = 0;
88 $sOnChange = '';
89 if (!$disabled) {
90 $sOnChange = implode('', $parameterArray['fieldChangeFunc']);
91 // Used to accumulate the JS needed to restore the original selection.
92 foreach ($selItems as $p) {
93 // Non-selectable element:
94 if ($p[1] === '--div--') {
95 $selIcon = '';
96 if (isset($p[2]) && $p[2] !== 'empty-empty') {
97 $selIcon = FormEngineUtility::getIconHtml($p[2]);
98 }
99 $currentGroup++;
100 $groups[$currentGroup]['header'] = [
101 'icon' => $selIcon,
102 'title' => $p[0]
103 ];
104 } else {
105 // Check if some help text is available
106 // Help text is expected to be an associative array
107 // with two key, "title" and "description"
108 // For the sake of backwards compatibility, we test if the help text
109 // is a string and use it as a description (this could happen if items
110 // are modified with an itemProcFunc)
111 $hasHelp = false;
112 $help = '';
113 $helpArray = [];
114 if (!empty($p[3])) {
115 $hasHelp = true;
116 if (is_array($p[3])) {
117 $helpArray = $p[3];
118 } else {
119 $helpArray['description'] = $p[3];
120 }
121 }
122 if ($hasHelp) {
123 $help = BackendUtility::wrapInHelp('', '', '', $helpArray);
124 }
125
126 // Selected or not by default:
127 $checked = 0;
128 if (isset($itemArray[$p[1]])) {
129 $checked = 1;
130 unset($itemArray[$p[1]]);
131 }
132
133 // Build item array
134 $groups[$currentGroup]['items'][] = [
135 'id' => StringUtility::getUniqueId('select_checkbox_row_'),
136 'name' => $parameterArray['itemFormElName'] . '[' . $c . ']',
137 'value' => $p[1],
138 'checked' => $checked,
139 'disabled' => false,
140 'class' => '',
141 'icon' => FormEngineUtility::getIconHtml(!empty($p[2]) ? $p[2] : 'empty-empty'),
142 'title' => $p[0],
143 'help' => $help
144 ];
145 $c++;
146 }
147 }
148 }
149
150 $fieldInformationResult = $this->renderFieldInformation();
151 $fieldInformationHtml = $fieldInformationResult['html'];
152 $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
153
154 $fieldWizardResult = $this->renderFieldWizard();
155 $fieldWizardHtml = $fieldWizardResult['html'];
156 $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false);
157
158 $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
159 $html[] = $fieldInformationHtml;
160 $html[] = '<div class="form-wizards-wrap">';
161 $html[] = '<div class="form-wizards-element">';
162
163 // Add an empty hidden field which will send a blank value if all items are unselected.
164 $html[] = '<input type="hidden" class="select-checkbox" name="' . htmlspecialchars($parameterArray['itemFormElName']) . '" value="">';
165
166 // Building the checkboxes
167 foreach ($groups as $groupKey => $group) {
168 $groupId = htmlspecialchars($parameterArray['itemFormElID']) . '-group-' . $groupKey;
169 $groupIdCollapsible = $groupId . '-collapse';
170 $html[] = '<div id="' . $groupId . '" class="panel panel-default">';
171 if (is_array($group['header'])) {
172 $html[] = '<div class="panel-heading">';
173 $html[] = '<a data-toggle="collapse" href="#' . $groupIdCollapsible . '" aria-expanded="false" aria-controls="' . $groupIdCollapsible . '">';
174 $html[] = $group['header']['icon'];
175 $html[] = htmlspecialchars($group['header']['title']);
176 $html[] = '</a>';
177 $html[] = '</div>';
178 }
179 if (is_array($group['items']) && !empty($group['items'])) {
180 $tableRows = [];
181
182 // Render rows
183 foreach ($group['items'] as $item) {
184 $tableRows[] = '<tr class="' . $item['class'] . '">';
185 $tableRows[] = '<td class="col-checkbox">';
186 $tableRows[] = '<input type="checkbox" class="t3js-checkbox" '
187 . 'id="' . $item['id'] . '" '
188 . 'name="' . htmlspecialchars($item['name']) . '" '
189 . 'value="' . htmlspecialchars($item['value']) . '" '
190 . 'onclick="' . htmlspecialchars($sOnChange) . '" '
191 . ($item['checked'] ? 'checked=checked ' : '')
192 . ($item['disabled'] ? 'disabled=disabled ' : '') . '>';
193 $tableRows[] = '</td>';
194 $tableRows[] = '<td class="col-icon">';
195 $tableRows[] = '<label class="label-block" for="' . $item['id'] . '">' . $item['icon'] . '</label>';
196 $tableRows[] = '</td>';
197 $tableRows[] = '<td class="col-title">';
198 $tableRows[] = '<label class="label-block nowrap-disabled" for="' . $item['id'] . '">' . htmlspecialchars($this->appendValueToLabelInDebugMode($item['title'], $item['value']), ENT_COMPAT, 'UTF-8', false) . '</label>';
199 $tableRows[] = '</td>';
200 $tableRows[] = '<td class="text-right">' . $item['help'] . '</td>';
201 $tableRows[] = '</tr>';
202 }
203
204 // Build reset group button
205 $resetGroupBtn = '';
206 if (!empty($group['items'])) {
207 $title = htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.revertSelection'));
208 $resetGroupBtn = '<button type="button" '
209 . 'class="btn btn-default btn-sm t3js-revert-selection" '
210 . 'title="' . $title . '"'
211 . '>'
212 . $this->iconFactory->getIcon('actions-edit-undo', Icon::SIZE_SMALL)->render() . ' '
213 . $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.revertSelection') . '</button>';
214 }
215
216 if (is_array($group['header'])) {
217 $html[] = '<div id="' . $groupIdCollapsible . '" class="panel-collapse collapse" role="tabpanel">';
218 }
219 $checkboxId = uniqid($groupId);
220 $title = htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.toggleall'));
221 $html[] = '<div class="table-responsive">';
222 $html[] = '<table class="table table-transparent table-hover">';
223 $html[] = '<thead>';
224 $html[] = '<tr>';
225 $html[] = '<th class="col-checkbox">';
226 $html[] = '<input type="checkbox" id="' . $checkboxId . '" class="t3js-toggle-checkboxes" data-trigger="hover" data-placement="right" data-title="' . $title . '" data-toggle="tooltip" />';
227 $html[] = '</th>';
228 $html[] = '<th class="col-title" colspan="2"><label for="' . $checkboxId . '">' . $title . '</label></th>';
229 $html[] = '<th class="text-right">' . $resetGroupBtn . '</th>';
230 $html[] = '</tr>';
231 $html[] = '</thead>';
232 $html[] = '<tbody>' . implode(LF, $tableRows) . '</tbody>';
233 $html[] = '</table>';
234 $html[] = '</div>';
235 if (is_array($group['header'])) {
236 $html[] = '</div>';
237 }
238
239 $resultArray['requireJsModules'][] = ['TYPO3/CMS/Backend/FormEngine/Element/SelectCheckBoxElement' => '
240 function(SelectCheckBoxElement) {
241 new SelectCheckBoxElement(' . GeneralUtility::quoteJSvalue($checkboxId) . ');
242 }'
243 ];
244 }
245 $html[] = '</div>';
246 }
247
248 $html[] = '</div>';
249 if (!$disabled && !empty($fieldWizardHtml)) {
250 $html[] = '<div class="form-wizards-items-bottom">';
251 $html[] = $fieldWizardHtml;
252 $html[] = '</div>';
253 }
254 $html[] = '</div>';
255 $html[] = '</div>';
256 }
257
258 $resultArray['html'] = implode(LF, $html);
259 $resultArray['requireJsModules'][] = 'TYPO3/CMS/Backend/Tooltip';
260 return $resultArray;
261 }
262 }