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