[BUGFIX] Correct automatic grid column calculation for forms
[Packages/TYPO3.CMS.git] / typo3 / sysext / form / Classes / ViewHelpers / GridColumnClassAutoConfigurationViewHelper.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Form\ViewHelpers;
4
5 /*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18 use TYPO3\CMS\Form\Domain\Model\FormElements\GridContainerInterface;
19 use TYPO3\CMS\Form\Domain\Model\Renderable\RootRenderableInterface;
20 use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
21 use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
22 use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
23
24 /**
25 * Scope: frontend
26 * @api
27 */
28 class GridColumnClassAutoConfigurationViewHelper extends AbstractViewHelper
29 {
30 use CompileWithRenderStatic;
31
32 /**
33 * @var bool
34 */
35 protected $escapeOutput = false;
36
37 /**
38 * Initialize the arguments.
39 *
40 * @internal
41 */
42 public function initializeArguments()
43 {
44 $this->registerArgument('element', RootRenderableInterface::class, 'A RootRenderableInterface instance', true);
45 }
46
47 /**
48 * @param array $arguments
49 * @param \Closure $renderChildrenClosure
50 * @param RenderingContextInterface $renderingContext
51 * @return string
52 */
53 public static function renderStatic(
54 array $arguments,
55 \Closure $renderChildrenClosure,
56 RenderingContextInterface $renderingContext
57 ) {
58 $formElement = $arguments['element'];
59
60 $gridRowElement = $formElement->getParentRenderable();
61 $gridContainerElement = $gridRowElement->getParentRenderable();
62 $gridRowEChildElements = $gridRowElement->getElements();
63
64 if ($gridContainerElement instanceof GridContainerInterface) {
65 $gridViewPortConfiguration = $gridContainerElement->getProperties()['gridColumnClassAutoConfiguration'];
66 } else {
67 $gridViewPortConfiguration = $gridRowElement->getProperties()['gridColumnClassAutoConfiguration'];
68 }
69
70 if (empty($gridViewPortConfiguration)) {
71 return '';
72 }
73 $gridSize = (int)$gridViewPortConfiguration['gridSize'];
74
75 $columnsToCalculate = [];
76 $usedColumns = [];
77 foreach ($gridRowEChildElements as $childElement) {
78 if (empty($childElement->getProperties()['gridColumnClassAutoConfiguration'])) {
79 foreach ($gridViewPortConfiguration['viewPorts'] as $viewPortName => $configuration) {
80 $columnsToCalculate[$viewPortName]['elements']++;
81 }
82 } else {
83 $gridColumnViewPortConfiguration = $childElement->getProperties()['gridColumnClassAutoConfiguration'];
84 foreach ($gridViewPortConfiguration['viewPorts'] as $viewPortName => $configuration) {
85 $configuration = $gridColumnViewPortConfiguration['viewPorts'][$viewPortName];
86 if (
87 isset($configuration['numbersOfColumnsToUse'])
88 && (int)$configuration['numbersOfColumnsToUse'] > 0
89 ) {
90 $usedColumns[$viewPortName]['sum'] += (int)$configuration['numbersOfColumnsToUse'];
91 if ($childElement->getIdentifier() === $formElement->getIdentifier()) {
92 $usedColumns[$viewPortName]['concreteNumbersOfColumnsToUse'] = (int)$configuration['numbersOfColumnsToUse'];
93 if ($usedColumns[$viewPortName]['concreteNumbersOfColumnsToUse'] > $gridSize) {
94 $usedColumns[$viewPortName]['concreteNumbersOfColumnsToUse'] = $gridSize;
95 }
96 }
97 } else {
98 $columnsToCalculate[$viewPortName]['elements']++;
99 }
100 }
101 }
102 }
103
104 $classes = [];
105 foreach ($gridViewPortConfiguration['viewPorts'] as $viewPortName => $configuration) {
106 if (isset($usedColumns[$viewPortName]['concreteNumbersOfColumnsToUse'])) {
107 $numbersOfColumnsToUse = $usedColumns[$viewPortName]['concreteNumbersOfColumnsToUse'];
108 } else {
109 $restColumnsToDivide = $gridSize - $usedColumns[$viewPortName]['sum'];
110 $restElements = (int)$columnsToCalculate[$viewPortName]['elements'];
111
112 if ($restColumnsToDivide < 1) {
113 $restColumnsToDivide = $gridSize;
114 }
115 if ($restElements < 1) {
116 $restElements = 1;
117 }
118 $numbersOfColumnsToUse = floor($restColumnsToDivide / $restElements);
119 }
120
121 $classes[] = str_replace(
122 '{@numbersOfColumnsToUse}',
123 $numbersOfColumnsToUse,
124 $configuration['classPattern']
125 );
126 }
127
128 return implode(' ', $classes);
129 }
130 }