[TASK] Remove deprecated IMAGEBUTTON element
[Packages/TYPO3.CMS.git] / typo3 / sysext / form / Classes / Utility / TypoScriptToJsonConverter.php
1 <?php
2 namespace TYPO3\CMS\Form\Utility;
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
17 use TYPO3\CMS\Core\Utility\ArrayUtility;
18 use TYPO3\CMS\Core\Utility\GeneralUtility;
19 use TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement;
20
21 /**
22 * Typoscript to JSON converter
23 *
24 * Takes the incoming TypoScript and converts it to JSON.
25 */
26 class TypoScriptToJsonConverter
27 {
28 protected $registeredElementNames = array(
29 'BUTTON',
30 'CHECKBOX',
31 'CHECKBOXGROUP',
32 'FIELDSET',
33 'FILEUPLOAD',
34 'HEADER',
35 'HIDDEN',
36 'OPTGROUP',
37 'OPTION',
38 'PASSWORD',
39 'RADIO',
40 'RADIOGROUP',
41 'RESET',
42 'SELECT',
43 'SUBMIT',
44 'TEXTAREA',
45 'TEXTBLOCK',
46 'TEXTLINE'
47 );
48
49 /**
50 * @var array
51 */
52 protected $nameMapping = array(
53 'checkboxgroup' => 'CheckboxGroup',
54 'radiogroup' => 'RadioGroup',
55 );
56
57 /**
58 * @var array
59 */
60 protected $validationRules;
61
62 /**
63 * Convert TypoScript string to JSON
64 *
65 * @param array $typoscript TypoScript string containing all configuration for the form
66 * @return TYPO3\CMS\Form\Domain\Model\Json\FormJsonElement|false The JSON for the form
67 */
68 public function convert(array $typoscript)
69 {
70 $this->setValidationRules($typoscript);
71 $jsonObject = $this->createElement('form', $typoscript);
72 return $jsonObject;
73 }
74
75 /**
76 * Create element by loading class
77 * and instantiating the object
78 *
79 * @param string $class Type of element
80 * @param array $arguments Configuration array
81 * @return AbstractJsonElement
82 * @throws \RuntimeException
83 */
84 public function createElement($class, array $arguments = array())
85 {
86 $class = strtolower((string)$class);
87 if (!empty($this->nameMapping[$class])) {
88 $class = $this->nameMapping[$class];
89 }
90 $className = 'TYPO3\\CMS\\Form\\Domain\\Model\Json\\' . ucfirst($class) . 'JsonElement';
91 $this->addValidationRules($arguments);
92
93 if (!class_exists($className)) {
94 throw new \RuntimeException('Class "' . $className . '" does not exist', 1440779351);
95 }
96
97 /** @var $object AbstractJsonElement */
98 $object = GeneralUtility::makeInstance($className);
99 $object->setParameters($arguments);
100 if ($object->childElementsAllowed()) {
101 $this->getChildElementsByIntegerKey($object, $arguments);
102 }
103 return $object;
104 }
105
106 /**
107 * Rendering of a "numerical array" of Form objects from TypoScript
108 * Creates new object for each element found
109 *
110 * @param AbstractJsonElement $parentElement Parent model object
111 * @param array $typoscript Configuration array
112 * @return void
113 */
114 protected function getChildElementsByIntegerKey(AbstractJsonElement $parentElement, array $typoscript)
115 {
116 if (is_array($typoscript)) {
117 $keys = ArrayUtility::filterAndSortByNumericKeys($typoscript);
118 foreach ($keys as $key) {
119 $class = $typoscript[$key];
120 if ((int)$key && strpos($key, '.') === false) {
121 if (isset($typoscript[$key . '.'])) {
122 $elementArguments = $typoscript[$key . '.'];
123 } else {
124 $elementArguments = array();
125 }
126 $this->setElementType($parentElement, $class, $elementArguments);
127 }
128 }
129 }
130 }
131
132 /**
133 * Set the element type of the object
134 *
135 * Checks if the typoscript object is part of the FORM or has a predefined
136 * class for name or header object
137 *
138 * @param AbstractJsonElement $parentElement The parent object
139 * @param string $class A predefined class
140 * @param array $arguments Configuration array
141 * @return void
142 */
143 private function setElementType(AbstractJsonElement $parentElement, $class, array $arguments)
144 {
145 if (in_array($class, $this->registeredElementNames)) {
146 if (strstr($arguments['class'], 'predefined-name')) {
147 $class = 'NAME';
148 }
149 $this->addElement($parentElement, $class, $arguments);
150 }
151 }
152
153 /**
154 * Add child object to this element
155 *
156 * @param AbstractJsonElement $parentElement The parent object
157 * @param string $class Type of element
158 * @param array $arguments Configuration array
159 * @return void
160 */
161 public function addElement(AbstractJsonElement $parentElement, $class, array $arguments)
162 {
163 try {
164 $element = $this->createElement($class, $arguments);
165 $parentElement->addElement($element);
166 } catch (\RuntimeException $exception) {
167 // Catch missing classes or element types
168 // There are elements that can be used the
169 // TypoScript-like declaration, which don't
170 // have a counterpart in the ExtJS wizard.
171 }
172 }
173
174 /**
175 * Set the validation rules
176 *
177 * @param array $typoscript Configuration array
178 * @return void
179 */
180 protected function setValidationRules(array $typoscript)
181 {
182 if (isset($typoscript['rules.']) && is_array($typoscript['rules.'])) {
183 $this->validationRules = $typoscript['rules.'];
184 }
185 }
186
187 /**
188 * Add validation rules to an element if available
189 *
190 * In TypoScript the validation rules belong to the form and are connected
191 * to the elements by name. However, in the wizard, they are added to the
192 * element for usability
193 *
194 * @param array $arguments The element arguments
195 * @return void
196 */
197 protected function addValidationRules(array &$arguments)
198 {
199 if (!empty($this->validationRules) && isset($arguments['name'])) {
200 foreach ($this->validationRules as $key => $ruleName) {
201 if ((int)$key && strpos($key, '.') === false) {
202 if (isset($this->validationRules[$key . '.'])) {
203 $ruleConfiguration = $this->validationRules[$key . '.'];
204 if (isset($ruleConfiguration['element']) && $ruleConfiguration['element'] === $arguments['name']) {
205 $arguments['validation'][$ruleName] = $ruleConfiguration;
206 }
207 }
208 }
209 }
210 }
211 }
212 }