[BUGFIX] Fix path to language file in SelectTreeElement
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Form / AbstractNode.php
1 <?php
2 declare(strict_types=1);
3 namespace TYPO3\CMS\Backend\Form;
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 Psr\Log\LoggerAwareInterface;
19 use Psr\Log\LoggerAwareTrait;
20 use TYPO3\CMS\Core\Utility\ArrayUtility;
21 use TYPO3\CMS\Core\Utility\GeneralUtility;
22
23 /**
24 * Base class for container and single elements - their abstracts extend from here.
25 */
26 abstract class AbstractNode implements NodeInterface, LoggerAwareInterface
27 {
28 use LoggerAwareTrait;
29
30 /**
31 * Instance of the node factory to create sub elements, container and single element expansions.
32 *
33 * @var NodeFactory
34 */
35 protected $nodeFactory;
36
37 /**
38 * Main data array to work on, given from parent to child elements
39 *
40 * @var array
41 */
42 protected $data = [];
43
44 /**
45 * A list of default field information added to the element / container.
46 *
47 * @var array
48 */
49 protected $defaultFieldInformation = [];
50
51 /**
52 * A list of default field controls added to the element / container.
53 * This property is often reset by single elements.
54 *
55 * @var array
56 */
57 protected $defaultFieldControl = [];
58
59 /**
60 * A list of default field wizards added to the element / container.
61 * This property is often reset by single elements.
62 *
63 * @var array
64 */
65 protected $defaultFieldWizard = [];
66
67 /**
68 * Set data to data array and register node factory to render sub elements
69 *
70 * @param NodeFactory $nodeFactory
71 * @param array $data
72 */
73 public function __construct(NodeFactory $nodeFactory, array $data)
74 {
75 $this->data = $data;
76 $this->nodeFactory = $nodeFactory;
77 }
78
79 /**
80 * Handler for single nodes
81 *
82 * @return array As defined in initializeResultArray() of AbstractNode
83 */
84 abstract public function render();
85
86 /**
87 * Initialize the array that is returned to parent after calling. This structure
88 * is identical for *all* nodes. Parent will merge the return of a child with its
89 * own stuff and in itself return an array of the same structure.
90 *
91 * @return array
92 */
93 protected function initializeResultArray(): array
94 {
95 return [
96 'additionalJavaScriptPost' => [],
97 'additionalJavaScriptSubmit' => [],
98 'additionalHiddenFields' => [],
99 'additionalInlineLanguageLabelFiles' => [],
100 'stylesheetFiles' => [],
101 // can hold strings or arrays,
102 // string = requireJS module,
103 // array = requireJS module + callback e.g. array('TYPO3/Foo/Bar', 'function() {}')
104 'requireJsModules' => [],
105 'inlineData' => [],
106 'html' => '',
107 ];
108 }
109
110 /**
111 * Merge existing data with a child return array
112 *
113 * @param array $existing Currently merged array
114 * @param array $childReturn Array returned by child
115 * @param bool $mergeHtml If false, the ['html'] section of $childReturn will NOT be added to $existing
116 * @return array Result array
117 */
118 protected function mergeChildReturnIntoExistingResult(array $existing, array $childReturn, bool $mergeHtml = true): array
119 {
120 if ($mergeHtml && !empty($childReturn['html'])) {
121 $existing['html'] .= LF . $childReturn['html'];
122 }
123 foreach ($childReturn['additionalJavaScriptPost'] as $value) {
124 $existing['additionalJavaScriptPost'][] = $value;
125 }
126 foreach ($childReturn['additionalJavaScriptSubmit'] as $value) {
127 $existing['additionalJavaScriptSubmit'][] = $value;
128 }
129 foreach ($childReturn['additionalHiddenFields'] as $value) {
130 $existing['additionalHiddenFields'][] = $value;
131 }
132 foreach ($childReturn['stylesheetFiles'] as $value) {
133 $existing['stylesheetFiles'][] = $value;
134 }
135 if (!empty($childReturn['requireJsModules'])) {
136 foreach ($childReturn['requireJsModules'] as $module) {
137 $existing['requireJsModules'][] = $module;
138 }
139 }
140 if (!empty($childReturn['additionalInlineLanguageLabelFiles'])) {
141 foreach ($childReturn['additionalInlineLanguageLabelFiles'] as $inlineLanguageLabelFile) {
142 $existing['additionalInlineLanguageLabelFiles'][] = $inlineLanguageLabelFile;
143 }
144 }
145 if (!empty($childReturn['inlineData'])) {
146 $existingInlineData = $existing['inlineData'];
147 $childInlineData = $childReturn['inlineData'];
148 ArrayUtility::mergeRecursiveWithOverrule($existingInlineData, $childInlineData);
149 $existing['inlineData'] = $existingInlineData;
150 }
151 return $existing;
152 }
153
154 /**
155 * Build JSON string for validations rules.
156 *
157 * @param array $config
158 * @return string
159 */
160 protected function getValidationDataAsJsonString(array $config): string
161 {
162 $validationRules = [];
163 if (!empty($config['eval'])) {
164 $evalList = GeneralUtility::trimExplode(',', $config['eval'], true);
165 foreach ($evalList as $evalType) {
166 $validationRules[] = [
167 'type' => $evalType,
168 ];
169 }
170 }
171 if (!empty($config['range'])) {
172 $newValidationRule = [
173 'type' => 'range',
174 ];
175 if (!empty($config['range']['lower'])) {
176 $newValidationRule['lower'] = $config['range']['lower'];
177 }
178 if (!empty($config['range']['upper'])) {
179 $newValidationRule['upper'] = $config['range']['upper'];
180 }
181 $validationRules[] = $newValidationRule;
182 }
183 if (!empty($config['maxitems']) || !empty($config['minitems'])) {
184 $minItems = (isset($config['minitems'])) ? (int)$config['minitems'] : 0;
185 $maxItems = (isset($config['maxitems'])) ? (int)$config['maxitems'] : 99999;
186 $type = ($config['type']) ?: 'range';
187 $validationRules[] = [
188 'type' => $type,
189 'minItems' => $minItems,
190 'maxItems' => $maxItems
191 ];
192 }
193 if (!empty($config['required'])) {
194 $validationRules[] = ['type' => 'required'];
195 }
196 return json_encode($validationRules);
197 }
198 }