[TASK] Make TYPO3 Core PSR-2 standard compliant
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Form / FormDataProvider / TcaTypesShowitem.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\Core\Utility\GeneralUtility;
19 use TYPO3\CMS\Core\Utility\MathUtility;
20
21 /**
22 * Create final showitem configuration in processedTca for types and palette
23 * fields
24 * Handles all the nasty defails like subtypes_addlist and friends.
25 */
26 class TcaTypesShowitem implements FormDataProviderInterface
27 {
28 /**
29 * Processed TCA array
30 *
31 * @var array
32 */
33 protected $processedTca;
34
35 /**
36 * Set processedTca showitem
37 *
38 * @param array $result
39 * @return array
40 */
41 public function addData(array $result)
42 {
43 $this->processedTca = $result['processedTca'];
44
45 $recordTypeValue = $result['recordTypeValue'];
46
47 // Inline may override the type value - setting is given down from InlineRecordContainer if so - used primarily for FAL
48 if (!empty($result['overruleTypesArray'][$recordTypeValue]['showitem'])) {
49 $result['processedTca']['types'][$recordTypeValue]['showitem'] = $result['overruleTypesArray'][$recordTypeValue]['showitem'];
50 }
51
52 // Handle subtype_value_field, subtypes_addlist, subtypes_excludelist
53 if (!empty($result['processedTca']['types'][$recordTypeValue]['subtype_value_field'])) {
54 $subtypeFieldName = $result['processedTca']['types'][$recordTypeValue]['subtype_value_field'];
55 if (array_key_exists($subtypeFieldName, $result['databaseRow'])) {
56 $subtypeValue = $result['databaseRow'][$subtypeFieldName];
57 $result = $this->addFieldsBySubtypeAddList($result, $subtypeFieldName, $subtypeValue, $recordTypeValue);
58 $result = $this->removeFieldsBySubtypeExcludeList($result, $subtypeValue, $recordTypeValue);
59 }
60 }
61
62 // Handle bitmask_value_field, bitmask_excludelist_bits
63 if (!empty($result['processedTca']['types'][$recordTypeValue]['bitmask_value_field'])
64 && isset($result['processedTca']['types'][$recordTypeValue]['bitmask_excludelist_bits'])
65 && is_array($result['processedTca']['types'][$recordTypeValue]['bitmask_excludelist_bits'])
66 ) {
67 $bitmaskFieldName = $result['processedTca']['types'][$recordTypeValue]['bitmask_value_field'];
68 if (array_key_exists($bitmaskFieldName, $result['databaseRow'])) {
69 $bitmaskValue = $result['databaseRow'][$bitmaskFieldName];
70 $result = $this->removeFieldsByBitmaskExcludeBits($result, $bitmaskValue, $recordTypeValue);
71 }
72 }
73
74 // Handling of these parameters is finished. Unset them to not allow other handlers to fiddle with it.
75 // unset does not throw notice, even if not set
76 unset($result['processedTca']['types'][$recordTypeValue]['subtype_value_field']);
77 unset($result['processedTca']['types'][$recordTypeValue]['subtypes_excludelist']);
78 unset($result['processedTca']['types'][$recordTypeValue]['subtypes_addlist']);
79 unset($result['processedTca']['types'][$recordTypeValue]['bitmask_value_field']);
80 unset($result['processedTca']['types'][$recordTypeValue]['bitmask_excludelist_bits']);
81
82 return $result;
83 }
84
85 /**
86 * Insert additional fields in showitem based on subtypes_addlist
87 *
88 * databaseRow['theSubtypeValueField'] = 'theSubtypeValue'
89 * showitem = 'foo,theSubtypeValueField,bar'
90 * subtype_value_field = 'theSubtypeValueField'
91 * subtypes_addlist['theSubtypeValue'] = 'additionalField'
92 *
93 * -> showitem = 'foo,theSubtypeValueField,additionalField,bar'
94 *
95 * @param array $result Result array
96 * @param string $subtypeFieldName Field name holding subtype value
97 * @param string $subtypeValue subtype value
98 * @param string $recordTypeValue Given record type value
99 * @return array Modified result array
100 */
101 protected function addFieldsBySubtypeAddList(array $result, $subtypeFieldName, $subtypeValue, $recordTypeValue)
102 {
103 if (!empty($this->processedTca['types'][$recordTypeValue]['subtypes_addlist'][$subtypeValue])
104 && is_string($this->processedTca['types'][$recordTypeValue]['subtypes_addlist'][$subtypeValue])
105 ) {
106 $addListString = $this->processedTca['types'][$recordTypeValue]['subtypes_addlist'][$subtypeValue];
107 $addListArray = GeneralUtility::trimExplode(',', $addListString, true);
108 $showItemFieldString = $result['processedTca']['types'][$recordTypeValue]['showitem'];
109 $showItemFieldArray = GeneralUtility::trimExplode(',', $showItemFieldString, true);
110 // The "new" fields should be added after the subtype field itself, so find it
111 foreach ($showItemFieldArray as $index => $fieldConfigurationString) {
112 $found = false;
113 $fieldConfigurationArray = GeneralUtility::trimExplode(';', $fieldConfigurationString);
114 $fieldName = $fieldConfigurationArray[0];
115 if ($fieldName === $subtypeFieldName) {
116 // Found the subtype value field in showitem
117 $found = true;
118 } elseif ($fieldName === '--palette--') {
119 // Try to find subtype value field in palette
120 if (isset($fieldConfigurationArray[2])) {
121 $paletteName = $fieldConfigurationArray[2];
122 if (!empty($this->processedTca['palettes'][$paletteName]['showitem'])) {
123 $paletteFields = GeneralUtility::trimExplode(',', $this->processedTca['palettes'][$paletteName]['showitem'], true);
124 foreach ($paletteFields as $paletteFieldConfiguration) {
125 $paletteFieldConfigurationArray = GeneralUtility::trimExplode(';', $paletteFieldConfiguration);
126 if ($paletteFieldConfigurationArray[0] === $subtypeFieldName) {
127 // Found it in palette
128 $found = true;
129 break;
130 }
131 }
132 }
133 }
134 }
135 if ($found) {
136 // Add fields between subtype field and next element
137 array_splice($showItemFieldArray, $index + 1, 0, $addListArray);
138 break;
139 }
140 }
141 $result['processedTca']['types'][$recordTypeValue]['showitem'] = implode(',', $showItemFieldArray);
142 }
143 return $result;
144 }
145
146 /**
147 * Remove fields from showitem based on subtypes_excludelist
148 *
149 * databaseRow['theSubtypeValueField'] = 'theSubtypeValue'
150 * showitem = 'foo,toRemove,bar'
151 * subtype_value_field = 'theSubtypeValueField'
152 * subtypes_excludelist['theSubtypeValue'] = 'toRemove'
153 *
154 * -> showitem = 'foo,bar'
155 *
156 * @param array $result Result array
157 * @param string $subtypeValue subtype value
158 * @param string $recordTypeValue Given record type value
159 * @return array Modified result array
160 */
161 protected function removeFieldsBySubtypeExcludeList(array $result, $subtypeValue, $recordTypeValue)
162 {
163 if (!empty($this->processedTca['types'][$recordTypeValue]['subtypes_excludelist'][$subtypeValue])
164 && is_string($this->processedTca['types'][$recordTypeValue]['subtypes_excludelist'][$subtypeValue])
165 ) {
166 $removeListString = $this->processedTca['types'][$recordTypeValue]['subtypes_excludelist'][$subtypeValue];
167 $removeListArray = GeneralUtility::trimExplode(',', $removeListString, true);
168 $result = $this->removeFields($result, $removeListArray, $recordTypeValue);
169 $result = $this->removeFieldsFromPalettes($result, $removeListArray);
170 }
171 return $result;
172 }
173
174 /**
175 * Remove fields from showitem based on subtypes_excludelist
176 *
177 * databaseRow['theSubtypeValueField'] = 5 // 1 0 1
178 * showitem = 'foo,toRemoveBy4,bar'
179 * bitmask_value_field = 'theSubtypeValueField'
180 * bitmask_excludelist_bits[+2] = 'toRemoveBy4'
181 *
182 * -> showitem = 'foo,bar'
183 *
184 * @param array $result Result array
185 * @param string $bitmaskValue subtype value
186 * @param string $recordTypeValue Given record type value
187 * @return array Modified result array
188 */
189 protected function removeFieldsByBitmaskExcludeBits(array $result, $bitmaskValue, $recordTypeValue)
190 {
191 $removeListArray = array();
192 $bitmaskValue = MathUtility::forceIntegerInRange($bitmaskValue, 0);
193 $excludeListBitsArray = $this->processedTca['types'][$recordTypeValue]['bitmask_excludelist_bits'];
194 foreach ($excludeListBitsArray as $bitKey => $excludeList) {
195 $bitKey = (int)$bitKey;
196 $isNegative = (bool)($bitKey < 0);
197 $bit = abs($bitKey);
198 if (!$isNegative && ($bitmaskValue & pow(2, $bit))
199 || $isNegative && !($bitmaskValue & pow(2, $bit))
200 ) {
201 $removeListArray = array_merge($removeListArray, GeneralUtility::trimExplode(',', $excludeList, true));
202 }
203 }
204 $result = $this->removeFields($result, $removeListArray, $recordTypeValue);
205 return $this->removeFieldsFromPalettes($result, $removeListArray);
206 }
207
208 /**
209 * Remove fields from show item field list
210 *
211 * @param array $result Given show item list
212 * @param array $removeListArray Fields to remove
213 * @param string $recordTypeValue Given record type value
214 * @return array Modified result array
215 */
216 protected function removeFields(array $result, array $removeListArray, $recordTypeValue)
217 {
218 $newFieldList = array();
219 $showItemFieldString = $result['processedTca']['types'][$recordTypeValue]['showitem'];
220 $showItemFieldArray = GeneralUtility::trimExplode(',', $showItemFieldString, true);
221 foreach ($showItemFieldArray as $fieldConfigurationString) {
222 $fieldConfigurationArray = GeneralUtility::trimExplode(';', $fieldConfigurationString);
223 $fieldName = $fieldConfigurationArray[0];
224 if (!in_array($fieldConfigurationArray[0], $removeListArray, true)
225 // It does not make sense to exclude --palette-- and --div--
226 || $fieldName === '--palette--' || $fieldName === '--div--'
227 ) {
228 $newFieldList[] = $fieldConfigurationString;
229 }
230 }
231 $result['processedTca']['types'][$recordTypeValue]['showitem'] = implode(',', $newFieldList);
232 return $result;
233 }
234
235 /**
236 * Remove a list of element from all palettes
237 *
238 * @param array $result Result array
239 * @param array $removeListArray Array of elements to remove
240 * @return array Modified result array
241 * @todo: unit tests!
242 */
243 protected function removeFieldsFromPalettes(array $result, $removeListArray)
244 {
245 if (isset($result['processedTca']['palettes']) && is_array($result['processedTca']['palettes'])) {
246 foreach ($result['processedTca']['palettes'] as $paletteName => $paletteArray) {
247 if (!isset($paletteArray['showitem']) || !is_string($paletteArray['showitem'])) {
248 throw new \UnexpectedValueException(
249 'showitem field of palette ' . $paletteName . ' in table ' . $result['tableName'] . ' not found or not a string',
250 1439925240
251 );
252 }
253 $showItemFieldString = $paletteArray['showitem'];
254 $showItemFieldArray = GeneralUtility::trimExplode(',', $showItemFieldString, true);
255 $newFieldList = array();
256 foreach ($showItemFieldArray as $fieldConfigurationString) {
257 $fieldConfigurationArray = GeneralUtility::trimExplode(';', $fieldConfigurationString);
258 $fieldName = $fieldConfigurationArray[0];
259 if (!in_array($fieldConfigurationArray[0], $removeListArray, true)
260 || $fieldName === '--linebreak--'
261 ) {
262 $newFieldList[] = $fieldConfigurationString;
263 }
264 }
265 $result['processedTca']['palettes'][$paletteName]['showitem'] = implode(',', $newFieldList);
266 }
267 }
268 return $result;
269 }
270 }