Fixed issue #17284: Formprotection persistToken method is called too often, causing...
[Packages/TYPO3.CMS.git] / t3lib / tceforms / class.t3lib_tceforms_flexforms.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2010-2011 Kai Vogel (kai.vogel(at)speedprogs.de)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27
28
29 /**
30 * Contains FlexForm manipulation methods as part of the TCEforms
31 *
32 * @author Kai Vogel <kai.vogel(at)speedprogs.de>
33 */
34 class t3lib_TCEforms_Flexforms extends t3lib_TCEforms {
35
36 /**
37 * Options that will be removed from config after creating items for a select to prevent double parsing
38 *
39 * @var array
40 */
41 protected $removeSelectConfig = array(
42 'itemsProcFunc',
43 'foreign_table',
44 'foreign_table_where',
45 'foreign_table_prefix',
46 'foreign_table_loadIcons',
47 'neg_foreign_table',
48 'neg_foreign_table_where',
49 'neg_foreign_table_prefix',
50 'neg_foreign_table_loadIcons',
51 'neg_foreign_table_imposeValueField',
52 'fileFolder',
53 'fileFolder_extList',
54 'fileFolder_recursions',
55 'MM',
56 'MM_opposite_field',
57 'MM_match_fields',
58 'MM_insert_fields',
59 'MM_table_where',
60 'MM_hasUidField',
61 'special',
62 );
63
64 /**
65 * Modify the Data Structure of a FlexForm field via TSconfig and group access lists
66 *
67 * @param array $dataStructure The data structure of the FlexForm field
68 * @param string $table The table name of the record
69 * @param string $tableField The field name
70 * @param array $tableRow The record data
71 * @param array $tableConf Additional configuration options
72 * @return array Modified FlexForm DS
73 * @see t3lib_TCEforms::getSingleField_typeFlex()
74 */
75 public function modifyFlexFormDS(array $dataStructure, $table, $tableField, array $tableRow, array $tableConf) {
76 $singleSheet = (!isset($dataStructure['sheets']) || !is_array($dataStructure['sheets']));
77 $metaConf = (!empty($dataStructure['meta']) ? $dataStructure['meta'] : array());
78 $sheetConf = array();
79
80 // Get extension identifier (uses second pointer field if it's value is not empty, "list" or "*", else it must be a plugin and first one will be used)
81 $pointerFields = (!empty($tableConf['config']['ds_pointerField']) ? $tableConf['config']['ds_pointerField'] : 'list_type,CType');
82 $pointerFields = t3lib_div::trimExplode(',', $pointerFields);
83 $flexformIdentifier = (!empty($tableRow[$pointerFields[0]]) ? $tableRow[$pointerFields[0]] : '');
84 if (!empty($tableRow[$pointerFields[1]]) && $tableRow[$pointerFields[1]] != 'list' && $tableRow[$pointerFields[1]] != '*') {
85 $flexformIdentifier = $tableRow[$pointerFields[1]];
86 }
87 if (empty($flexformIdentifier)) {
88 return $dataStructure;
89 }
90
91 // Get field configuration from page TSConfig
92 $TSconfig = $this->setTSconfig($table, $tableRow);
93 if (!empty($TSconfig[$tableField][$flexformIdentifier . '.'])) {
94 $sheetConf = t3lib_div::removeDotsFromTS($TSconfig[$tableField][$flexformIdentifier . '.']);
95 }
96 ;
97
98 // Get non-exclude-fields from group access lists
99 $nonExcludeFields = $this->getFlexFormNonExcludeFields($table, $tableField, $flexformIdentifier);
100
101 // Load complete DS, including external file references
102 $dataStructure = t3lib_div::resolveAllSheetsInDS($dataStructure);
103
104 // Modify flexform sheets
105 foreach ($dataStructure['sheets'] as $sheetName => $sheet) {
106 if (empty($sheet['ROOT']['el']) || !is_array($sheet['ROOT']['el'])) {
107 continue;
108 }
109
110 // Remove whole sheet (tab) if disabled
111 if (!empty($sheetConf[$sheetName]['disabled'])) {
112 unset($dataStructure['sheets'][$sheetName]);
113 continue;
114 }
115
116 // Rename sheet (tab)
117 if (!empty($sheetConf[$sheetName]['title'])) {
118 $dataStructure['sheets'][$sheetName]['ROOT']['TCEforms']['sheetTitle'] = $sheetConf[$sheetName]['title'];
119 }
120
121 // Modify all configured fields in sheet
122 $dataStructure['sheets'][$sheetName]['ROOT']['el'] = $this->modifySingleFlexFormSheet(
123 $sheet['ROOT']['el'],
124 $table,
125 $tableField,
126 $tableRow,
127 (!empty($sheetConf[$sheetName]) ? $sheetConf[$sheetName] : array()),
128 (!empty($nonExcludeFields[$sheetName]) ? $nonExcludeFields[$sheetName] : array())
129 );
130
131 // Remove empty sheet (tab)
132 if (empty($dataStructure['sheets'][$sheetName]['ROOT']['el'])) {
133 unset($dataStructure['sheets'][$sheetName]);
134 }
135 }
136
137 // Recover single flexform structure
138 if ($singleSheet && isset($dataStructure['sheets']['sDEF'])) {
139 $dataStructure = $dataStructure['sheets']['sDEF'];
140 }
141
142 // Recover meta configuration
143 if (!empty($metaConf)) {
144 $dataStructure['meta'] = $metaConf;
145 }
146
147 return $dataStructure;
148 }
149
150 /**
151 * Modify a single FlexForm sheet according to given configuration
152 *
153 * @param array $sheet Flexform sheet to manipulate
154 * @param string $table The table name
155 * @param string $tableField The field name
156 * @param array $tableRow The record data
157 * @param array $sheetConf Sheet configuration
158 * @param array $nonExcludeFields Non-exclude-fields for this sheet
159 * @return array Modified sheet
160 * @see t3lib_TCEforms_flex::modifyFlexFormDS()
161 */
162 public function modifySingleFlexFormSheet(array $sheet, $table, $tableField, array $tableRow, array $sheetConf, array $nonExcludeFields) {
163 if (empty($sheet) || empty($table) || empty($tableField) || empty($tableRow)) {
164 return $sheet;
165 }
166
167 // Modify fields
168 foreach ($sheet as $fieldName => $field) {
169
170 // Remove excluded fields
171 if (!$GLOBALS['BE_USER']->isAdmin() && !empty($field['TCEforms']['exclude']) && empty($nonExcludeFields[$fieldName])) {
172 unset($sheet[$fieldName]);
173 continue;
174 }
175
176 // Stop here if no TSConfig was found for this field
177 if (empty($sheetConf[$fieldName]) || !is_array($sheetConf[$fieldName])) {
178 continue;
179 }
180
181 // Remove disabled fields
182 if (!empty($sheetConf[$fieldName]['disabled'])) {
183 unset($sheet[$fieldName]);
184 continue;
185 }
186
187 $fieldConf = $sheetConf[$fieldName];
188 $removeItems = (!empty($fieldConf['removeItems']) ? t3lib_div::trimExplode(',', $fieldConf['removeItems'], TRUE) : array());
189 $keepItems = (!empty($fieldConf['keepItems']) ? t3lib_div::trimExplode(',', $fieldConf['keepItems'], TRUE) : array());
190 $renameItems = (!empty($fieldConf['altLabels']) && is_array($fieldConf['altLabels']) ? $fieldConf['altLabels'] : array());
191 $addItems = (!empty($fieldConf['addItems']) && is_array($fieldConf['addItems']) ? $fieldConf['addItems'] : array());
192
193 unset($fieldConf['removeItems']);
194 unset($fieldConf['keepItems']);
195 unset($fieldConf['altLabels']);
196 unset($fieldConf['addItems']);
197
198 // Manipulate field
199 if (!empty($field['TCEforms']) && is_array($field['TCEforms'])) {
200 $sheet[$fieldName]['TCEforms'] = t3lib_div::array_merge_recursive_overrule($field['TCEforms'], $fieldConf);
201 }
202
203 // Manipulate only select fields, other field types will stop here
204 if (empty($field['TCEforms']['config']['type']) || $field['TCEforms']['config']['type'] != 'select') {
205 continue;
206 }
207
208 // Getting the selector box items from system
209 $selItems = $this->addSelectOptionsToItemArray(
210 $this->initItemArray($field['TCEforms']),
211 $field['TCEforms'],
212 $this->setTSconfig($table, $tableRow),
213 $tableField
214 );
215
216 // Possibly filter some items
217 $keepItemsFunc = create_function('$value', 'return $value[1];');
218 $selItems = t3lib_div::keepItemsInArray($selItems, $keepItems, $keepItemsFunc);
219
220 // Possibly add some items
221 $selItems = $this->addItems($selItems, $addItems);
222
223 // Process items by a user function
224 if (!empty($field['TCEforms']['config']['itemsProcFunc'])) {
225 $selItems = $this->procItems(
226 $selItems,
227 $fieldConf['config'],
228 $field['TCEforms']['config'],
229 $table,
230 $tableRow,
231 $tableField
232 );
233 }
234
235 // Remove special configuration options after creating items to prevent double parsing
236 foreach ($this->removeSelectConfig as $option) {
237 unset($sheet[$fieldName]['TCEforms']['config'][$option]);
238 }
239
240 // Rename and remove items in select
241 if ((!empty($removeItems) || !empty($renameItems)) && !empty($selItems) && is_array($selItems)) {
242 foreach ($selItems as $itemKey => $itemConf) {
243 // Option has no key, no manipulation possible
244 if (!isset($itemConf[1])) {
245 continue;
246 }
247
248 // Remove
249 foreach ($removeItems as $removeKey => $removeValue) {
250 if (strcasecmp($removeValue, $itemConf[1]) == 0) {
251 unset($selItems[$itemKey]);
252 unset($removeItems[$removeKey]);
253 }
254 }
255
256 // Rename
257 foreach ($renameItems as $renameKey => $renameValue) {
258 if (strcasecmp($renameKey, $itemConf[1]) == 0) {
259 $selItems[$itemKey][0] = $renameValue;
260 unset($renameItems[$renameKey]);
261 }
262 }
263 }
264 }
265
266 $sheet[$fieldName]['TCEforms']['config']['items'] = $selItems;
267
268 }
269
270 return $sheet;
271 }
272
273 /**
274 * Get FlexForm non-exclude-fields for current backend user
275 *
276 * @param string $table The table name
277 * @param string $tableField The field name
278 * @param string $extIdent The extension identifier
279 * @return array All non_exclude_fields from FlexForms
280 * @see t3lib_TCEforms::getSingleField_typeFlex()
281 */
282 protected function getFlexFormNonExcludeFields($table, $tableField, $extIdent) {
283 if (empty($GLOBALS['BE_USER']->groupData['non_exclude_fields']) || empty($table) || empty($tableField) || empty($extIdent)) {
284 return array();
285 }
286
287 $accessListFields = t3lib_div::trimExplode(',', $GLOBALS['BE_USER']->groupData['non_exclude_fields']);
288 $identPrefix = $table . ':' . $tableField . ';' . $extIdent . ';';
289 $nonExcludeFields = array();
290
291 // Collect only FlexForm fields
292 foreach ($accessListFields as $field) {
293 if (strpos($field, $identPrefix) !== FALSE) {
294 list(, , $sheetName, $fieldName) = explode(';', $field);
295 $nonExcludeFields[$sheetName][$fieldName] = TRUE;
296 }
297 }
298
299 return $nonExcludeFields;
300 }
301
302 /**
303 * Compare two arrays by their first value
304 *
305 * @param array $array1 First array
306 * @param array $array2 Second array
307 * @return integer Negative int if first array is lower, zero if both are identical, and positive if second is higher
308 */
309 public static function compareArraysByFirstValue(array $array1, array $array2) {
310 $array1 = reset($array1);
311 $array2 = reset($array2);
312
313 if (is_string($array1) && is_string($array2)) {
314 return strcasecmp($array1, $array2);
315 }
316
317 return 0;
318 }
319
320 }
321
322 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['classes/t3lib/tceforms/class.t3lib_tceforms_flexforms.php']) {
323 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['classes/t3lib/tceforms/class.t3lib_tceforms_flexforms.php']);
324 }
325
326 ?>