TYPO3 CMS  TYPO3_8-7
PaletteAndSingleContainer.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 
20 
31 {
37  protected $resultArray = [];
38 
44  public function render()
45  {
46  $languageService = $this->getLanguageService();
47 
48  /*
49  * The first code block creates a target structure array to later create the final
50  * HTML string. The single fields and sub containers are rendered here already and
51  * other parts of the return array from children except html are accumulated in
52  * $this->resultArray
53  *
54  $targetStructure = array(
55  0 => array(
56  'type' => 'palette',
57  'fieldName' => 'palette1',
58  'fieldLabel' => 'palette1',
59  'elements' => array(
60  0 => array(
61  'type' => 'single',
62  'fieldName' => 'paletteName',
63  'fieldLabel' => 'element1',
64  'fieldHtml' => 'element1',
65  ),
66  1 => array(
67  'type' => 'linebreak',
68  ),
69  2 => array(
70  'type' => 'single',
71  'fieldName' => 'paletteName',
72  'fieldLabel' => 'element2',
73  'fieldHtml' => 'element2',
74  ),
75  ),
76  ),
77  1 => array(
78  'type' => 'single',
79  'fieldName' => 'element3',
80  'fieldLabel' => 'element3',
81  'fieldHtml' => 'element3',
82  ),
83  2 => array(
84  'type' => 'palette2',
85  'fieldName' => 'palette2',
86  'fieldLabel' => '', // Palettes may not have a label
87  'elements' => array(
88  0 => array(
89  'type' => 'single',
90  'fieldName' => 'element4',
91  'fieldLabel' => 'element4',
92  'fieldHtml' => 'element4',
93  ),
94  1 => array(
95  'type' => 'linebreak',
96  ),
97  2 => array(
98  'type' => 'single',
99  'fieldName' => 'element5',
100  'fieldLabel' => 'element5',
101  'fieldHtml' => 'element5',
102  ),
103  ),
104  ),
105  );
106  */
107 
108  // Create an intermediate structure of rendered sub elements and elements nested in palettes
109  $targetStructure = [];
110  $mainStructureCounter = -1;
111  $fieldsArray = $this->data['fieldsArray'];
112  $this->resultArray = $this->initializeResultArray();
113  foreach ($fieldsArray as $fieldString) {
114  $fieldConfiguration = $this->explodeSingleFieldShowItemConfiguration($fieldString);
115  $fieldName = $fieldConfiguration['fieldName'];
116  if ($fieldName === '--palette--') {
117  $paletteElementArray = $this->createPaletteContentArray($fieldConfiguration['paletteName']);
118  if (!empty($paletteElementArray)) {
119  $mainStructureCounter ++;
120  $targetStructure[$mainStructureCounter] = [
121  'type' => 'palette',
122  'fieldName' => $fieldConfiguration['paletteName'],
123  'fieldLabel' => $languageService->sL($fieldConfiguration['fieldLabel']),
124  'elements' => $paletteElementArray,
125  ];
126  }
127  } else {
128  if (!is_array($this->data['processedTca']['columns'][$fieldName])) {
129  continue;
130  }
131 
132  $options = $this->data;
133  $options['fieldName'] = $fieldName;
134 
135  $options['renderType'] = 'singleFieldContainer';
136  $childResultArray = $this->nodeFactory->create($options)->render();
137 
138  if (!empty($childResultArray['html'])) {
139  $mainStructureCounter ++;
140  $fieldLabel = '';
141  if (!empty($this->data['processedTca']['columns'][$fieldName]['label'])) {
142  $fieldLabel = $this->data['processedTca']['columns'][$fieldName]['label'];
143  }
144  $targetStructure[$mainStructureCounter] = [
145  'type' => 'single',
146  'fieldName' => $fieldConfiguration['fieldName'],
147  'fieldLabel' => $fieldLabel,
148  'fieldHtml' => $childResultArray['html'],
149  ];
150  }
151 
152  $this->resultArray = $this->mergeChildReturnIntoExistingResult($this->resultArray, $childResultArray, false);
153  }
154  }
155 
156  // Compile final content
157  $content = [];
158  foreach ($targetStructure as $element) {
159  if ($element['type'] === 'palette') {
160  $paletteName = $element['fieldName'];
161  $paletteElementsHtml = $this->renderInnerPaletteContent($element);
162 
163  $isHiddenPalette = !empty($this->data['processedTca']['palettes'][$paletteName]['isHiddenPalette']);
164 
165  $paletteElementsHtml = '<div class="row">' . $paletteElementsHtml . '</div>';
166 
167  $content[] = $this->fieldSetWrap($paletteElementsHtml, $isHiddenPalette, $element['fieldLabel']);
168  } else {
169  // Return raw HTML only in case of user element with no wrapping requested
170  if ($this->isUserNoTableWrappingField($element)) {
171  $content[] = $element['fieldHtml'];
172  } else {
173  $content[] = $this->fieldSetWrap($this->wrapSingleFieldContentWithLabelAndOuterDiv($element));
174  }
175  }
176  }
177 
178  $finalResultArray = $this->resultArray;
179  $finalResultArray['html'] = implode(LF, $content);
180  return $finalResultArray;
181  }
182 
189  protected function createPaletteContentArray($paletteName)
190  {
191  // palette needs a palette name reference, otherwise it does not make sense to try rendering of it
192  if (empty($paletteName) || empty($this->data['processedTca']['palettes'][$paletteName]['showitem'])) {
193  return [];
194  }
195 
196  $resultStructure = [];
197  $foundRealElement = false; // Set to true if not only line breaks were rendered
198  $fieldsArray = GeneralUtility::trimExplode(',', $this->data['processedTca']['palettes'][$paletteName]['showitem'], true);
199  foreach ($fieldsArray as $fieldString) {
200  $fieldArray = $this->explodeSingleFieldShowItemConfiguration($fieldString);
201  $fieldName = $fieldArray['fieldName'];
202  if ($fieldName === '--linebreak--') {
203  $resultStructure[] = [
204  'type' => 'linebreak',
205  ];
206  } else {
207  if (!is_array($this->data['processedTca']['columns'][$fieldName])) {
208  continue;
209  }
210  $options = $this->data;
211  $options['fieldName'] = $fieldName;
212 
213  $options['renderType'] = 'singleFieldContainer';
214  $singleFieldContentArray = $this->nodeFactory->create($options)->render();
215 
216  if (!empty($singleFieldContentArray['html'])) {
217  $foundRealElement = true;
218  $fieldLabel = '';
219  if (!empty($this->data['processedTca']['columns'][$fieldName]['label'])) {
220  $fieldLabel = $this->data['processedTca']['columns'][$fieldName]['label'];
221  }
222  $resultStructure[] = [
223  'type' => 'single',
224  'fieldName' => $fieldName,
225  'fieldLabel' => $fieldLabel,
226  'fieldHtml' => $singleFieldContentArray['html'],
227  ];
228  }
229  $this->resultArray = $this->mergeChildReturnIntoExistingResult($this->resultArray, $singleFieldContentArray, false);
230  }
231  }
232 
233  if ($foundRealElement) {
234  return $resultStructure;
235  }
236  return [];
237  }
238 
245  protected function renderInnerPaletteContent(array $elementArray)
246  {
247  // Group fields
248  $groupedFields = [];
249  $row = 0;
250  $lastLineWasLinebreak = true;
251  foreach ($elementArray['elements'] as $element) {
252  if ($element['type'] === 'linebreak') {
253  if (!$lastLineWasLinebreak) {
254  $row++;
255  $groupedFields[$row][] = $element;
256  $row++;
257  $lastLineWasLinebreak = true;
258  }
259  } else {
260  $lastLineWasLinebreak = false;
261  $groupedFields[$row][] = $element;
262  }
263  }
264 
265  $result = [];
266  // Process fields
267  foreach ($groupedFields as $fields) {
268  $numberOfItems = count($fields);
269  $colWidth = (int)floor(12 / $numberOfItems);
270  // Column class calculation
271  $colClass = 'col-md-12';
272  $colClear = [];
273  if ($colWidth == 6) {
274  $colClass = 'col-sm-6';
275  $colClear = [
276  2 => 'visible-sm-block visible-md-block visible-lg-block',
277  ];
278  } elseif ($colWidth === 4) {
279  $colClass = 'col-sm-4';
280  $colClear = [
281  3 => 'visible-sm-block visible-md-block visible-lg-block',
282  ];
283  } elseif ($colWidth === 3) {
284  $colClass = 'col-sm-6 col-md-3';
285  $colClear = [
286  2 => 'visible-sm-block',
287  4 => 'visible-md-block visible-lg-block',
288  ];
289  } elseif ($colWidth <= 2) {
290  $colClass = 'checkbox-column col-sm-6 col-md-3 col-lg-2';
291  $colClear = [
292  2 => 'visible-sm-block',
293  4 => 'visible-md-block',
294  6 => 'visible-lg-block'
295  ];
296  }
297 
298  // Render fields
299  for ($counter = 0; $counter < $numberOfItems; $counter++) {
300  $element = $fields[$counter];
301  if ($element['type'] === 'linebreak') {
302  if ($counter !== $numberOfItems) {
303  $result[] = '<div class="clearfix"></div>';
304  }
305  } else {
306  $result[] = $this->wrapSingleFieldContentWithLabelAndOuterDiv($element, [$colClass]);
307 
308  // Breakpoints
309  if ($counter + 1 < $numberOfItems && !empty($colClear)) {
310  foreach ($colClear as $rowBreakAfter => $clearClass) {
311  if (($counter + 1) % $rowBreakAfter === 0) {
312  $result[] = '<div class="clearfix ' . $clearClass . '"></div>';
313  }
314  }
315  }
316  }
317  }
318  }
319 
320  return implode(LF, $result);
321  }
322 
331  protected function fieldSetWrap($content, $paletteHidden = false, $label = '')
332  {
333  $fieldSetClass = 'form-section';
334  if ($paletteHidden) {
335  $fieldSetClass .= ' hide';
336  }
337 
338  $result = [];
339  $result[] = '<fieldset class="' . $fieldSetClass . '">';
340 
341  if (!empty($label)) {
342  $result[] = '<h4 class="form-section-headline">' . htmlspecialchars($label) . '</h4>';
343  }
344 
345  $result[] = $content;
346  $result[] = '</fieldset>';
347  return implode(LF, $result);
348  }
349 
357  protected function wrapSingleFieldContentWithLabelAndOuterDiv(array $element, array $additionalPaletteClasses = [])
358  {
359  $fieldName = $element['fieldName'];
360 
361  $paletteFieldClasses = [
362  'form-group',
363  't3js-formengine-validation-marker',
364  't3js-formengine-palette-field',
365  ];
366  foreach ($additionalPaletteClasses as $class) {
367  $paletteFieldClasses[] = $class;
368  }
369 
370  $label = BackendUtility::wrapInHelp($this->data['tableName'], $fieldName, htmlspecialchars($element['fieldLabel']));
371 
372  $content = [];
373  $content[] = '<div class="' . implode(' ', $paletteFieldClasses) . '">';
374  $content[] = '<label class="t3js-formengine-label">';
375  $content[] = $label;
376  $content[] = '</label>';
377  $content[] = $element['fieldHtml'];
378  $content[] = '</div>';
379 
380  return implode(LF, $content);
381  }
382 
389  protected function isUserNoTableWrappingField($element)
390  {
391  $fieldName = $element['fieldName'];
392  if (
393  $this->data['processedTca']['columns'][$fieldName]['config']['type'] === 'user'
394  && !empty($this->data['processedTca']['columns'][$fieldName]['config']['noTableWrapping'])
395  ) {
396  return true;
397  }
398  return false;
399  }
400 
404  protected function getLanguageService()
405  {
406  return $GLOBALS['LANG'];
407  }
408 }
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
$fields
Definition: pages.php:4
wrapSingleFieldContentWithLabelAndOuterDiv(array $element, array $additionalPaletteClasses=[])
mergeChildReturnIntoExistingResult(array $existing, array $childReturn, bool $mergeHtml=true)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']