adb448e06f1b6db5fb6f830eb72651b303918e86
[Packages/TYPO3.CMS.git] / typo3 / sysext / form / Classes / View / Confirmation / Element / Abstract.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2011 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 * Abstract class for the form elements view
27 *
28 * @author Patrick Broens <patrick@patrickbroens.nl>
29 * @package TYPO3
30 * @subpackage form
31 */
32 abstract class tx_form_View_Confirmation_Element_Abstract {
33
34 /**
35 * The model for the current object
36 *
37 * @var object
38 */
39 protected $model;
40
41 /**
42 * Wrap for elements
43 *
44 * @var string
45 */
46 protected $elementWrap = '
47 <li>
48 <element />
49 </li>
50 ';
51
52 /**
53 * True if element needs no element wrap
54 * like <li>element</li>
55 *
56 * @var boolean
57 */
58 protected $noWrap = FALSE;
59
60 /**
61 * Constructor
62 *
63 * @param object $model Current elements model
64 * @return void
65 */
66 public function __construct($model) {
67 $this->model = $model;
68 }
69
70 /**
71 * Parse the XML of a view object,
72 * check the node type and name
73 * and add the proper XML part of child tags
74 * to the DOMDocument of the current tag
75 *
76 * @param DOMDocument $dom
77 * @param DOMNode $reference Current XML structure
78 * @param boolean $emptyElement
79 * @return boolean
80 */
81 protected function parseXML(DOMDocument $dom, DOMNode $reference, $emptyElement = FALSE) {
82 $node = $reference->firstChild;
83
84 while (!is_null($node)) {
85 $deleteNode = FALSE;
86 $nodeType = $node->nodeType;
87 $nodeName = $node->nodeName;
88 switch ($nodeType) {
89 case XML_TEXT_NODE:
90 break;
91 // @todo Consider putting these processings to the accordant Element model classes!!!
92 case XML_ELEMENT_NODE:
93 switch($nodeName) {
94 case 'containerWrap':
95 $containerWrap = $this->render('containerWrap');
96 if ($containerWrap) {
97 $this->replaceNodeWithFragment($dom, $node, $containerWrap);
98 } else {
99 $emptyElement = TRUE;
100 }
101 $deleteNode = TRUE;
102 break;
103 case 'elements':
104 $replaceNode = $this->getChildElements($dom);
105 if ($replaceNode) {
106 $node->parentNode->replaceChild($replaceNode, $node);
107 } else {
108 $emptyElement = TRUE;
109 }
110 break;
111 case 'label':
112 if (!strstr(get_class($this), '_Additional_')) {
113 if ($this->model->additionalIsSet($nodeName)) {
114 $this->replaceNodeWithFragment($dom, $node, $this->getAdditional('label'));
115 }
116 $deleteNode = TRUE;
117 } else {
118 if (!$this->model->additionalIsSet($nodeName)) {
119 $deleteNode = TRUE;
120 }
121 }
122 break;
123 case 'legend':
124 if (!strstr(get_class($this), '_Additional_')) {
125 if ($this->model->additionalIsSet($nodeName)) {
126 $this->replaceNodeWithFragment($dom, $node, $this->getAdditional('legend'));
127 }
128 $deleteNode = TRUE;
129 }
130 break;
131 case 'inputvalue':
132 if (array_key_exists('checked', $this->model->getAllowedAttributes())) {
133 if (!$this->model->hasAttribute('checked')) {
134 $emptyElement = TRUE;
135 }
136 } elseif (
137 array_key_exists('selected', $this->model->getAllowedAttributes()) &&
138 !$this->model->hasAttribute('selected')
139 ) {
140 $emptyElement = TRUE;
141 } else {
142 $inputValue = $this->getInputValue();
143 if ($inputValue != '') {
144 $replaceNode = $dom->createTextNode($this->getInputValue());
145 $node->parentNode->insertBefore($replaceNode, $node);
146 } else {
147 $emptyElement = TRUE;
148 }
149 }
150 $deleteNode = TRUE;
151 break;
152 case 'labelvalue':
153 case 'legendvalue':
154 $replaceNode = $dom->createTextNode($this->getAdditionalValue());
155 $node->parentNode->insertBefore($replaceNode, $node);
156 $deleteNode = TRUE;
157 break;
158 }
159 break;
160 }
161
162 // Parse the child nodes of this node if available
163 if ($node->hasChildNodes()) {
164 $emptyElement = $this->parseXML($dom, $node, $emptyElement);
165 }
166
167 // Get the current node for deletion if replaced. We need this because nextSibling can be empty
168 $oldNode = $node;
169
170 // Go to next sibling to parse
171 $node = $node->nextSibling;
172
173 // Delete the old node. This can only be done after going to the next sibling
174 if ($deleteNode) {
175 $oldNode->parentNode->removeChild($oldNode);
176 }
177 }
178
179 return $emptyElement;
180 }
181
182 /**
183 * Get the content for the current object as DOMDocument
184 *
185 * @param string $type Type of element for layout
186 * @param boolean $returnFirstChild If TRUE, the first child will be returned instead of the DOMDocument
187 * @return mixed DOMDocument/DOMNode XML part of the view object
188 */
189 public function render($type = 'element', $returnFirstChild = TRUE) {
190 $useLayout = $this->getLayout((string) $type);
191
192 $dom = new DOMDocument('1.0', 'utf-8');
193 $dom->formatOutput = TRUE;
194 $dom->preserveWhiteSpace = FALSE;
195 $dom->loadXML($useLayout);
196
197 $emptyElement = $this->parseXML($dom, $dom);
198
199 if ($emptyElement) {
200 return NULL;
201 } elseif ($returnFirstChild) {
202 return $dom->firstChild;
203 } else {
204 return $dom;
205 }
206 }
207
208 /**
209 * Ask the layoutHandler to get the layout for this object
210 *
211 * @param string $type Layout type
212 * @return string HTML string of the layout to use for this element
213 */
214 public function getLayout($type) {
215 /** @var $layoutHandler tx_form_System_Layout */
216 $layoutHandler = t3lib_div::makeInstance('tx_form_System_Layout');
217
218 switch($type) {
219 case 'element':
220 $layoutDefault = $this->layout;
221 $layout = $layoutHandler->getLayoutByObject(
222 tx_form_Common::getInstance()->getLastPartOfClassName($this, TRUE),
223 $layoutDefault
224 );
225 break;
226 case 'elementWrap':
227 $layoutDefault = $this->elementWrap;
228 $elementWrap = $layoutHandler->getLayoutByObject(
229 $type,
230 $layoutDefault
231 );
232 $layout = str_replace('<element />', $this->getLayout('element'), $elementWrap);
233 break;
234 case 'containerWrap':
235 $layoutDefault = $this->containerWrap;
236 $layout = $layoutHandler->getLayoutByObject(
237 $type,
238 $layoutDefault
239 );
240 break;
241 }
242
243 return $layout;
244 }
245
246 /**
247 * Replace the current node with a document fragment
248 *
249 * @param DOMDocument $dom
250 * @param DOMNode $node Current Node
251 * @param DOMNode $value Value to import
252 * @return void
253 */
254 public function replaceNodeWithFragment(DOMDocument $dom, DOMNode $node, DOMNode $value) {
255 $replaceNode = $dom->createDocumentFragment();
256 $domNode = $dom->importNode($value, TRUE);
257 $replaceNode->appendChild($domNode);
258 $node->parentNode->insertBefore($replaceNode, $node);
259 }
260
261 /**
262 * Set the attributes on the html tags according to the attributes that are
263 * assigned in the model for a certain element
264 *
265 * @param DOMElement $domElement DOM element of the specific HTML tag
266 * @return void
267 */
268 public function setAttributes(DOMElement $domElement) {
269 $attributes = $this->model->getAttributes();
270 foreach ($attributes as $key => $attribute) {
271 if (!empty($attribute)) {
272 $value = $attribute->getValue();
273 if (!empty($value)) {
274 $domElement->setAttribute($key, $value);
275 }
276 }
277 }
278 }
279
280 /**
281 * Set a single attribute of a HTML tag specified by key
282 *
283 * @param DOMElement $domElement DOM element of the specific HTML tag
284 * @param string $key Attribute key
285 * @return void
286 */
287 public function setAttribute(DOMElement $domElement, $key) {
288 $attribute = $this->model->getAttributeValue((string) $key);
289
290 if (!empty($attribute)) {
291 $domElement->setAttribute($key, $attribute);
292 }
293 }
294
295 /**
296 * Sets the value of an attribute with the value of another attribute,
297 * for instance equalizing the name and id attributes for the form tag
298 *
299 * @param DOMElement $domElement DOM element of the specific HTML tag
300 * @param string $key Key of the attribute which needs to be changed
301 * @param string $other Key of the attribute to take the value from
302 * @return unknown_type
303 */
304 public function setAttributeWithValueofOtherAttribute(DOMElement $domElement, $key, $other) {
305 $attribute = $this->model->getAttributeValue((string) $other);
306
307 if (!empty($attribute)) {
308 $domElement->setAttribute($key, $attribute);
309 }
310 }
311
312 /**
313 * Load and instantiate an additional object
314 *
315 * @param string $class Type of additional
316 * @return object
317 */
318 protected function createAdditional($class) {
319 $class = strtolower((string) $class);
320 $className = 'tx_form_View_Confirmation_Additional_' . ucfirst($class);
321
322 return t3lib_div::makeInstance($className, $this->model);
323 }
324
325 /**
326 * Create additional object by key and render the content
327 *
328 * @param string $key Type of additional
329 * @return DOMNode
330 */
331 public function getAdditional($key) {
332 $additional = $this->createAdditional($key);
333 return $additional->render();
334 }
335
336 /**
337 * @return string
338 */
339 public function getInputValue() {
340 if (method_exists($this->model, 'getData')) {
341 $inputValue = nl2br($this->model->getData(), TRUE);
342 } else {
343 $inputValue = $this->model->getAttributeValue('value');
344 }
345
346 return $inputValue;
347 }
348
349 /**
350 * Return the id for the element wraps,
351 * like <li id="csc-form-"> ... </li>
352 *
353 * @return string
354 */
355 public function getElementWrapId() {
356 $elementId = (integer) $this->model->getElementId();
357 $wrapId = 'csc-form-' . $elementId;
358
359 return $wrapId;
360 }
361
362 /**
363 * Read the noWrap value of an element
364 * if TRUE the element does not need a element wrap
365 * like <li>element</li>
366 *
367 * @return boolean
368 */
369 public function noWrap() {
370 return $this->noWrap;
371 }
372 }
373 ?>