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