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