TYPO3  7.6
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 = array();
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 = array();
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] = array(
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  $targetStructure[$mainStructureCounter] = array(
141  'type' => 'single',
142  'fieldName' => $fieldConfiguration['fieldName'],
143  'fieldLabel' => $this->getSingleFieldLabel($fieldName, $fieldConfiguration['fieldLabel']),
144  'fieldHtml' => $childResultArray['html'],
145  );
146  }
147 
148  $childResultArray['html'] = '';
149  $this->resultArray = $this->mergeChildReturnIntoExistingResult($this->resultArray, $childResultArray);
150  }
151  }
152 
153  // Compile final content
154  $content = array();
155  foreach ($targetStructure as $element) {
156  if ($element['type'] === 'palette') {
157  $paletteName = $element['fieldName'];
158  $paletteElementsHtml = $this->renderInnerPaletteContent($element);
159 
160  $isHiddenPalette = !empty($this->data['processedTca']['palettes'][$paletteName]['isHiddenPalette']);
161 
162  $paletteElementsHtml = '<div class="row">' . $paletteElementsHtml . '</div>';
163 
164  $content[] = $this->fieldSetWrap($paletteElementsHtml, $isHiddenPalette, $element['fieldLabel']);
165  } else {
166  // Return raw HTML only in case of user element with no wrapping requested
167  if ($this->isUserNoTableWrappingField($element)) {
168  $content[] = $element['fieldHtml'];
169  } else {
170  $content[] = $this->fieldSetWrap($this->wrapSingleFieldContentWithLabelAndOuterDiv($element));
171  }
172  }
173  }
174 
175  $finalResultArray = $this->resultArray;
176  $finalResultArray['html'] = implode(LF, $content);
177  return $finalResultArray;
178  }
179 
186  protected function createPaletteContentArray($paletteName)
187  {
188  // palette needs a palette name reference, otherwise it does not make sense to try rendering of it
189  if (empty($paletteName) || empty($this->data['processedTca']['palettes'][$paletteName]['showitem'])) {
190  return array();
191  }
192 
193  $resultStructure = array();
194  $foundRealElement = false; // Set to true if not only line breaks were rendered
195  $fieldsArray = GeneralUtility::trimExplode(',', $this->data['processedTca']['palettes'][$paletteName]['showitem'], true);
196  foreach ($fieldsArray as $fieldString) {
197  $fieldArray = $this->explodeSingleFieldShowItemConfiguration($fieldString);
198  $fieldName = $fieldArray['fieldName'];
199  if ($fieldName === '--linebreak--') {
200  $resultStructure[] = array(
201  'type' => 'linebreak',
202  );
203  } else {
204  if (!is_array($this->data['processedTca']['columns'][$fieldName])) {
205  continue;
206  }
207  $options = $this->data;
208  $options['fieldName'] = $fieldName;
209 
210  $options['renderType'] = 'singleFieldContainer';
211  $singleFieldContentArray = $this->nodeFactory->create($options)->render();
212 
213  if (!empty($singleFieldContentArray['html'])) {
214  $foundRealElement = true;
215  $resultStructure[] = array(
216  'type' => 'single',
217  'fieldName' => $fieldName,
218  'fieldLabel' => $this->getSingleFieldLabel($fieldName, $fieldArray['fieldLabel']),
219  'fieldHtml' => $singleFieldContentArray['html'],
220  );
221  $singleFieldContentArray['html'] = '';
222  }
223  $this->resultArray = $this->mergeChildReturnIntoExistingResult($this->resultArray, $singleFieldContentArray);
224  }
225  }
226 
227  if ($foundRealElement) {
228  return $resultStructure;
229  } else {
230  return array();
231  }
232  }
233 
240  protected function renderInnerPaletteContent(array $elementArray)
241  {
242  // Group fields
243  $groupedFields = array();
244  $row = 0;
245  $lastLineWasLinebreak = true;
246  foreach ($elementArray['elements'] as $element) {
247  if ($element['type'] === 'linebreak') {
248  if (!$lastLineWasLinebreak) {
249  $row++;
250  $groupedFields[$row][] = $element;
251  $row++;
252  $lastLineWasLinebreak = true;
253  }
254  } else {
255  $lastLineWasLinebreak = false;
256  $groupedFields[$row][] = $element;
257  }
258  }
259 
260  $result = array();
261  // Process fields
262  foreach ($groupedFields as $fields) {
263  $numberOfItems = count($fields);
264  $colWidth = (int)floor(12 / $numberOfItems);
265  // Column class calculation
266  $colClass = "col-md-12";
267  $colClear = array();
268  if ($colWidth == 6) {
269  $colClass = "col-sm-6";
270  $colClear = array(
271  2 => 'visible-sm-block visible-md-block visible-lg-block',
272  );
273  } elseif ($colWidth === 4) {
274  $colClass = "col-sm-4";
275  $colClear = array(
276  3 => 'visible-sm-block visible-md-block visible-lg-block',
277  );
278  } elseif ($colWidth === 3) {
279  $colClass = "col-sm-6 col-md-3";
280  $colClear = array(
281  2 => 'visible-sm-block',
282  4 => 'visible-md-block visible-lg-block',
283  );
284  } elseif ($colWidth <= 2) {
285  $colClass = "checkbox-column col-sm-6 col-md-3 col-lg-2";
286  $colClear = array(
287  2 => 'visible-sm-block',
288  4 => 'visible-md-block',
289  6 => 'visible-lg-block'
290  );
291  }
292 
293  // Render fields
294  for ($counter = 0; $counter < $numberOfItems; $counter++) {
295  $element = $fields[$counter];
296  if ($element['type'] === 'linebreak') {
297  if ($counter !== $numberOfItems) {
298  $result[] = '<div class="clearfix"></div>';
299  }
300  } else {
301  $result[] = $this->wrapSingleFieldContentWithLabelAndOuterDiv($element, array($colClass));
302 
303  // Breakpoints
304  if ($counter + 1 < $numberOfItems && !empty($colClear)) {
305  foreach ($colClear as $rowBreakAfter => $clearClass) {
306  if (($counter + 1) % $rowBreakAfter === 0) {
307  $result[] = '<div class="clearfix ' . $clearClass . '"></div>';
308  }
309  }
310  }
311  }
312  }
313  }
314 
315  return implode(LF, $result);
316  }
317 
326  protected function fieldSetWrap($content, $paletteHidden = false, $label = '')
327  {
328  $fieldSetClass = 'form-section';
329  if ($paletteHidden) {
330  $fieldSetClass = 'hide';
331  }
332 
333  $result = array();
334  $result[] = '<fieldset class="' . $fieldSetClass . '">';
335 
336  if (!empty($label)) {
337  $result[] = '<h4 class="form-section-headline">' . htmlspecialchars($label) . '</h4>';
338  }
339 
340  $result[] = $content;
341  $result[] = '</fieldset>';
342  return implode(LF, $result);
343  }
344 
352  protected function wrapSingleFieldContentWithLabelAndOuterDiv(array $element, array $additionalPaletteClasses = array())
353  {
354  $fieldName = $element['fieldName'];
355 
356  $paletteFieldClasses = array(
357  'form-group',
358  't3js-formengine-validation-marker',
359  't3js-formengine-palette-field',
360  );
361  foreach ($additionalPaletteClasses as $class) {
362  $paletteFieldClasses[] = $class;
363  }
364 
365  $label = BackendUtility::wrapInHelp($this->data['tableName'], $fieldName, htmlspecialchars($element['fieldLabel']));
366 
367  $content = array();
368  $content[] = '<div class="' . implode(' ', $paletteFieldClasses) . '">';
369  $content[] = '<label class="t3js-formengine-label">';
370  $content[] = $label;
371  $content[] = '</label>';
372  $content[] = $element['fieldHtml'];
373  $content[] = '</div>';
374 
375  return implode(LF, $content);
376  }
377 
385  protected function getSingleFieldLabel($fieldName, $labelFromShowItem)
386  {
387  $languageService = $this->getLanguageService();
388  $table = $this->data['tableName'];
389  $label = $labelFromShowItem;
390  if (!empty($this->data['processedTca']['columns'][$fieldName]['label'])) {
391  $label = $this->data['processedTca']['columns'][$fieldName]['label'];
392  }
393  if (!empty($labelFromShowItem)) {
394  $label = $labelFromShowItem;
395  }
396 
397  $fieldTSConfig = [];
398  if (isset($this->data['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.'])
399  && is_array($this->data['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.'])
400  ) {
401  $fieldTSConfig = $this->data['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.'];
402  }
403 
404  if (!empty($fieldTSConfig['label'])) {
405  $label = $fieldTSConfig['label'];
406  }
407  if (!empty($fieldTSConfig['label.'][$languageService->lang])) {
408  $label = $fieldTSConfig['label.'][$languageService->lang];
409  }
410  return $languageService->sL($label);
411  }
412 
419  protected function isUserNoTableWrappingField($element)
420  {
421  $fieldName = $element['fieldName'];
422  if (
423  $this->data['processedTca']['columns'][$fieldName]['config']['type'] === 'user'
424  && !empty($this->data['processedTca']['columns'][$fieldName]['config']['noTableWrapping'])
425  ) {
426  return true;
427  }
428  return false;
429  }
430 
434  protected function getLanguageService()
435  {
436  return $GLOBALS['LANG'];
437  }
438 }