[FEATURE] Add a new TCA type "slug"
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Form / Element / InputSlugElement.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\Core\Localization\LanguageService;
19 use TYPO3\CMS\Core\Site\Entity\SiteInterface;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21 use TYPO3\CMS\Core\Utility\MathUtility;
22 use TYPO3\CMS\Core\Utility\StringUtility;
23
24 /**
25 * General type=input element with some additional value.
26 */
27 class InputSlugElement extends AbstractFormElement
28 {
29 /**
30 * Default field wizards enabled for this element.
31 *
32 * @var array
33 */
34 protected $defaultFieldWizard = [
35 'localizationStateSelector' => [
36 'renderType' => 'localizationStateSelector',
37 ],
38 'otherLanguageContent' => [
39 'renderType' => 'otherLanguageContent',
40 'after' => [
41 'localizationStateSelector'
42 ],
43 ],
44 'defaultLanguageDifferences' => [
45 'renderType' => 'defaultLanguageDifferences',
46 'after' => [
47 'otherLanguageContent',
48 ],
49 ],
50 ];
51
52 /**
53 * This will render a single-line input form field, possibly with various control/validation features
54 *
55 * @return array As defined in initializeResultArray() of AbstractNode
56 */
57 public function render()
58 {
59 $table = $this->data['tableName'];
60 $row = $this->data['databaseRow'];
61 $parameterArray = $this->data['parameterArray'];
62 $resultArray = $this->initializeResultArray();
63
64 $languageField = $GLOBALS['TCA'][$table]['ctrl']['languageField'];
65 $languageId = (int)($row[$languageField] ?? $this->data['defaultLanguageRow'][$languageField] ?? 0);
66 $baseUrl = $this->getPrefix($this->data['site'], $languageId);
67
68 $itemValue = $parameterArray['itemFormElValue'];
69 $config = $parameterArray['fieldConf']['config'];
70 $evalList = GeneralUtility::trimExplode(',', $config['eval'], true);
71 $size = MathUtility::forceIntegerInRange($config['size'] ?? $this->defaultInputWidth, $this->minimumInputWidth, $this->maxInputWidth);
72 $width = (int)$this->formMaxWidth($size);
73
74 // Convert UTF-8 characters back (that is important, see Slug class when sanitizing)
75 $itemValue = rawurldecode($itemValue);
76
77 $idAttribute = StringUtility::getUniqueId('formengine-input-');
78 $attributes = [
79 'value' => '',
80 'id' => $idAttribute,
81 'class' => 'form-control',
82 'disabled' => 'disabled',
83 'placeholder' => '/',
84 'data-formengine-validation-rules' => $this->getValidationDataAsJsonString($config),
85 'data-formengine-input-params' => json_encode([
86 'field' => $parameterArray['itemFormElName'],
87 'evalList' => implode(',', $evalList),
88 'is_in' => trim($config['is_in'] ?? '')
89 ]),
90 'data-formengine-input-name' => $parameterArray['itemFormElName'],
91 ];
92
93 $fieldInformationResult = $this->renderFieldInformation();
94 $fieldInformationHtml = $fieldInformationResult['html'];
95 $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
96
97 $fieldControlResult = $this->renderFieldControl();
98 $fieldControlHtml = $fieldControlResult['html'];
99 $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldControlResult, false);
100
101 $fieldWizardResult = $this->renderFieldWizard();
102 $fieldWizardHtml = $fieldWizardResult['html'];
103 $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false);
104
105 $mainFieldHtml = [];
106 $mainFieldHtml[] = '<div class="formengine-field-item t3js-formengine-field-item">';
107 $mainFieldHtml[] = $fieldInformationHtml;
108 $mainFieldHtml[] = '<div class="form-control-wrap" style="max-width: ' . $width . 'px">';
109 $mainFieldHtml[] = '<div class="form-wizards-wrap">';
110 $mainFieldHtml[] = '<div class="form-wizards-element">';
111 $mainFieldHtml[] = '<div class="input-group">' . ($baseUrl ? '<span class="input-group-addon">' . htmlspecialchars($baseUrl) . '</span>' : '') . '<input type="text"' . GeneralUtility::implodeAttributes($attributes, true) . ' /></div>';
112 $mainFieldHtml[] = '<input type="hidden" name="' . $parameterArray['itemFormElName'] . '" value="' . htmlspecialchars($itemValue) . '" />';
113 $mainFieldHtml[] = '</div>';
114 if (!empty($fieldControlHtml)) {
115 $mainFieldHtml[] = '<div class="form-wizards-items-aside">';
116 $mainFieldHtml[] = '<div class="btn-group">';
117 $mainFieldHtml[] = $fieldControlHtml;
118 $mainFieldHtml[] = '</div>';
119 $mainFieldHtml[] = '</div>';
120 }
121 if (!empty($fieldWizardHtml)) {
122 $mainFieldHtml[] = '<div class="form-wizards-items-bottom">';
123 $mainFieldHtml[] = $fieldWizardHtml;
124 $mainFieldHtml[] = '</div>';
125 }
126 $mainFieldHtml[] = '</div>';
127 $mainFieldHtml[] = '</div>';
128 $mainFieldHtml[] = '</div>';
129
130 $resultArray['html'] = implode(LF, $mainFieldHtml);
131 return $resultArray;
132 }
133
134 /**
135 * Render the prefix for the input field.
136 *
137 * @param SiteInterface $site
138 * @param int $requestLanguageId
139 * @return string
140 */
141 protected function getPrefix(SiteInterface $site, int $requestLanguageId = 0): string
142 {
143 $language = $site->getLanguageById($requestLanguageId);
144 $baseUrl = $language->getBase();
145 $baseUrl = rtrim($baseUrl, '/');
146 if (!empty($baseUrl)) {
147 $urlParts = parse_url($baseUrl);
148 if (!isset($urlParts['scheme']) && isset($urlParts['host'])) {
149 $baseUrl = 'http:' . $baseUrl;
150 }
151 }
152 return $baseUrl;
153 }
154
155 /**
156 * @return LanguageService
157 */
158 protected function getLanguageService(): LanguageService
159 {
160 return $GLOBALS['LANG'];
161 }
162 }