[TASK] Upgrade typo3/phar-stream-wrapper to v3.1.3 (PHP 7.4)
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Form / Element / CheckboxElement.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Backend\Form\Element;
4
5 /*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18 use TYPO3\CMS\Backend\Form\NodeFactory;
19 use TYPO3\CMS\Core\Imaging\Icon;
20 use TYPO3\CMS\Core\Imaging\IconRegistry;
21 use TYPO3\CMS\Core\Utility\GeneralUtility;
22
23 /**
24 * Generation of TCEform elements of the type "check"
25 */
26 class CheckboxElement extends AbstractFormElement
27 {
28 /**
29 * @var IconRegistry
30 */
31 private $iconRegistry;
32
33 /**
34 * Default field information enabled for this element.
35 *
36 * @var array
37 */
38 protected $defaultFieldInformation = [
39 'tcaDescription' => [
40 'renderType' => 'tcaDescription',
41 ],
42 ];
43
44 /**
45 * Default field wizards enabled for this element.
46 *
47 * @var array
48 */
49 protected $defaultFieldWizard = [
50 'localizationStateSelector' => [
51 'renderType' => 'localizationStateSelector',
52 ],
53 'otherLanguageContent' => [
54 'renderType' => 'otherLanguageContent',
55 'after' => [
56 'localizationStateSelector'
57 ],
58 ],
59 'defaultLanguageDifferences' => [
60 'renderType' => 'defaultLanguageDifferences',
61 'after' => [
62 'otherLanguageContent',
63 ],
64 ],
65 ];
66
67 /**
68 * @param NodeFactory $nodeFactory
69 * @param array $data
70 */
71 public function __construct(NodeFactory $nodeFactory, array $data)
72 {
73 parent::__construct($nodeFactory, $data);
74 $this->iconRegistry = GeneralUtility::makeInstance(IconRegistry::class);
75 }
76
77 /**
78 * This will render a checkbox or an array of checkboxes
79 *
80 * @return array As defined in initializeResultArray() of AbstractNode
81 */
82 public function render(): array
83 {
84 $resultArray = $this->initializeResultArray();
85
86 $elementHtml = '';
87 $disabled = false;
88 if ($this->data['parameterArray']['fieldConf']['config']['readOnly']) {
89 $disabled = true;
90 }
91 // Traversing the array of items
92 $items = $this->data['parameterArray']['fieldConf']['config']['items'];
93
94 $numberOfItems = \count($items);
95 if ($numberOfItems === 0) {
96 $items[] = ['', ''];
97 $numberOfItems = 1;
98 }
99 $formElementValue = (int)$this->data['parameterArray']['itemFormElValue'];
100 $cols = (int)$this->data['parameterArray']['fieldConf']['config']['cols'];
101 if ($cols > 1) {
102 [$colClass, $colClear] = $this->calculateColumnMarkup($cols);
103 $elementHtml .= '<div class="checkbox-row row">';
104 $counter = 0;
105 // $itemKey is important here, because items could have been removed via TSConfig
106 foreach ($items as $itemKey => $itemDefinition) {
107 $label = $itemDefinition[0];
108 $elementHtml .=
109 '<div class="checkbox-column ' . $colClass . '">'
110 . $this->renderSingleCheckboxElement($label, $itemKey, $formElementValue, $numberOfItems, $this->data['parameterArray'], $disabled) .
111 '</div>';
112 ++$counter;
113 if ($counter < $numberOfItems && !empty($colClear)) {
114 foreach ($colClear as $rowBreakAfter => $clearClass) {
115 if ($counter % $rowBreakAfter === 0) {
116 $elementHtml .= '<div class="clearfix ' . $clearClass . '"></div>';
117 }
118 }
119 }
120 }
121 $elementHtml .= '</div>';
122 } else {
123 $counter = 0;
124 foreach ($items as $itemKey => $itemDefinition) {
125 $label = $itemDefinition[0];
126 $elementHtml .= $this->renderSingleCheckboxElement($label, $counter, $formElementValue, $numberOfItems, $this->data['parameterArray'], $disabled);
127 ++$counter;
128 }
129 }
130 if (!$disabled) {
131 $elementHtml .= '<input type="hidden" name="' . htmlspecialchars($this->data['parameterArray']['itemFormElName']) . '" value="' . htmlspecialchars((string)$formElementValue) . '" />';
132 }
133
134 $fieldInformationResult = $this->renderFieldInformation();
135 $fieldInformationHtml = $fieldInformationResult['html'];
136 $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
137
138 $fieldWizardResult = $this->renderFieldWizard();
139 $fieldWizardHtml = $fieldWizardResult['html'];
140 $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false);
141
142 $html = [];
143 $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
144 $html[] = $fieldInformationHtml;
145 $html[] = '<div class="form-wizards-wrap">';
146 $html[] = '<div class="form-wizards-element">';
147 $html[] = $elementHtml;
148 $html[] = '</div>';
149 if (!$disabled && !empty($fieldWizardHtml)) {
150 $html[] = '<div class="form-wizards-items-bottom">';
151 $html[] = $fieldWizardHtml;
152 $html[] = '</div>';
153 }
154 $html[] = '</div>';
155 $html[] = '</div>';
156
157 $resultArray['html'] = implode(LF, $html);
158 return $resultArray;
159 }
160
161 /**
162 * This functions builds the HTML output for the checkbox
163 *
164 * @param string $label Label of this item
165 * @param int $itemCounter Number of this element in the list of all elements
166 * @param int $formElementValue Value of this element
167 * @param int $numberOfItems Full number of items
168 * @param array $additionalInformation Information with additional configuration options.
169 * @param bool $disabled TRUE if form element is disabled
170 * @return string Single element HTML
171 */
172 protected function renderSingleCheckboxElement($label, $itemCounter, $formElementValue, $numberOfItems, $additionalInformation, $disabled): string
173 {
174 $config = $additionalInformation['fieldConf']['config'];
175 $inline = !empty($config['cols']) && $config['cols'] === 'inline';
176 $invert = isset($config['items'][$itemCounter]['invertStateDisplay']) && $config['items'][$itemCounter]['invertStateDisplay'] === true;
177 $checkboxParameters = $this->checkBoxParams(
178 $additionalInformation['itemFormElName'],
179 $formElementValue,
180 $itemCounter,
181 $numberOfItems,
182 implode('', $additionalInformation['fieldChangeFunc'])
183 );
184 $checkboxId = $additionalInformation['itemFormElID'] . '_' . $itemCounter;
185
186 $iconIdentifierChecked = !empty($config['items'][$itemCounter]['iconIdentifierChecked']) ? $config['items'][$itemCounter]['iconIdentifierChecked'] : 'actions-check';
187 if (!$this->iconRegistry->isRegistered($iconIdentifierChecked)) {
188 $iconIdentifierChecked = 'actions-check';
189 }
190 $iconIdentifierUnchecked = !empty($config['items'][$itemCounter]['iconIdentifierUnchecked']) ? $config['items'][$itemCounter]['iconIdentifierUnchecked'] : 'empty-empty';
191 if (!$this->iconRegistry->isRegistered($iconIdentifierUnchecked)) {
192 $iconIdentifierUnchecked = 'empty-empty';
193 }
194 $iconChecked = $this->iconFactory->getIcon($iconIdentifierChecked, Icon::SIZE_SMALL)->render('inline');
195 $iconUnchecked = $this->iconFactory->getIcon($iconIdentifierUnchecked, Icon::SIZE_SMALL)->render('inline');
196
197 return '
198 <div class="checkbox checkbox-type-icon-toggle' . ($invert ? ' checkbox-invert' : '') . ($inline ? ' checkbox-inline' : '') . (!$disabled ? '' : ' disabled') . '">
199 <input type="checkbox"
200 class="checkbox-input"
201 value="1"
202 data-formengine-input-name="' . htmlspecialchars($additionalInformation['itemFormElName']) . '"
203 ' . $checkboxParameters . '
204 ' . ($disabled ? ' disabled="disabled"' : '') . '
205 id="' . $checkboxId . '" />
206 <label class="checkbox-label" for="' . $checkboxId . '">
207 <span class="checkbox-label-icon">
208 <span class="checkbox-label-icon-checked">' . ($invert ? $iconUnchecked : $iconChecked) . '</span>
209 <span class="checkbox-label-icon-unchecked">' . ($invert ? $iconChecked : $iconUnchecked) . '</span>
210 </span>
211 <span class="checkbox-label-text">' . $this->appendValueToLabelInDebugMode(($label ? htmlspecialchars($label) : '&nbsp;'), $formElementValue) . '</span>
212 </label>
213 </div>';
214 }
215 }