TYPO3 CMS  TYPO3_7-6
FlexFormTools.php
Go to the documentation of this file.
1 <?php
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 
19 
24 {
30  public $convertCharset = false;
31 
38 
45 
52 
60  'parentTagMap' => [
61  'data' => 'sheet',
62  'sheet' => 'language',
63  'language' => 'field',
64  'el' => 'field',
65  'field' => 'value',
66  'field:el' => 'el',
67  'el:_IS_NUM' => 'section',
68  'section' => 'itemType'
69  ],
70  'disableTypeAttrib' => 2
71  ];
72 
78  public $callBackObj = null;
79 
85  public $cleanFlexFormXML = [];
86 
97  public function traverseFlexFormXMLData($table, $field, $row, $callBackObj, $callBackMethod_value)
98  {
99  if (!is_array($GLOBALS['TCA'][$table]) || !is_array($GLOBALS['TCA'][$table]['columns'][$field])) {
100  return 'TCA table/field was not defined.';
101  }
102  $this->callBackObj = $callBackObj;
103  // Get Data Structure:
104  $dataStructArray = BackendUtility::getFlexFormDS($GLOBALS['TCA'][$table]['columns'][$field]['config'], $row, $table, $field);
105  // If data structure was ok, proceed:
106  if (is_array($dataStructArray)) {
107  // Get flexform XML data:
108  $xmlData = $row[$field];
109  // Convert charset:
110  if ($this->convertCharset) {
111  $xmlHeaderAttributes = GeneralUtility::xmlGetHeaderAttribs($xmlData);
112  $storeInCharset = strtolower($xmlHeaderAttributes['encoding']);
113  if ($storeInCharset) {
114  $currentCharset = $GLOBALS['LANG']->charSet;
115  $xmlData = $GLOBALS['LANG']->csConvObj->conv($xmlData, $storeInCharset, $currentCharset, 1);
116  }
117  }
118  $editData = GeneralUtility::xml2array($xmlData);
119  if (!is_array($editData)) {
120  return 'Parsing error: ' . $editData;
121  }
122  // Tabs sheets
123  if (is_array($dataStructArray['sheets'])) {
124  $sKeys = array_keys($dataStructArray['sheets']);
125  } else {
126  $sKeys = ['sDEF'];
127  }
128  // Traverse languages:
129  foreach ($sKeys as $sheet) {
130  list($dataStruct, $sheet) = GeneralUtility::resolveSheetDefInDS($dataStructArray, $sheet);
131  // Render sheet:
132  if (is_array($dataStruct['ROOT']) && is_array($dataStruct['ROOT']['el'])) {
133  $PA['vKeys'] = ['DEF'];
134  $PA['lKey'] = 'lDEF';
135  $PA['callBackMethod_value'] = $callBackMethod_value;
136  $PA['table'] = $table;
137  $PA['field'] = $field;
138  $PA['uid'] = $row['uid'];
139  $this->traverseFlexFormXMLData_DS = &$dataStruct;
140  $this->traverseFlexFormXMLData_Data = &$editData;
141  // Render flexform:
142  $this->traverseFlexFormXMLData_recurse($dataStruct['ROOT']['el'], $editData['data'][$sheet]['lDEF'], $PA, 'data/' . $sheet . '/lDEF');
143  } else {
144  return 'Data Structure ERROR: No ROOT element found for sheet "' . $sheet . '".';
145  }
146  }
147  } else {
148  return 'Data Structure ERROR: ' . $dataStructArray;
149  }
150  }
151 
161  public function traverseFlexFormXMLData_recurse($dataStruct, $editData, &$PA, $path = '')
162  {
163  if (is_array($dataStruct)) {
164  foreach ($dataStruct as $key => $value) {
165  // The value of each entry must be an array.
166  if (is_array($value)) {
167  if ($value['type'] == 'array') {
168  // Array (Section) traversal
169  if ($value['section']) {
170  $cc = 0;
171  if (is_array($editData[$key]['el'])) {
172  if ($this->reNumberIndexesOfSectionData) {
173  $temp = [];
174  $c3 = 0;
175  foreach ($editData[$key]['el'] as $v3) {
176  $temp[++$c3] = $v3;
177  }
178  $editData[$key]['el'] = $temp;
179  }
180  foreach ($editData[$key]['el'] as $k3 => $v3) {
181  if (is_array($v3)) {
182  $cc = $k3;
183  $theType = key($v3);
184  $theDat = $v3[$theType];
185  $newSectionEl = $value['el'][$theType];
186  if (is_array($newSectionEl)) {
187  $this->traverseFlexFormXMLData_recurse([$theType => $newSectionEl], [$theType => $theDat], $PA, $path . '/' . $key . '/el/' . $cc);
188  }
189  }
190  }
191  }
192  } else {
193  // Array traversal
194  if (is_array($editData) && is_array($editData[$key])) {
195  $this->traverseFlexFormXMLData_recurse($value['el'], $editData[$key]['el'], $PA, $path . '/' . $key . '/el');
196  }
197  }
198  } elseif (is_array($value['TCEforms']['config'])) {
199  // Processing a field value:
200  foreach ($PA['vKeys'] as $vKey) {
201  $vKey = 'v' . $vKey;
202  // Call back
203  if ($PA['callBackMethod_value'] && is_array($editData) && is_array($editData[$key])) {
204  $this->executeCallBackMethod($PA['callBackMethod_value'], [$value, $editData[$key][$vKey], $PA, $path . '/' . $key . '/' . $vKey, $this]);
205  }
206  }
207  }
208  }
209  }
210  }
211  }
212 
220  protected function executeCallBackMethod($methodName, array $parameterArray)
221  {
222  return call_user_func_array([$this->callBackObj, $methodName], $parameterArray);
223  }
224 
231  public function getAvailableLanguages()
232  {
235  // Find all language records in the system
236  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
237  'language_isocode,static_lang_isocode,title,uid',
238  'sys_language',
239  'pid=0' . BackendUtility::deleteClause('sys_language'),
240  '',
241  'title'
242  );
243  // Traverse them
244  $output = [];
245  $output[0] = [
246  'uid' => 0,
247  'title' => 'Default language',
248  'ISOcode' => 'DEF'
249  ];
250  while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
251  $output[$row['uid']] = $row;
252  if (!empty($row['language_isocode'])) {
253  $output[$row['uid']]['ISOcode'] = $row['language_isocode'];
254  } elseif ($isL && $row['static_lang_isocode']) {
255  \TYPO3\CMS\Core\Utility\GeneralUtility::deprecationLog('Usage of the field "static_lang_isocode" is discouraged, and will stop working with CMS 8. Use the built-in language field "language_isocode" in your sys_language records.');
256  $rr = BackendUtility::getRecord('static_languages', $row['static_lang_isocode'], 'lg_iso_2');
257  if ($rr['lg_iso_2']) {
258  $output[$row['uid']]['ISOcode'] = $rr['lg_iso_2'];
259  }
260  }
261  if (!$output[$row['uid']]['ISOcode']) {
262  unset($output[$row['uid']]);
263  }
264  }
265  $GLOBALS['TYPO3_DB']->sql_free_result($res);
266  return $output;
267  }
268 
269  /***********************************
270  *
271  * Processing functions
272  *
273  ***********************************/
283  public function cleanFlexFormXML($table, $field, $row)
284  {
285  // New structure:
286  $this->cleanFlexFormXML = [];
287  // Create and call iterator object:
288  $flexObj = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools::class);
289  $flexObj->reNumberIndexesOfSectionData = true;
290  $flexObj->traverseFlexFormXMLData($table, $field, $row, $this, 'cleanFlexFormXML_callBackFunction');
291  return $this->flexArray2Xml($this->cleanFlexFormXML, true);
292  }
293 
305  public function cleanFlexFormXML_callBackFunction($dsArr, $data, $PA, $path, $pObj)
306  {
307  // Just setting value in our own result array, basically replicating the structure:
308  $pObj->setArrayValueByPath($path, $this->cleanFlexFormXML, $data);
309  }
310 
311  /***********************************
312  *
313  * Multi purpose functions
314  *
315  ***********************************/
323  public function &getArrayValueByPath($pathArray, &$array)
324  {
325  if (!is_array($pathArray)) {
326  $pathArray = explode('/', $pathArray);
327  }
328  if (is_array($array) && !empty($pathArray)) {
329  $key = array_shift($pathArray);
330  if (isset($array[$key])) {
331  if (empty($pathArray)) {
332  return $array[$key];
333  }
334  return $this->getArrayValueByPath($pathArray, $array[$key]);
335  }
336  return null;
337  }
338  }
339 
348  public function setArrayValueByPath($pathArray, &$array, $value)
349  {
350  if (isset($value)) {
351  if (!is_array($pathArray)) {
352  $pathArray = explode('/', $pathArray);
353  }
354  if (is_array($array) && !empty($pathArray)) {
355  $key = array_shift($pathArray);
356  if (empty($pathArray)) {
357  $array[$key] = $value;
358  return true;
359  }
360  if (!isset($array[$key])) {
361  $array[$key] = [];
362  }
363  return $this->setArrayValueByPath($pathArray, $array[$key], $value);
364  }
365  }
366  }
367 
375  public function flexArray2Xml($array, $addPrologue = false)
376  {
377  if ($GLOBALS['TYPO3_CONF_VARS']['BE']['flexformForceCDATA']) {
378  $this->flexArray2Xml_options['useCDATA'] = 1;
379  }
380  $options = $GLOBALS['TYPO3_CONF_VARS']['BE']['niceFlexFormXMLtags'] ? $this->flexArray2Xml_options : [];
381  $spaceInd = $GLOBALS['TYPO3_CONF_VARS']['BE']['compactFlexFormXML'] ? -1 : 4;
382  $output = GeneralUtility::array2xml($array, '', 0, 'T3FlexForms', $spaceInd, $options);
383  if ($addPrologue) {
384  $output = '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>' . LF . $output;
385  }
386  return $output;
387  }
388 }
static array2xml(array $array, $NSprefix='', $level=0, $docTag='phparray', $spaceInd=0, array $options=[], array $stackData=[])
static getFlexFormDS($conf, $row, $table, $fieldName='', $WSOL=true, $newRecordPidValue=0)
executeCallBackMethod($methodName, array $parameterArray)
traverseFlexFormXMLData_recurse($dataStruct, $editData, &$PA, $path='')
static resolveSheetDefInDS($dataStructArray, $sheet='sDEF')
cleanFlexFormXML_callBackFunction($dsArr, $data, $PA, $path, $pObj)
traverseFlexFormXMLData($table, $field, $row, $callBackObj, $callBackMethod_value)
static xml2array($string, $NSprefix='', $reportDocTag=false)
static getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static deleteClause($table, $tableAlias='')