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