1<?php 2 3declare(strict_types=1); 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 18namespace TYPO3\CMS\Backend\Form\Element; 19 20use TYPO3\CMS\Core\Utility\StringUtility; 21 22/** 23 * Generation of TCEform elements of the type "check" 24 */ 25class CheckboxLabeledToggleElement extends AbstractFormElement 26{ 27 /** 28 * Default field information enabled for this element. 29 * 30 * @var array 31 */ 32 protected $defaultFieldInformation = [ 33 'tcaDescription' => [ 34 'renderType' => 'tcaDescription', 35 ], 36 ]; 37 38 /** 39 * Default field wizards enabled for this element. 40 * 41 * @var array 42 */ 43 protected $defaultFieldWizard = [ 44 'localizationStateSelector' => [ 45 'renderType' => 'localizationStateSelector', 46 ], 47 'otherLanguageContent' => [ 48 'renderType' => 'otherLanguageContent', 49 'after' => [ 50 'localizationStateSelector', 51 ], 52 ], 53 'defaultLanguageDifferences' => [ 54 'renderType' => 'defaultLanguageDifferences', 55 'after' => [ 56 'otherLanguageContent', 57 ], 58 ], 59 ]; 60 61 /** 62 * This will render a checkbox or an array of checkboxes 63 * 64 * @return array As defined in initializeResultArray() of AbstractNode 65 */ 66 public function render(): array 67 { 68 $resultArray = $this->initializeResultArray(); 69 70 $elementHtml = ''; 71 $disabled = false; 72 if ($this->data['parameterArray']['fieldConf']['config']['readOnly'] ?? false) { 73 $disabled = true; 74 } 75 // Traversing the array of items 76 $items = $this->data['parameterArray']['fieldConf']['config']['items']; 77 78 $numberOfItems = \count($items); 79 if ($numberOfItems === 0) { 80 $items[] = ['', '']; 81 $numberOfItems = 1; 82 } 83 $formElementValue = (int)$this->data['parameterArray']['itemFormElValue']; 84 $cols = (int)($this->data['parameterArray']['fieldConf']['config']['cols'] ?? 0); 85 if ($cols > 1) { 86 [$colClass, $colClear] = $this->calculateColumnMarkup($cols); 87 $elementHtml .= '<div class="checkbox-row row">'; 88 $counter = 0; 89 // $itemKey is important here, because items could have been removed via TSConfig 90 foreach ($items as $itemKey => $itemDefinition) { 91 $label = $itemDefinition[0]; 92 $elementHtml .= 93 '<div class="checkbox-column ' . $colClass . '">' 94 . $this->renderSingleCheckboxElement($label, $itemKey, $formElementValue, $numberOfItems, $this->data['parameterArray'], $disabled) . 95 '</div>'; 96 ++$counter; 97 if ($counter < $numberOfItems && !empty($colClear)) { 98 foreach ($colClear as $rowBreakAfter => $clearClass) { 99 if ($counter % $rowBreakAfter === 0) { 100 $elementHtml .= '<div class="clearfix ' . $clearClass . '"></div>'; 101 } 102 } 103 } 104 } 105 $elementHtml .= '</div>'; 106 } else { 107 $counter = 0; 108 foreach ($items as $itemKey => $itemDefinition) { 109 $label = $itemDefinition[0]; 110 $elementHtml .= $this->renderSingleCheckboxElement($label, $counter, $formElementValue, $numberOfItems, $this->data['parameterArray'], $disabled); 111 ++$counter; 112 } 113 } 114 if (!$disabled) { 115 $elementHtml .= '<input type="hidden" name="' . htmlspecialchars($this->data['parameterArray']['itemFormElName']) . '" value="' . htmlspecialchars((string)$formElementValue) . '" />'; 116 } 117 118 $fieldInformationResult = $this->renderFieldInformation(); 119 $fieldInformationHtml = $fieldInformationResult['html']; 120 $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false); 121 122 $fieldWizardResult = $this->renderFieldWizard(); 123 $fieldWizardHtml = $fieldWizardResult['html']; 124 $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false); 125 126 $html = []; 127 $html[] = '<div class="formengine-field-item t3js-formengine-field-item">'; 128 $html[] = $fieldInformationHtml; 129 $html[] = '<div class="form-wizards-wrap">'; 130 $html[] = '<div class="form-wizards-element">'; 131 $html[] = $elementHtml; 132 $html[] = '</div>'; 133 if (!$disabled && !empty($fieldWizardHtml)) { 134 $html[] = '<div class="form-wizards-items-bottom">'; 135 $html[] = $fieldWizardHtml; 136 $html[] = '</div>'; 137 } 138 $html[] = '</div>'; 139 $html[] = '</div>'; 140 141 $resultArray['html'] = implode(LF, $html); 142 return $resultArray; 143 } 144 145 /** 146 * This functions builds the HTML output for the checkbox 147 * 148 * @param string $label Label of this item 149 * @param int $itemCounter Number of this element in the list of all elements 150 * @param int $formElementValue Value of this element 151 * @param int $numberOfItems Full number of items 152 * @param array $additionalInformation Information with additional configuration options. 153 * @param bool $disabled TRUE if form element is disabled 154 * @return string Single element HTML 155 */ 156 protected function renderSingleCheckboxElement($label, $itemCounter, $formElementValue, $numberOfItems, $additionalInformation, $disabled): string 157 { 158 $config = $additionalInformation['fieldConf']['config']; 159 $inline = !empty($config['cols']) && $config['cols'] === 'inline'; 160 $invert = isset($config['items'][$itemCounter]['invertStateDisplay']) && $config['items'][$itemCounter]['invertStateDisplay'] === true; 161 $checkboxParameters = $this->checkBoxParams( 162 $additionalInformation['itemFormElName'], 163 $formElementValue, 164 $itemCounter, 165 $numberOfItems, 166 $additionalInformation['fieldChangeFunc'] ?? [], 167 $invert 168 ); 169 $uniqueId = StringUtility::getUniqueId('_'); 170 $checkboxId = $additionalInformation['itemFormElID'] . '_' . $itemCounter . $uniqueId; 171 return ' 172 <div class="form-check form-check-type-labeled-toggle' . ($inline ? ' form-check-inline' : '') . (!$disabled ? '' : ' disabled') . '"> 173 <input type="checkbox" 174 class="form-check-input" 175 value="1" 176 data-formengine-input-name="' . htmlspecialchars($additionalInformation['itemFormElName']) . '" 177 ' . $checkboxParameters . ' 178 ' . (!$disabled ? '' : ' disabled="disabled"') . ' 179 id="' . $checkboxId . '" /> 180 <label class="form-check-label" for="' . $checkboxId . '"> 181 <span class="form-check-label-switch"> 182 <span class="form-check-label-switch-checked"> 183 ' . $config['items'][$itemCounter]['labelChecked'] . ' 184 </span> 185 <span class="form-check-label-switch-unchecked"> 186 ' . $config['items'][$itemCounter]['labelUnchecked'] . ' 187 </span> 188 </span> 189 <span class="form-check-label-text">' . $this->appendValueToLabelInDebugMode(($label ? htmlspecialchars($label) : ' '), $formElementValue) . '</span> 190 </label> 191 </div>'; 192 } 193} 194