[FEATURE] Reusable getCategoryFieldsForTable itemsProcFunc
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Form / FormDataProvider / EvaluateDisplayConditions.php
1 <?php
2 namespace TYPO3\CMS\Backend\Form\FormDataProvider;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Backend\Form\FormDataProviderInterface;
18 use TYPO3\CMS\Backend\Form\Utility\DisplayConditionEvaluator;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20
21 /**
22 * Class EvaluateDisplayConditions implements the TCA 'displayCond' option.
23 * The display condition is a colon separated string which describes
24 * the condition to decide whether a form field should be displayed.
25 */
26 class EvaluateDisplayConditions implements FormDataProviderInterface
27 {
28 /**
29 * Remove fields from processedTca columns that should not be displayed.
30 *
31 * @param array $result
32 * @return array
33 */
34 public function addData(array $result)
35 {
36 $result = $this->removeFlexformFields($result);
37 $result = $this->removeFlexformSheets($result);
38 $result = $this->removeTcaColumns($result);
39
40 return $result;
41 }
42
43 /**
44 * Evaluate the TCA column display conditions and remove columns that are not displayed
45 *
46 * @param array $result
47 * @return array
48 */
49 protected function removeTcaColumns($result)
50 {
51 foreach ($result['processedTca']['columns'] as $columnName => $columnConfiguration) {
52 if (!isset($columnConfiguration['displayCond'])) {
53 continue;
54 }
55
56 $displayConditionValid = $this->getDisplayConditionEvaluator()->evaluateDisplayCondition(
57 $columnConfiguration['displayCond'],
58 $result['databaseRow']
59 );
60 if (!$displayConditionValid) {
61 unset($result['processedTca']['columns'][$columnName]);
62 }
63 }
64
65 return $result;
66 }
67
68 /**
69 * Remove flexform sheets from processed tca if hidden by display conditions
70 *
71 * @param array $result
72 * @return array
73 */
74 protected function removeFlexformSheets($result)
75 {
76 foreach ($result['processedTca']['columns'] as $columnName => $columnConfiguration) {
77 if (!isset($columnConfiguration['config']['type'])
78 || $columnConfiguration['config']['type'] !== 'flex'
79 || !isset($result['processedTca']['columns'][$columnName]['config']['ds']['sheets'])
80 || !is_array($result['processedTca']['columns'][$columnName]['config']['ds']['sheets'])
81 ) {
82 continue;
83 }
84
85 $flexFormRowData = is_array($result['databaseRow'][$columnName]['data']) ? $result['databaseRow'][$columnName]['data'] : [];
86 $flexFormRowData = $this->flattenFlexformRowData($flexFormRowData);
87 $flexFormRowData['parentRec'] = $result['databaseRow'];
88
89 $flexFormSheets = $result['processedTca']['columns'][$columnName]['config']['ds']['sheets'];
90 foreach ($flexFormSheets as $sheetName => $sheetConfiguration) {
91 if (!isset($sheetConfiguration['ROOT']['displayCond'])) {
92 continue;
93 }
94 $displayConditionValid = $this->getDisplayConditionEvaluator()->evaluateDisplayCondition(
95 $sheetConfiguration['ROOT']['displayCond'],
96 $flexFormRowData,
97 true
98 );
99 if (!$displayConditionValid) {
100 unset($result['processedTca']['columns'][$columnName]['config']['ds']['sheets'][$sheetName]);
101 }
102 }
103 }
104
105 return $result;
106 }
107
108 /**
109 * Remove fields from flexform sheets if hidden by display conditions
110 *
111 * @param array $result
112 * @return array
113 */
114 protected function removeFlexformFields($result)
115 {
116 foreach ($result['processedTca']['columns'] as $columnName => $columnConfiguration) {
117 if (!isset($columnConfiguration['config']['type'])
118 || $columnConfiguration['config']['type'] !== 'flex'
119 || !isset($result['processedTca']['columns'][$columnName]['config']['ds']['sheets'])
120 || !is_array($result['processedTca']['columns'][$columnName]['config']['ds']['sheets'])
121 ) {
122 continue;
123 }
124
125 $flexFormRowData = is_array($result['databaseRow'][$columnName]['data']) ? $result['databaseRow'][$columnName]['data'] : [];
126 $flexFormRowData['parentRec'] = $result['databaseRow'];
127
128 foreach ($result['processedTca']['columns'][$columnName]['config']['ds']['sheets'] as $sheetName => $sheetConfiguration) {
129 $flexFormSheetRowData = $flexFormRowData[$sheetName]['lDEF'];
130 $flexFormSheetRowData['parentRec'] = $result['databaseRow'];
131 $result['processedTca']['columns'][$columnName]['config']['ds']['sheets'][$sheetName] = $this->removeFlexformFieldsRecursive(
132 $result['processedTca']['columns'][$columnName]['config']['ds']['sheets'][$sheetName],
133 $flexFormSheetRowData
134 );
135 }
136 }
137
138 return $result;
139 }
140
141 /**
142 * Remove fields from flexform data structure
143 *
144 * @param array $structure Given hierarchy
145 * @param array $flexFormRowData
146 * @return array Modified hierarchy
147 */
148 protected function removeFlexformFieldsRecursive($structure, $flexFormRowData)
149 {
150 $newStructure = [];
151 foreach ($structure as $key => $value) {
152 if ($key === 'el' && is_array($value)) {
153 $newSubStructure = [];
154 foreach ($value as $subKey => $subValue) {
155 if (!isset($subValue['displayCond']) || $this->getDisplayConditionEvaluator()->evaluateDisplayCondition($subValue['displayCond'], $flexFormRowData, true)) {
156 $newSubStructure[$subKey] = $subValue;
157 }
158 }
159 $value = $newSubStructure;
160 }
161 if (is_array($value)) {
162 $value = $this->removeFlexformFieldsRecursive($value, $flexFormRowData);
163 }
164 $newStructure[$key] = $value;
165 }
166
167 return $newStructure;
168 }
169
170 /**
171 * Flatten the Flexform data row for sheet level display conditions that use SheetName.FieldName
172 *
173 * @param array $flexFormRowData
174 * @return array
175 */
176 protected function flattenFlexformRowData($flexFormRowData)
177 {
178 $flatFlexFormRowData = [];
179 foreach ($flexFormRowData as $sheetName => $sheetConfiguration) {
180 foreach ($sheetConfiguration['lDEF'] as $fieldName => $fieldConfiguration) {
181 $flatFlexFormRowData[$sheetName . '.' . $fieldName] = $fieldConfiguration;
182 }
183 }
184
185 return $flatFlexFormRowData;
186 }
187
188 /**
189 * Returns the DisplayConditionEvaluator utility.
190 *
191 * @return DisplayConditionEvaluator
192 */
193 protected function getDisplayConditionEvaluator()
194 {
195 return GeneralUtility::makeInstance(DisplayConditionEvaluator::class);
196 }
197 }