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