[TASK] Fix broken references to exceptions in global namespace
[Packages/TYPO3.CMS.git] / typo3 / sysext / form / Classes / Domain / Factory / TypoScriptFactory.php
1 <?php
2 namespace TYPO3\CMS\Form\Domain\Factory;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2008 Patrick Broens (patrick@patrickbroens.nl)
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 *
19 * This script is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
26 /**
27 * Typoscript factory for form
28 *
29 * Takes the incoming Typoscipt and adds all the necessary form objects
30 * according to the configuration.
31 *
32 * @author Patrick Broens <patrick@patrickbroens.nl>
33 * @package TYPO3
34 * @subpackage form
35 */
36 class TypoScriptFactory implements \TYPO3\CMS\Core\SingletonInterface {
37
38 const PROPERTY_DisableContentElement = 'disableContentElement';
39 /**
40 * @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
41 */
42 protected $localContentObject;
43
44 /**
45 * @var boolean
46 */
47 protected $disableContentElement = FALSE;
48
49 /**
50 * Build model from Typoscript
51 *
52 * @param array $typoscript Typoscript containing all configuration
53 * @return \TYPO3\CMS\Form\Domain\Model\Form The form object containing the child elements
54 */
55 public function buildModelFromTyposcript(array $typoscript) {
56 if (isset($typoscript[self::PROPERTY_DisableContentElement])) {
57 $this->setDisableContentElement($typoscript[self::PROPERTY_DisableContentElement]);
58 }
59 $this->setLayoutHandler($typoscript);
60 $form = $this->createElement('form', $typoscript);
61 return $form;
62 }
63
64 /**
65 * Disables the content element.
66 *
67 * @param boolean $disableContentElement
68 * @return void
69 */
70 public function setDisableContentElement($disableContentElement) {
71 $this->disableContentElement = (bool) $disableContentElement;
72 }
73
74 /**
75 * Rendering of a "numerical array" of Form objects from TypoScript
76 * Creates new object for each element found
77 *
78 * @param \TYPO3\CMS\Form\Domain\Model\Element\AbstractElement $parentElement Parent model object
79 * @param array $arguments Configuration array
80 * @throws \InvalidArgumentException
81 * @return void
82 */
83 public function getChildElementsByIntegerKey(\TYPO3\CMS\Form\Domain\Model\Element\AbstractElement $parentElement, array $typoscript) {
84 if (is_array($typoscript)) {
85 $keys = \TYPO3\CMS\Core\TypoScript\TemplateService::sortedKeyList($typoscript);
86 foreach ($keys as $key) {
87 $class = $typoscript[$key];
88 if (intval($key) && !strstr($key, '.')) {
89 if (isset($typoscript[$key . '.'])) {
90 $elementArguments = $typoscript[$key . '.'];
91 } else {
92 $elementArguments = array();
93 }
94 $this->setElementType($parentElement, $class, $elementArguments);
95 }
96 }
97 } else {
98 throw new \InvalidArgumentException(('Container element with id=' . $parentElement->getElementId()) . ' has no configuration which means no children.', 1333754854);
99 }
100 }
101
102 /**
103 * Create and add element by type.
104 * This can be a derived Typoscript object by "<",
105 * a form element, or a regular Typoscript object.
106 *
107 * @param \TYPO3\CMS\Form\Domain\Model\Element\AbstractElement $parentElement The parent for the new element
108 * @param string $class Classname for the element
109 * @param array $arguments Configuration array
110 * @return void
111 */
112 public function setElementType(\TYPO3\CMS\Form\Domain\Model\Element\AbstractElement $parentElement, $class, array $arguments) {
113 if (in_array($class, \TYPO3\CMS\Form\Utility\FormUtility::getInstance()->getFormObjects())) {
114 $this->addElement($parentElement, $class, $arguments);
115 } elseif ($this->disableContentElement === FALSE) {
116 if (substr($class, 0, 1) == '<') {
117 $key = trim(substr($class, 1));
118 /** @var $typoscriptParser \TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser */
119 $typoscriptParser = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\TypoScript\\Parser\\TypoScriptParser');
120 $oldArguments = $arguments;
121 list($class, $arguments) = $typoscriptParser->getVal($key, $GLOBALS['TSFE']->tmpl->setup);
122 if (is_array($oldArguments) && count($oldArguments)) {
123 $arguments = $this->getLocalConentObject()->joinTSarrays($arguments, $oldArguments);
124 }
125 $GLOBALS['TT']->incStackPointer();
126 $contentObject = array(
127 'cObj' => $class,
128 'cObj.' => $arguments
129 );
130 $this->addElement($parentElement, 'content', $contentObject);
131 $GLOBALS['TT']->decStackPointer();
132 } else {
133 $contentObject = array(
134 'cObj' => $class,
135 'cObj.' => $arguments
136 );
137 $this->addElement($parentElement, 'content', $contentObject);
138 }
139 }
140 }
141
142 /**
143 * Add child object to this element
144 *
145 * @param \TYPO3\CMS\Form\Domain\Model\Element\AbstractElement $parentElement Parent model object
146 * @param string $class Type of element
147 * @param array $arguments Configuration array
148 * @return object
149 */
150 public function addElement(\TYPO3\CMS\Form\Domain\Model\Element\AbstractElement $parentElement, $class, array $arguments = array()) {
151 $element = $this->createElement($class, $arguments);
152 $parentElement->addElement($element);
153 }
154
155 /**
156 * Create element by loading class
157 * and instantiating the object
158 *
159 * @param string $class Type of element
160 * @param array $arguments Configuration array
161 * @return \TYPO3\CMS\Form\Domain\Model\Element\AbstractElement
162 */
163 public function createElement($class, array $arguments = array()) {
164 $class = strtolower((string) $class);
165 if ($class === 'form') {
166 $className = 'tx_form_Domain_Model_' . ucfirst($class);
167 } else {
168 $className = 'tx_form_Domain_Model_Element_' . ucfirst($class);
169 }
170 /** @var $object \TYPO3\CMS\Form\Domain\Model\Element\AbstractElement */
171 $object = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($className);
172 if ($object->getElementType() === \TYPO3\CMS\Form\Domain\Model\Element\AbstractElement::ELEMENT_TYPE_CONTENT) {
173 $object->setData($arguments['cObj'], $arguments['cObj.']);
174 } elseif ($object->getElementType() === \TYPO3\CMS\Form\Domain\Model\Element\AbstractElement::ELEMENT_TYPE_PLAIN) {
175 $object->setProperties($arguments);
176 } elseif ($object->getElementType() === \TYPO3\CMS\Form\Domain\Model\Element\AbstractElement::ELEMENT_TYPE_FORM) {
177 $object->setData($arguments['data']);
178 $this->reconstituteElement($object, $arguments);
179 } else {
180 throw new \InvalidArgumentException(('Element type "' . $object->getElementType()) . '" is not supported.', 1333754878);
181 }
182 return $object;
183 }
184
185 /**
186 * Reconstitutes the domain model of the accordant element.
187 *
188 * @param \TYPO3\CMS\Form\Domain\Model\Element\AbstractElement $element
189 * @param array $arguments Configuration array
190 * @return void
191 */
192 protected function reconstituteElement(\TYPO3\CMS\Form\Domain\Model\Element\AbstractElement $element, array $arguments = array()) {
193 $this->setAttributes($element, $arguments);
194 $this->setAdditionals($element, $arguments);
195 if (isset($arguments['filters.'])) {
196 $this->setFilters($element, $arguments['filters.']);
197 }
198 $element->setLayout($arguments['layout']);
199 $element->setValue($arguments['value']);
200 $element->setName($arguments['name']);
201 $element->setMessagesFromValidation();
202 $element->setErrorsFromValidation();
203 $element->checkFilterAndSetIncomingDataFromRequest();
204 $this->getChildElementsByIntegerKey($element, $arguments);
205 }
206
207 /**
208 * Set the attributes
209 *
210 * @param \TYPO3\CMS\Form\Domain\Model\Element\AbstractElement $element Model object
211 * @param array $arguments Arguments
212 * @return void
213 */
214 public function setAttributes(\TYPO3\CMS\Form\Domain\Model\Element\AbstractElement $element, array $arguments) {
215 if ($element->hasAllowedAttributes()) {
216 $attributes = $element->getAllowedAttributes();
217 $mandatoryAttributes = $element->getMandatoryAttributes();
218 foreach ($attributes as $attribute => $value) {
219 if (((isset($arguments[$attribute]) || isset($arguments[$attribute . '.'])) || in_array($attribute, $mandatoryAttributes)) || !empty($value)) {
220 if (!empty($arguments[$attribute])) {
221 $value = $arguments[$attribute];
222 } elseif (!empty($arguments[($attribute . '.')])) {
223 $value = $arguments[$attribute . '.'];
224 }
225 try {
226 $element->setAttribute($attribute, $value);
227 } catch (\Exception $exception) {
228 throw new \RuntimeException('Cannot call user function for attribute ' . ucfirst($attribute), 1333754904);
229 }
230 }
231 }
232 } else {
233 throw new \InvalidArgumentException(('The element with id=' . $element->getElementId()) . ' has no default attributes set.', 1333754925);
234 }
235 }
236
237 /**
238 * Set the additionals from Element Typoscript configuration
239 *
240 * @param \TYPO3\CMS\Form\Domain\Model\Element\AbstractElement $element Model object
241 * @param array $arguments Arguments
242 * @return void
243 */
244 public function setAdditionals(\TYPO3\CMS\Form\Domain\Model\Element\AbstractElement $element, array $arguments) {
245 if (!empty($arguments)) {
246 if ($element->hasAllowedAdditionals()) {
247 $additionals = $element->getAllowedAdditionals();
248 foreach ($additionals as $additional) {
249 if (isset($arguments[$additional . '.']) || isset($arguments[$additional])) {
250 if (isset($arguments[$additional]) && isset($arguments[$additional . '.'])) {
251 $value = $arguments[$additional . '.'];
252 $type = $arguments[$additional];
253 } elseif (isset($arguments[$additional . '.'])) {
254 $value = $arguments[$additional . '.'];
255 $type = 'TEXT';
256 } else {
257 $value['value'] = $arguments[$additional];
258 $type = 'TEXT';
259 }
260 try {
261 $element->setAdditional($additional, $type, $value);
262 } catch (\Exception $exception) {
263 throw new \RuntimeException('Cannot call user function for additional ' . ucfirst($additional), 1333754941);
264 }
265 }
266 if (isset($arguments['layout.'][$additional]) && $element->additionalIsSet($additional)) {
267 $layout = $arguments['layout.'][$additional];
268 $element->setAdditionalLayout($additional, $layout);
269 }
270 }
271 } else {
272 throw new \InvalidArgumentException(('The element with id=' . $element->getElementId()) . ' has no additionals set.', 1333754962);
273 }
274 }
275 }
276
277 /**
278 * Add the filters according to the settings in the Typoscript array
279 *
280 * @param \TYPO3\CMS\Form\Domain\Model\Element\AbstractElement $element Model object
281 * @param array $arguments TypoScript
282 * @return void
283 */
284 protected function setFilters(\TYPO3\CMS\Form\Domain\Model\Element\AbstractElement $element, array $arguments) {
285 $keys = \TYPO3\CMS\Core\TypoScript\TemplateService::sortedKeyList($arguments);
286 foreach ($keys as $key) {
287 $class = $arguments[$key];
288 if (intval($key) && !strstr($key, '.')) {
289 $filterArguments = $arguments[$key . '.'];
290 $filter = $element->makeFilter($class, $filterArguments);
291 $element->addFilter($filter);
292 }
293 }
294 }
295
296 /**
297 * Set the layout handler
298 *
299 * @param array $typoscript TypoScript
300 * @return \TYPO3\CMS\Form\Layout The layout handler
301 */
302 public function setLayoutHandler(array $typoscript) {
303 /** @var $layoutHandler \TYPO3\CMS\Form\Layout */
304 $layoutHandler = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Form\\Layout');
305 // singleton
306 if (isset($typoscript['layout.'])) {
307 $layoutHandler->setLayout($typoscript['layout.']);
308 }
309 return $layoutHandler;
310 }
311
312 /**
313 * Set the request handler
314 *
315 * @param array $typoscript TypoScript
316 * @return \TYPO3\CMS\Form\Request The request handler
317 */
318 public function setRequestHandler($typoscript) {
319 $prefix = isset($typoscript['prefix']) ? $typoscript['prefix'] : '';
320 $method = isset($typoscript['method']) ? $typoscript['method'] : '';
321 /** @var $requestHandler \TYPO3\CMS\Form\Request */
322 $requestHandler = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Form\\Request');
323 // singleton
324 $requestHandler->setPrefix($prefix);
325 $requestHandler->setMethod($method);
326 $requestHandler->storeFiles();
327 return $requestHandler;
328 }
329
330 /**
331 * Set the validation rules
332 *
333 * Makes the validation object and adds rules to it
334 *
335 * @param array $typoscript TypoScript
336 * @return \TYPO3\CMS\Form\Utility\ValidatorUtility The validation object
337 */
338 public function setRules(array $typoscript) {
339 $rulesTyposcript = isset($typoscript['rules.']) ? $typoscript['rules.'] : NULL;
340 /** @var $rulesClass \TYPO3\CMS\Form\Utility\ValidatorUtility */
341 $rulesClass = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Form\\Utility\\ValidatorUtility', $rulesTyposcript);
342 // singleton
343 if (is_array($rulesTyposcript)) {
344 $keys = \TYPO3\CMS\Core\TypoScript\TemplateService::sortedKeyList($rulesTyposcript);
345 foreach ($keys as $key) {
346 $class = $rulesTyposcript[$key];
347 if (intval($key) && !strstr($key, '.')) {
348 $elementArguments = $rulesTyposcript[$key . '.'];
349 $rule = $rulesClass->createRule($class, $elementArguments);
350 $rule->setFieldName($elementArguments['element']);
351 $breakOnError = isset($elementArguments['breakOnError']) ? $elementArguments['breakOnError'] : FALSE;
352 $rulesClass->addRule($rule, $elementArguments['element'], $breakOnError);
353 }
354 }
355 }
356 return $rulesClass;
357 }
358
359 /**
360 * Gets the local content object.
361 *
362 * @return \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
363 */
364 protected function getLocalConentObject() {
365 if (!isset($this->localContentObject)) {
366 $this->localContentObject = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\ContentObject\\ContentObjectRenderer');
367 }
368 return $this->localContentObject;
369 }
370
371 }
372
373
374 ?>