TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
PaletteAndSingleContainer.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Backend\Form\Container;
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 
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  $childResultArray['html'] = '';
153  $this->resultArray = $this->mergeChildReturnIntoExistingResult($this->resultArray, $childResultArray);
154  }
155  }
156 
157  // Compile final content
158  $content = [];
159  foreach ($targetStructure as $element) {
160  if ($element['type'] === 'palette') {
161  $paletteName = $element['fieldName'];
162  $paletteElementsHtml = $this->renderInnerPaletteContent($element);
163 
164  $isHiddenPalette = !empty($this->data['processedTca']['palettes'][$paletteName]['isHiddenPalette']);
165 
166  $paletteElementsHtml = '<div class="row">' . $paletteElementsHtml . '</div>';
167 
168  $content[] = $this->fieldSetWrap($paletteElementsHtml, $isHiddenPalette, $element['fieldLabel']);
169  } else {
170  // Return raw HTML only in case of user element with no wrapping requested
171  if ($this->isUserNoTableWrappingField($element)) {
172  $content[] = $element['fieldHtml'];
173  } else {
174  $content[] = $this->fieldSetWrap($this->wrapSingleFieldContentWithLabelAndOuterDiv($element));
175  }
176  }
177  }
178 
179  $finalResultArray = $this->resultArray;
180  $finalResultArray['html'] = implode(LF, $content);
181  return $finalResultArray;
182  }
183 
190  protected function createPaletteContentArray($paletteName)
191  {
192  // palette needs a palette name reference, otherwise it does not make sense to try rendering of it
193  if (empty($paletteName) || empty($this->data['processedTca']['palettes'][$paletteName]['showitem'])) {
194  return [];
195  }
196 
197  $resultStructure = [];
198  $foundRealElement = false; // Set to true if not only line breaks were rendered
199  $fieldsArray = GeneralUtility::trimExplode(',', $this->data['processedTca']['palettes'][$paletteName]['showitem'], true);
200  foreach ($fieldsArray as $fieldString) {
201  $fieldArray = $this->explodeSingleFieldShowItemConfiguration($fieldString);
202  $fieldName = $fieldArray['fieldName'];
203  if ($fieldName === '--linebreak--') {
204  $resultStructure[] = [
205  'type' => 'linebreak',
206  ];
207  } else {
208  if (!is_array($this->data['processedTca']['columns'][$fieldName])) {
209  continue;
210  }
211  $options = $this->data;
212  $options['fieldName'] = $fieldName;
213 
214  $options['renderType'] = 'singleFieldContainer';
215  $singleFieldContentArray = $this->nodeFactory->create($options)->render();
216 
217  if (!empty($singleFieldContentArray['html'])) {
218  $foundRealElement = true;
219  $fieldLabel = '';
220  if (!empty($this->data['processedTca']['columns'][$fieldName]['label'])) {
221  $fieldLabel = $this->data['processedTca']['columns'][$fieldName]['label'];
222  }
223  $resultStructure[] = [
224  'type' => 'single',
225  'fieldName' => $fieldName,
226  'fieldLabel' => $fieldLabel,
227  'fieldHtml' => $singleFieldContentArray['html'],
228  ];
229  $singleFieldContentArray['html'] = '';
230  }
231  $this->resultArray = $this->mergeChildReturnIntoExistingResult($this->resultArray, $singleFieldContentArray);
232  }
233  }
234 
235  if ($foundRealElement) {
236  return $resultStructure;
237  } else {
238  return [];
239  }
240  }
241 
248  protected function renderInnerPaletteContent(array $elementArray)
249  {
250  // Group fields
251  $groupedFields = [];
252  $row = 0;
253  $lastLineWasLinebreak = true;
254  foreach ($elementArray['elements'] as $element) {
255  if ($element['type'] === 'linebreak') {
256  if (!$lastLineWasLinebreak) {
257  $row++;
258  $groupedFields[$row][] = $element;
259  $row++;
260  $lastLineWasLinebreak = true;
261  }
262  } else {
263  $lastLineWasLinebreak = false;
264  $groupedFields[$row][] = $element;
265  }
266  }
267 
268  $result = [];
269  // Process fields
270  foreach ($groupedFields as $fields) {
271  $numberOfItems = count($fields);
272  $colWidth = (int)floor(12 / $numberOfItems);
273  // Column class calculation
274  $colClass = 'col-md-12';
275  $colClear = [];
276  if ($colWidth == 6) {
277  $colClass = 'col-sm-6';
278  $colClear = [
279  2 => 'visible-sm-block visible-md-block visible-lg-block',
280  ];
281  } elseif ($colWidth === 4) {
282  $colClass = 'col-sm-4';
283  $colClear = [
284  3 => 'visible-sm-block visible-md-block visible-lg-block',
285  ];
286  } elseif ($colWidth === 3) {
287  $colClass = 'col-sm-6 col-md-3';
288  $colClear = [
289  2 => 'visible-sm-block',
290  4 => 'visible-md-block visible-lg-block',
291  ];
292  } elseif ($colWidth <= 2) {
293  $colClass = 'checkbox-column col-sm-6 col-md-3 col-lg-2';
294  $colClear = [
295  2 => 'visible-sm-block',
296  4 => 'visible-md-block',
297  6 => 'visible-lg-block'
298  ];
299  }
300 
301  // Render fields
302  for ($counter = 0; $counter < $numberOfItems; $counter++) {
303  $element = $fields[$counter];
304  if ($element['type'] === 'linebreak') {
305  if ($counter !== $numberOfItems) {
306  $result[] = '<div class="clearfix"></div>';
307  }
308  } else {
309  $result[] = $this->wrapSingleFieldContentWithLabelAndOuterDiv($element, [$colClass]);
310 
311  // Breakpoints
312  if ($counter + 1 < $numberOfItems && !empty($colClear)) {
313  foreach ($colClear as $rowBreakAfter => $clearClass) {
314  if (($counter + 1) % $rowBreakAfter === 0) {
315  $result[] = '<div class="clearfix ' . $clearClass . '"></div>';
316  }
317  }
318  }
319  }
320  }
321  }
322 
323  return implode(LF, $result);
324  }
325 
334  protected function fieldSetWrap($content, $paletteHidden = false, $label = '')
335  {
336  $fieldSetClass = 'form-section';
337  if ($paletteHidden) {
338  $fieldSetClass .= ' hide';
339  }
340 
341  $result = [];
342  $result[] = '<fieldset class="' . $fieldSetClass . '">';
343 
344  if (!empty($label)) {
345  $result[] = '<h4 class="form-section-headline">' . htmlspecialchars($label) . '</h4>';
346  }
347 
348  $result[] = $content;
349  $result[] = '</fieldset>';
350  return implode(LF, $result);
351  }
352 
360  protected function wrapSingleFieldContentWithLabelAndOuterDiv(array $element, array $additionalPaletteClasses = [])
361  {
362  $fieldName = $element['fieldName'];
363 
364  $paletteFieldClasses = [
365  'form-group',
366  't3js-formengine-validation-marker',
367  't3js-formengine-palette-field',
368  ];
369  foreach ($additionalPaletteClasses as $class) {
370  $paletteFieldClasses[] = $class;
371  }
372 
373  $label = BackendUtility::wrapInHelp($this->data['tableName'], $fieldName, htmlspecialchars($element['fieldLabel']));
374 
375  $content = [];
376  $content[] = '<div class="' . implode(' ', $paletteFieldClasses) . '">';
377  $content[] = '<label class="t3js-formengine-label">';
378  $content[] = $label;
379  $content[] = '</label>';
380  $content[] = $element['fieldHtml'];
381  $content[] = '</div>';
382 
383  return implode(LF, $content);
384  }
385 
392  protected function isUserNoTableWrappingField($element)
393  {
394  $fieldName = $element['fieldName'];
395  if (
396  $this->data['processedTca']['columns'][$fieldName]['config']['type'] === 'user'
397  && !empty($this->data['processedTca']['columns'][$fieldName]['config']['noTableWrapping'])
398  ) {
399  return true;
400  }
401  return false;
402  }
403 
407  protected function getLanguageService()
408  {
409  return $GLOBALS['LANG'];
410  }
411 }
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
wrapSingleFieldContentWithLabelAndOuterDiv(array $element, array $additionalPaletteClasses=[])
mergeChildReturnIntoExistingResult(array $existing, array $childReturn)
if(TYPO3_MODE=== 'BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']