‪TYPO3CMS  10.4
PaletteAndSingleContainer.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
22 
33 {
39  protected ‪$resultArray = [];
40 
46  public function ‪render()
47  {
48  $languageService = $this->‪getLanguageService();
49 
50  /*
51  * The first code block creates a target structure array to later create the final
52  * HTML string. The single fields and sub containers are rendered here already and
53  * other parts of the return array from children except html are accumulated in
54  * $this->resultArray
55  *
56  $targetStructure = array(
57  0 => array(
58  'type' => 'palette',
59  'fieldName' => 'palette1',
60  'fieldLabel' => 'palette1',
61  'elements' => array(
62  0 => array(
63  'type' => 'single',
64  'fieldName' => 'paletteName',
65  'fieldLabel' => 'element1',
66  'fieldHtml' => 'element1',
67  ),
68  1 => array(
69  'type' => 'linebreak',
70  ),
71  2 => array(
72  'type' => 'single',
73  'fieldName' => 'paletteName',
74  'fieldLabel' => 'element2',
75  'fieldHtml' => 'element2',
76  ),
77  ),
78  ),
79  1 => array(
80  'type' => 'single',
81  'fieldName' => 'element3',
82  'fieldLabel' => 'element3',
83  'fieldHtml' => 'element3',
84  ),
85  2 => array(
86  'type' => 'palette2',
87  'fieldName' => 'palette2',
88  'fieldLabel' => '', // Palettes may not have a label
89  'elements' => array(
90  0 => array(
91  'type' => 'single',
92  'fieldName' => 'element4',
93  'fieldLabel' => 'element4',
94  'fieldHtml' => 'element4',
95  ),
96  1 => array(
97  'type' => 'linebreak',
98  ),
99  2 => array(
100  'type' => 'single',
101  'fieldName' => 'element5',
102  'fieldLabel' => 'element5',
103  'fieldHtml' => 'element5',
104  ),
105  ),
106  ),
107  );
108  */
109 
110  // Create an intermediate structure of rendered sub elements and elements nested in palettes
111  $targetStructure = [];
112  $mainStructureCounter = -1;
113  $fieldsArray = $this->data['fieldsArray'];
114  $this->resultArray = $this->‪initializeResultArray();
115  foreach ($fieldsArray as $fieldString) {
116  $fieldConfiguration = $this->‪explodeSingleFieldShowItemConfiguration($fieldString);
117  $fieldName = $fieldConfiguration['fieldName'];
118  if ($fieldName === '--palette--') {
119  $paletteElementArray = $this->‪createPaletteContentArray($fieldConfiguration['paletteName']);
120  if (!empty($paletteElementArray)) {
121  $mainStructureCounter++;
122  $paletteLabel = $fieldConfiguration['fieldLabel'];
123  if ($paletteLabel === null
124  && !empty($this->data['processedTca']['palettes'][$fieldConfiguration['paletteName']]['label'])
125  ) {
126  // If there is no label in ['types']['aType']['showitem'] for this palette: "--palette--;;aPalette" but
127  // not "--palette--;LLL:aLabelReference;aPalette", then use ['palettes']['aPalette']['label'] if given.
128  $paletteLabel = $this->data['processedTca']['palettes'][$fieldConfiguration['paletteName']]['label'];
129  }
130  $targetStructure[$mainStructureCounter] = [
131  'type' => 'palette',
132  'fieldName' => $fieldConfiguration['paletteName'],
133  'fieldLabel' => $languageService->sL($paletteLabel),
134  'elements' => $paletteElementArray,
135  ];
136  }
137  } else {
138  if (!is_array($this->data['processedTca']['columns'][$fieldName])) {
139  continue;
140  }
141 
142  $options = ‪$this->data;
143  $options['fieldName'] = $fieldName;
144 
145  $options['renderType'] = 'singleFieldContainer';
146  $childResultArray = $this->nodeFactory->create($options)->render();
147 
148  if (!empty($childResultArray['html'])) {
149  $mainStructureCounter++;
150  $fieldLabel = '';
151  if (!empty($this->data['processedTca']['columns'][$fieldName]['label'])) {
152  $fieldLabel = $this->data['processedTca']['columns'][$fieldName]['label'];
153  }
154  $targetStructure[$mainStructureCounter] = [
155  'type' => 'single',
156  'fieldName' => $fieldConfiguration['fieldName'],
157  'fieldLabel' => $fieldLabel,
158  'fieldHtml' => $childResultArray['html'],
159  ];
160  }
161 
162  $this->resultArray = $this->‪mergeChildReturnIntoExistingResult($this->resultArray, $childResultArray, false);
163  }
164  }
165 
166  // Compile final content
167  $content = [];
168  foreach ($targetStructure as $element) {
169  if ($element['type'] === 'palette') {
170  $paletteName = $element['fieldName'];
171  $paletteElementsHtml = $this->‪renderInnerPaletteContent($element);
172 
173  $isHiddenPalette = !empty($this->data['processedTca']['palettes'][$paletteName]['isHiddenPalette']);
174 
175  $paletteElementsHtml = '<div class="row">' . $paletteElementsHtml . '</div>';
176 
177  $content[] = $this->‪fieldSetWrap($paletteElementsHtml, $isHiddenPalette, $element['fieldLabel']);
178  } else {
179  // Return raw HTML only in case of user element with no wrapping requested
180  if ($this->‪isUserNoTableWrappingField($element)) {
181  $content[] = $element['fieldHtml'];
182  } else {
183  $content[] = $this->‪fieldSetWrap($this->‪wrapSingleFieldContentWithLabelAndOuterDiv($element));
184  }
185  }
186  }
187 
188  $finalResultArray = ‪$this->resultArray;
189  $finalResultArray['html'] = implode(LF, $content);
190  return $finalResultArray;
191  }
192 
199  protected function ‪createPaletteContentArray($paletteName)
200  {
201  // palette needs a palette name reference, otherwise it does not make sense to try rendering of it
202  if (empty($paletteName) || empty($this->data['processedTca']['palettes'][$paletteName]['showitem'])) {
203  return [];
204  }
205 
206  $resultStructure = [];
207  $foundRealElement = false; // Set to true if not only line breaks were rendered
208  $fieldsArray = ‪GeneralUtility::trimExplode(',', $this->data['processedTca']['palettes'][$paletteName]['showitem'], true);
209  foreach ($fieldsArray as $fieldString) {
210  $fieldArray = $this->‪explodeSingleFieldShowItemConfiguration($fieldString);
211  $fieldName = $fieldArray['fieldName'];
212  if ($fieldName === '--linebreak--') {
213  $resultStructure[] = [
214  'type' => 'linebreak',
215  ];
216  } else {
217  if (!is_array($this->data['processedTca']['columns'][$fieldName])) {
218  continue;
219  }
220  $options = ‪$this->data;
221  $options['fieldName'] = $fieldName;
222 
223  $options['renderType'] = 'singleFieldContainer';
224  $singleFieldContentArray = $this->nodeFactory->create($options)->render();
225 
226  if (!empty($singleFieldContentArray['html'])) {
227  $foundRealElement = true;
228  $fieldLabel = '';
229  if (!empty($this->data['processedTca']['columns'][$fieldName]['label'])) {
230  $fieldLabel = $this->data['processedTca']['columns'][$fieldName]['label'];
231  }
232  $resultStructure[] = [
233  'type' => 'single',
234  'fieldName' => $fieldName,
235  'fieldLabel' => $fieldLabel,
236  'fieldHtml' => $singleFieldContentArray['html'],
237  ];
238  }
239  $this->resultArray = $this->‪mergeChildReturnIntoExistingResult($this->resultArray, $singleFieldContentArray, false);
240  }
241  }
242 
243  if ($foundRealElement) {
244  return $resultStructure;
245  }
246  return [];
247  }
248 
255  protected function ‪renderInnerPaletteContent(array $elementArray)
256  {
257  // Group fields
258  $groupedFields = [];
259  $row = 0;
260  $lastLineWasLinebreak = true;
261  foreach ($elementArray['elements'] as $element) {
262  if ($element['type'] === 'linebreak') {
263  if (!$lastLineWasLinebreak) {
264  $row++;
265  $groupedFields[$row][] = $element;
266  $row++;
267  $lastLineWasLinebreak = true;
268  }
269  } else {
270  $lastLineWasLinebreak = false;
271  $groupedFields[$row][] = $element;
272  }
273  }
274 
275  $result = [];
276  // Process fields
277  foreach ($groupedFields as ‪$fields) {
278  $numberOfItems = count(‪$fields);
279  $colWidth = (int)floor(12 / $numberOfItems);
280  // Column class calculation
281  $colClass = 'col-md-12';
282  $colClear = [];
283  if ($colWidth == 6) {
284  $colClass = 'col-sm-6';
285  $colClear = [
286  2 => 'visible-sm-block visible-md-block visible-lg-block',
287  ];
288  } elseif ($colWidth === 4) {
289  $colClass = 'col-sm-4';
290  $colClear = [
291  3 => 'visible-sm-block visible-md-block visible-lg-block',
292  ];
293  } elseif ($colWidth === 3) {
294  $colClass = 'col-sm-6 col-md-3';
295  $colClear = [
296  2 => 'visible-sm-block',
297  4 => 'visible-md-block visible-lg-block',
298  ];
299  } elseif ($colWidth <= 2) {
300  $colClass = 'checkbox-column col-sm-6 col-md-3 col-lg-2';
301  $colClear = [
302  2 => 'visible-sm-block',
303  4 => 'visible-md-block',
304  6 => 'visible-lg-block'
305  ];
306  }
307 
308  // Render fields
309  for ($counter = 0; $counter < $numberOfItems; $counter++) {
310  $element = ‪$fields[$counter];
311  if ($element['type'] === 'linebreak') {
312  if ($counter !== $numberOfItems) {
313  $result[] = '<div class="clearfix"></div>';
314  }
315  } else {
316  $result[] = $this->‪wrapSingleFieldContentWithLabelAndOuterDiv($element, [$colClass]);
317 
318  // Breakpoints
319  if ($counter + 1 < $numberOfItems && !empty($colClear)) {
320  foreach ($colClear as $rowBreakAfter => $clearClass) {
321  if (($counter + 1) % $rowBreakAfter === 0) {
322  $result[] = '<div class="clearfix ' . $clearClass . '"></div>';
323  }
324  }
325  }
326  }
327  }
328  }
329 
330  return implode(LF, $result);
331  }
332 
341  protected function ‪fieldSetWrap($content, $paletteHidden = false, $label = '')
342  {
343  $fieldSetClass = 'form-section';
344  if ($paletteHidden) {
345  $fieldSetClass .= ' hide';
346  }
347 
348  $result = [];
349  $result[] = '<fieldset class="' . $fieldSetClass . '">';
350 
351  if (!empty($label)) {
352  $result[] = '<h4 class="form-section-headline">' . htmlspecialchars($label) . '</h4>';
353  }
354 
355  $result[] = $content;
356  $result[] = '</fieldset>';
357  return implode(LF, $result);
358  }
359 
367  protected function ‪wrapSingleFieldContentWithLabelAndOuterDiv(array $element, array $additionalPaletteClasses = [])
368  {
369  $fieldName = $element['fieldName'];
370 
371  $paletteFieldClasses = [
372  'form-group',
373  't3js-formengine-validation-marker',
374  't3js-formengine-palette-field',
375  ];
376  foreach ($additionalPaletteClasses as $class) {
377  $paletteFieldClasses[] = $class;
378  }
379 
380  $label = ‪BackendUtility::wrapInHelp($this->data['tableName'], $fieldName, htmlspecialchars($element['fieldLabel']));
381 
382  if (‪$GLOBALS['TYPO3_CONF_VARS']['BE']['debug'] && $this->‪getBackendUser()->isAdmin()) {
383  $label .= '<code>[' . htmlspecialchars($fieldName) . ']</code>';
384  }
385 
386  $content = [];
387  $content[] = '<div class="' . implode(' ', $paletteFieldClasses) . '">';
388  $content[] = '<label class="t3js-formengine-label">';
389  $content[] = $label;
390  $content[] = '</label>';
391  $content[] = $element['fieldHtml'];
392  $content[] = '</div>';
393 
394  return implode(LF, $content);
395  }
396 
403  protected function ‪isUserNoTableWrappingField($element)
404  {
405  $fieldName = $element['fieldName'];
406  if (
407  $this->data['processedTca']['columns'][$fieldName]['config']['type'] === 'user'
408  && !empty($this->data['processedTca']['columns'][$fieldName]['config']['noTableWrapping'])
409  ) {
410  return true;
411  }
412  return false;
413  }
414 
418  protected function ‪getLanguageService()
419  {
420  return ‪$GLOBALS['LANG'];
421  }
422 
428  protected function ‪getBackendUser()
429  {
430  return ‪$GLOBALS['BE_USER'];
431  }
432 }
‪TYPO3\CMS\Backend\Form\Container\PaletteAndSingleContainer\createPaletteContentArray
‪array createPaletteContentArray($paletteName)
Definition: PaletteAndSingleContainer.php:198
‪TYPO3\CMS\Backend\Form\Container\PaletteAndSingleContainer\getBackendUser
‪BackendUserAuthentication getBackendUser()
Definition: PaletteAndSingleContainer.php:427
‪TYPO3\CMS\Backend\Form\AbstractNode\mergeChildReturnIntoExistingResult
‪array mergeChildReturnIntoExistingResult(array $existing, array $childReturn, bool $mergeHtml=true)
Definition: AbstractNode.php:116
‪TYPO3\CMS\Backend\Form\AbstractNode\initializeResultArray
‪array initializeResultArray()
Definition: AbstractNode.php:90
‪TYPO3\CMS\Backend\Form\Container\PaletteAndSingleContainer\getLanguageService
‪LanguageService getLanguageService()
Definition: PaletteAndSingleContainer.php:417
‪TYPO3\CMS\Backend\Form\Container\PaletteAndSingleContainer\renderInnerPaletteContent
‪string renderInnerPaletteContent(array $elementArray)
Definition: PaletteAndSingleContainer.php:254
‪TYPO3\CMS\Backend\Form\Container
Definition: AbstractContainer.php:16
‪$fields
‪$fields
Definition: pages.php:5
‪TYPO3\CMS\Backend\Utility\BackendUtility\wrapInHelp
‪static string wrapInHelp($table, $field, $text='', array $overloadHelpText=[])
Definition: BackendUtility.php:2260
‪TYPO3\CMS\Backend\Form\Container\AbstractContainer\explodeSingleFieldShowItemConfiguration
‪array explodeSingleFieldShowItemConfiguration($field)
Definition: AbstractContainer.php:90
‪TYPO3\CMS\Backend\Form\AbstractNode\$data
‪array $data
Definition: AbstractNode.php:42
‪TYPO3\CMS\Backend\Form\Container\AbstractContainer
Definition: AbstractContainer.php:28
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Backend\Form\Container\PaletteAndSingleContainer\fieldSetWrap
‪string fieldSetWrap($content, $paletteHidden=false, $label='')
Definition: PaletteAndSingleContainer.php:340
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:75
‪TYPO3\CMS\Backend\Form\Container\PaletteAndSingleContainer\$resultArray
‪array $resultArray
Definition: PaletteAndSingleContainer.php:38
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static string[] trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:1059
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:42
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Backend\Form\Container\PaletteAndSingleContainer\isUserNoTableWrappingField
‪bool isUserNoTableWrappingField($element)
Definition: PaletteAndSingleContainer.php:402
‪TYPO3\CMS\Backend\Form\Container\PaletteAndSingleContainer
Definition: PaletteAndSingleContainer.php:33
‪TYPO3\CMS\Backend\Form\Container\PaletteAndSingleContainer\render
‪array render()
Definition: PaletteAndSingleContainer.php:45
‪TYPO3\CMS\Backend\Form\Container\PaletteAndSingleContainer\wrapSingleFieldContentWithLabelAndOuterDiv
‪string wrapSingleFieldContentWithLabelAndOuterDiv(array $element, array $additionalPaletteClasses=[])
Definition: PaletteAndSingleContainer.php:366