[BUGFIX] EXT:form - Allow setting classes via layout for elements
[Packages/TYPO3.CMS.git] / typo3 / sysext / form / Classes / Utility / CompatibilityLayerUtility.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\Builder\FormBuilder;
19 use TYPO3\CMS\Form\Domain\Model\Element;
20
21 /**
22 * Compatibility layer.
23 * Used in the scope of one(!) specific form element.
24 */
25 class CompatibilityLayerUtility {
26
27 /**
28 * @param FormBuilder $formBuilder
29 * @return CompatibilityLayerUtility
30 */
31 static public function create(FormBuilder $formBuilder) {
32 /** @var CompatibilityLayerUtility $compatibilityService */
33 $compatibilityService = \TYPO3\CMS\Form\Utility\FormUtility::getObjectManager()->get(CompatibilityLayerUtility::class);
34 $compatibilityService->setFormBuilder($formBuilder);
35 return $compatibilityService;
36 }
37
38 /**
39 * Layout array from form configuration
40 *
41 * @var array
42 */
43 protected $layout = array();
44
45 /**
46 * @var FormBuilder
47 */
48 protected $formBuilder;
49
50 /**
51 * @var array
52 */
53 protected $registeredFormElements = array(
54 'TEXTLINE',
55 'SUBMIT',
56 'RESET',
57 'RADIO',
58 'PASSWORD',
59 'IMAGEBUTTON',
60 'FILEUPLOAD',
61 'CHECKBOX',
62 'BUTTON',
63 'TEXTAREA',
64 'HIDDEN',
65 'CONTENTELEMENT',
66 'TEXTBLOCK',
67 'SELECT',
68 'FIELDSET',
69 'RADIOGROUP',
70 'CHECKBOXGROUP',
71 );
72
73 /**
74 * @var array
75 */
76 protected $elementsWithoutLabel = array(
77 'HIDDEN',
78 'CONTENTELEMENT',
79 'TEXTBLOCK',
80 'FIELDSET',
81 'RADIOGROUP',
82 'CHECKBOXGROUP',
83 );
84
85 /**
86 * @var array
87 */
88 protected $containerElements = array(
89 'FIELDSET',
90 'RADIOGROUP',
91 'CHECKBOXGROUP',
92 );
93
94 /**
95 * @param FormBuilder $formBuilder
96 */
97 public function setFormBuilder(FormBuilder $formBuilder) {
98 $this->formBuilder = $formBuilder;
99 }
100
101 /**
102 * Set the layout configuration for one or more elements
103 *
104 * @param NULL|array $layout The configuration array
105 * @return void
106 * @deprecated since TYPO3 CMS 7, this function will be removed in TYPO3 CMS 8, as the functionality is now done via fluid
107 */
108 public function setGlobalLayoutConfiguration($layout = array()) {
109 GeneralUtility::deprecationLog('EXT:form: Do not use "layout." anymore. Deprecated since TYPO3 CMS 7, this function will be removed in TYPO3 CMS 8.');
110 if (is_array($layout)) {
111 foreach ($layout as $elementType => $elementValue) {
112 $elementType = strtoupper($elementType);
113 $this->layout[$elementType] = $elementValue;
114 }
115 }
116 }
117
118 /**
119 * Get the layout of the object
120 * Looks if there is an assigned layout by configuration of the element
121 * otherwise it will look if there is a layout set in the form configuration.
122 *
123 * @param string $elementType Type of element e.g BUTTON
124 * @return string The element layout
125 * @deprecated since TYPO3 CMS 7, this function will be removed in TYPO3 CMS 8, as the functionality is now done via fluid
126 */
127 public function getGlobalLayoutByElementType($elementType) {
128 GeneralUtility::deprecationLog('EXT:form: Do not use "layout." anymore. Deprecated since TYPO3 CMS 7, this function will be removed in TYPO3 CMS 8.');
129 $layout = '';
130 if (!empty($this->layout[$elementType])) {
131 $layout = $this->layout[$elementType];
132 } else {
133 $action = $this->formBuilder->getControllerAction();
134 switch ($elementType) {
135 case 'FORM':
136 $layout = '<form><containerWrap /></form>';
137 break;
138 case 'CONFIRMATION':
139 $layout = '<containerWrap />';
140 break;
141 case 'HTML':
142 $layout = '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body><table cellspacing="0"><containerWrap /></table></body></html>';
143 break;
144 case 'CONTAINERWRAP':
145 if ($action !== 'process') {
146 $layout = '<ol><elements /></ol>';
147 } else {
148 $layout = '<tbody><elements /></tbody>';
149 }
150 break;
151 case 'ELEMENTWRAP':
152 if ($action !== 'process') {
153 $layout = '<li><element /></li>';
154 } else {
155 $layout = '<tr><element /></tr>';
156 }
157 break;
158 case 'LABEL':
159 if ($action === 'show') {
160 $layout = '<label><labelvalue /><mandatory /><error /></label>';
161 } else if ($action === 'confirmation') {
162 $layout = '<label><labelvalue /></label>';
163 } else {
164 $layout = '<em><labelvalue /></em>';
165 }
166 break;
167 case 'LEGEND':
168 if ($action !== 'process') {
169 $layout = '<legend><legendvalue /></legend>';
170 } else {
171 $layout = '<thead><tr><th colspan="2" align="left"><legendvalue /></th></tr></thead>';
172 }
173 break;
174 case 'MANDATORY':
175 if ($action !== 'process') {
176 $layout = '<em><mandatoryvalue /></em>';
177 } else {
178 $layout = '';
179 }
180 break;
181 case 'ERROR':
182 if ($action !== 'process') {
183 $layout = '<strong><errorvalue /></strong>';
184 } else {
185 $layout = '';
186 }
187 break;
188 case 'RADIOGROUP':
189 case 'CHECKBOXGROUP':
190 case 'FIELDSET':
191 if ($action !== 'process') {
192 $layout = '<fieldset><legend /><containerWrap /></fieldset>';
193 } else {
194 $layout = '<td colspan="2"><table cellspacing="0" style="padding-left: 20px; margin-bottom: 20px;"><legend /><containerWrap /></table></td>';
195 }
196 break;
197 case 'HIDDEN':
198 if ($action !== 'process') {
199 $layout = '<input />';
200 } else {
201 $layout = '';
202 }
203 break;
204 case 'SELECT':
205 if ($action === 'show') {
206 $layout = '<label /><select><elements /></select>';
207 } else if ($action === 'confirmation') {
208 $layout = '<label /><ol><elements /></ol>';
209 } else {
210 $layout = '<td style="width: 200px;"><label /></td><td><elements /></td>';
211 }
212 break;
213 case 'TEXTAREA':
214 if ($action === 'show') {
215 $layout = '<label /><textarea />';
216 } else if ($action === 'confirmation') {
217 $layout = '<label /><inputvalue />';
218 } else {
219 $layout = '<td style="width: 200px;" valign="top"><label /></td><td><inputvalue /></td>';
220 }
221 break;
222 case 'BUTTON':
223 case 'IMAGEBUTTON':
224 case 'PASSWORD':
225 case 'RESET':
226 case 'SUBMIT':
227 if ($action !== 'show') {
228 $layout = '';
229 break;
230 }
231 case 'CHECKBOX':
232 case 'FILEUPLOAD':
233 case 'RADIO':
234 case 'TEXTLINE':
235 if ($action === 'show') {
236 $layout = '<label /><input />';
237 } else if ($action === 'confirmation') {
238 $layout = '<label /><inputvalue />';
239 } else {
240 $layout = '<td style="width: 200px;"><label /></td><td><inputvalue /></td>';
241 }
242 break;
243 }
244 }
245 return $layout;
246 }
247
248 /**
249 * Set the layout for a element
250 * Not supported / ignored: OPTGROUP, OPTION, layout.legend
251 *
252 * @param \TYPO3\CMS\Form\Domain\Model\Element $element
253 * @param array $userConfiguredElementTyposcript The configuration array
254 * @return void
255 * @deprecated since TYPO3 CMS 7, this function will be removed in TYPO3 CMS 8, as the functionality is now done via fluid
256 */
257 public function setElementLayouts(Element $element, array $userConfiguredElementTyposcript = array()) {
258 GeneralUtility::deprecationLog('EXT:form: Do not use "layout." anymore. Deprecated since TYPO3 CMS 7, this function will be removed in TYPO3 CMS 8.');
259 if ($element->getElementType() === 'FORM') {
260 $containerWrapReturn = $this->replaceTagWithMarker('elements', 'body', $this->getGlobalLayoutByElementType('CONTAINERWRAP'));
261 if ($this->formBuilder->getControllerAction() === 'show') {
262 $formWrapReturn = $this->replaceTagWithMarker('containerwrap', 'form', $this->getGlobalLayoutByElementType('FORM'));
263 } else if ($this->formBuilder->getControllerAction() === 'confirmation') {
264 $formWrapReturn = $this->replaceTagWithMarker('containerwrap', 'body', $this->getGlobalLayoutByElementType('CONFIRMATION'));
265 } else {
266 $formWrapReturn = $this->replaceTagWithMarker('containerwrap', 'html', $this->getGlobalLayoutByElementType('HTML'));
267 }
268 $formLayout = str_replace($formWrapReturn['marker'], $containerWrapReturn['html'], $formWrapReturn['html']);
269 $formContainerWrap = explode($containerWrapReturn['marker'], $formLayout);
270 $layout['containerInnerWrap'] = $formContainerWrap;
271 $element->setLayout($layout);
272 $classFromLayout = $this->getElementClassFromLayout('form');
273 if (!empty($classFromLayout)) {
274 if (!empty($element->getAdditionalArgument('class'))) {
275 $classFromLayout .= ' ' . $element->getAdditionalArgument('class');
276 }
277 $element->setAdditionalArgument('class', $classFromLayout);
278 }
279 return;
280 }
281 if (in_array($element->getElementType(), $this->registeredFormElements)) {
282 /* Get the element layout definition or fallback to the global definition (if set) */
283 if (isset($userConfiguredElementTyposcript['layout'])) {
284 $elementLayout = $userConfiguredElementTyposcript['layout'];
285 } else {
286 $elementLayout = $this->getGlobalLayoutByElementType($element->getElementType());
287 }
288 /* if a element layout exist */
289 $elementWrap = NULL;
290 if ($elementLayout) {
291 $elementWrap = $this->determineElementOuterWraps($element->getElementType(), $elementLayout);
292 if ($elementWrap['html'] !== '') {
293 /* layout.label */
294 if (!in_array($element->getElementType(), $this->elementsWithoutLabel, TRUE)) {
295 $labelLayout = $this->getGlobalLayoutByElementType('LABEL');
296 $mandatoryLayout = '';
297 $errorLayout = '';
298 if ($this->formBuilder->getControllerAction() === 'show') {
299 /* layout.mandatory */
300 $mandatoryMessages = $this->formBuilder->getValidationBuilder()->getMandatoryValidationMessagesByElementName($element->getName());
301 if (!empty($mandatoryMessages)) {
302 $mandatoryLayout = $this->replaceLabelContent('mandatory', $mandatoryMessages);
303 }
304 /* layout.error */
305 $errorMessages = $element->getValidationErrorMessages();
306 if (!empty($errorMessages)) {
307 $errorLayout = $this->replaceLabelContent('error', $errorMessages);
308 }
309 }
310 /* Replace the mandatory and error messages */
311 $mandatoryReturn = $this->replaceTagWithMarker('mandatory', 'body', $labelLayout);
312 $labelContainContent = FALSE;
313 if ($mandatoryReturn['html'] !== '') {
314 if (!empty($mandatoryLayout)) {
315 $labelContainContent = TRUE;
316 }
317 $labelLayout = str_replace($mandatoryReturn['marker'], $mandatoryLayout, $mandatoryReturn['html']);
318 }
319 $errorReturn = $this->replaceTagWithMarker('error', 'body', $labelLayout);
320 if ($errorReturn['html'] !== '') {
321 if (!empty($errorLayout)) {
322 $labelContainContent = TRUE;
323 }
324 $labelLayout = str_replace($errorReturn['marker'], $errorLayout, $errorReturn['html']);
325 }
326 /* Replace the label value */
327 $labelValueReturn = $this->replaceTagWithMarker('labelvalue', 'body', $labelLayout);
328 if ($labelValueReturn['html'] !== '') {
329 if (!empty($element->getAdditionalArgument('label'))) {
330 $labelContainContent = TRUE;
331 }
332 $labelLayout = str_replace($labelValueReturn['marker'], $element->getAdditionalArgument('label'), $labelValueReturn['html']);
333 }
334 if (!$labelContainContent) {
335 $labelLayout = '';
336 } else {
337 $libxmlUseInternalErrors = libxml_use_internal_errors(true);
338 $dom = new \DOMDocument('1.0', 'utf-8');
339 $dom->formatOutput = TRUE;
340 $dom->preserveWhiteSpace = FALSE;
341 if ($dom->loadXML($labelLayout)) {
342 $nodes = $dom->getElementsByTagName('label');
343 if ($nodes->length) {
344 $node = $nodes->item(0);
345 if ($node) {
346 $node->setAttribute('for', $element->getId());
347 $labelLayout = $dom->saveXML($dom->firstChild);
348 }
349 }
350 }
351 libxml_use_internal_errors($libxmlUseInternalErrors);
352 }
353 /* Replace <label />, <error /> and <mandatory /> in the element wrap html */
354 $labelReturn = $this->replaceTagWithMarker('label', 'body', $elementWrap['html']);
355 if ($labelReturn['html'] !== '') {
356 $elementWrap['html'] = str_replace($labelReturn['marker'], $labelLayout, $labelReturn['html']);
357 }
358 $errorReturn = $this->replaceTagWithMarker('error', 'body', $elementWrap['html']);
359 if ($errorReturn['html'] !== '') {
360 $elementWrap['html'] = str_replace($errorReturn['marker'], $errorLayout, $errorReturn['html']);
361 }
362 $mandatoryReturn = $this->replaceTagWithMarker('mandatory', 'body', $elementWrap['html']);
363 if ($mandatoryReturn['html'] !== '') {
364 $elementWrap['html'] = str_replace($mandatoryReturn['marker'], $mandatoryLayout, $mandatoryReturn['html']);
365 }
366 }
367 $elementWrap = explode($elementWrap['marker'], $elementWrap['html']);
368 } else {
369 $elementWrap = NULL;
370 }
371 }
372 /* Set element outer wraps and set the default classes */
373 $elementOuterWrap = NULL;
374 if ($this->getGlobalLayoutByElementType('ELEMENTWRAP')) {
375 $libxmlUseInternalErrors = libxml_use_internal_errors(true);
376 $dom = new \DOMDocument('1.0', 'utf-8');
377 $dom->formatOutput = TRUE;
378 $dom->preserveWhiteSpace = FALSE;
379 if ($dom->loadXML($this->getGlobalLayoutByElementType('ELEMENTWRAP'))) {
380 $node = $dom->firstChild;
381 if ($node) {
382 $class = '';
383 if ($node->getAttribute('class') !== '') {
384 $class = $node->getAttribute('class') . ' ';
385 }
386 $class .= 'csc-form-' . $element->getElementCounter() . ' csc-form-element csc-form-element-' . $element->getElementTypeLowerCase();
387 $node->setAttribute('class', $class);
388 $elementOuterWrap = $dom->saveXML($dom->firstChild);
389 $return = $this->replaceTagWithMarker('element', 'body', $elementOuterWrap);
390 if ($return['marker'] !== '') {
391 $elementOuterWrap = explode($return['marker'], $return['html']);
392 if ($element->getElementType() === 'SELECT') {
393 $layout = $element->getLayout();
394 $layout['optionOuterWrap'] = $elementOuterWrap;
395 $element->setLayout($layout);
396 }
397 } else {
398 /* this should never be happen */
399 $elementOuterWrap = NULL;
400 }
401 }
402 } else {
403 $elementOuterWrap = NULL;
404 }
405 libxml_use_internal_errors($libxmlUseInternalErrors);
406 }
407
408 if (
409 $elementWrap
410 && !$elementOuterWrap
411 ) {
412 /* If only $elementWrap isset */
413 $layout = $element->getLayout();
414 $layout['elementOuterWrap'] = $elementWrap;
415 $element->setLayout($layout);
416 } else if (
417 !$elementWrap
418 && $elementOuterWrap
419 ) {
420 /* If only $elementOuterWrap isset */
421 $layout = $element->getLayout();
422 $layout['elementOuterWrap'] = $elementOuterWrap;
423 $element->setLayout($layout);
424 } else if (
425 $elementWrap
426 && $elementOuterWrap
427 ) {
428 /* If $elementWrap isset and $elementOuterWrap isset */
429 $elementWrap = array(
430 $elementOuterWrap[0] . $elementWrap[0],
431 $elementWrap[1] . $elementOuterWrap[1],
432 );
433 $layout = $element->getLayout();
434 $layout['elementOuterWrap'] = $elementWrap;
435 $element->setLayout($layout);
436 }
437
438 /* Set container inner wraps */
439 if (in_array($element->getElementType(), $this->containerElements)) {
440 $elementWrap = $this->determineElementOuterWraps($element->getElementType(), $elementLayout);
441 /* Replace the legend value */
442 $legendLayout = $this->getGlobalLayoutByElementType('LEGEND');
443 $legendValueReturn = $this->replaceTagWithMarker('legendvalue', 'body', $legendLayout);
444 $legendContainContent = FALSE;
445 if ($legendValueReturn['html'] !== '') {
446 if (!empty($element->getAdditionalArgument('legend'))) {
447 $legendContainContent = TRUE;
448 }
449 $legendLayout = str_replace($legendValueReturn['marker'], $element->getAdditionalArgument('legend'), $legendValueReturn['html']);
450 }
451 /* remove <mandatory /> and <error /> from legend */
452 $mandatoryReturn = $this->replaceTagWithMarker('mandatory', 'body', $legendLayout);
453 if (!empty($mandatoryReturn['html'])) {
454 $legendLayout = str_replace($mandatoryReturn['marker'], '', $mandatoryReturn['html']);
455 }
456 $errorReturn = $this->replaceTagWithMarker('error', 'body', $legendLayout);
457 if (!empty($errorReturn['html'])) {
458 $legendLayout = str_replace($errorReturn['marker'], '', $errorReturn['html']);
459 }
460
461 if (!$legendContainContent) {
462 $legendLayout = '';
463 }
464 /* No fieldset tag exist.
465 * Ignore CONTAINERWRAP
466 * */
467 if ($elementWrap['html'] === '') {
468 $containerWrapReturn = $this->replaceTagWithMarker('elements', 'body', $elementLayout);
469 $legendReturn = $this->replaceTagWithMarker('legend', 'body', $containerWrapReturn['html']);
470
471 if ($legendReturn['html'] !== '') {
472 $containerWrapReturn['html'] = str_replace($legendReturn['marker'], $legendLayout, $legendReturn['html']);
473 }
474 if ($containerWrapReturn['marker'] && $containerWrapReturn['html']) {
475 $containerWrap = explode($containerWrapReturn['marker'], $containerWrapReturn['html']);
476 } else {
477 $containerWrap = array('', '');
478 }
479
480 $layout = $element->getLayout();
481 $layout['containerInnerWrap'] = $containerWrap;
482 $layout['noFieldsetTag'] = TRUE;
483 $element->setLayout($layout);
484 } else {
485 $legendReturn = $this->replaceTagWithMarker('legend', 'body', $elementWrap['html']);
486
487 if ($legendReturn['html'] !== '') {
488 $elementWrap['html'] = str_replace($legendReturn['marker'], $legendLayout, $legendReturn['html']);
489 }
490
491 /* set the wraps */
492 $containerOuterWrap = array('', '');
493 $containerOuterWrap = explode($elementWrap['marker'], $elementWrap['html']);
494 $containerWrapReturn = $this->replaceTagWithMarker('elements', 'body', $this->getGlobalLayoutByElementType('CONTAINERWRAP'));
495 $containerInnerWrap = explode($containerWrapReturn['marker'], $containerWrapReturn['html']);
496
497 $containerWrap = array(
498 $containerOuterWrap[0] . $containerInnerWrap[0],
499 $containerInnerWrap[1] . $containerOuterWrap[1],
500 );
501
502 $layout = $element->getLayout();
503 $layout['containerInnerWrap'] = $containerWrap;
504 $element->setLayout($layout);
505 $classFromLayout = $this->getElementClassFromLayout('fieldset');
506 if (!empty($classFromLayout)) {
507 if (!empty($element->getHtmlAttribute('class'))) {
508 $classFromLayout .= ' ' . $element->getHtmlAttribute('class');
509 }
510 $element->setHtmlAttribute('class', $classFromLayout);
511 }
512 }
513 } else {
514 /* set class attribute for the element tag */
515 if ($this->formBuilder->getControllerAction() === 'show') {
516 if ($elementType === 'TEXTAREA') {
517 $tagName = 'textarea';
518 } elseif ($elementType === 'SELECT') {
519 $tagName = 'select';
520 } else {
521 $tagName = 'input';
522 }
523
524 $classFromLayout = $this->getElementClassFromLayout($element->getElementType(), $tagName);
525 if (!empty($classFromLayout)) {
526 if (!empty($element->getAdditionalArgument('class'))) {
527 $classFromLayout .= ' ' . $element->getAdditionalArgument('class');
528 }
529 $element->setAdditionalArgument('class', $classFromLayout);
530 }
531 }
532 }
533 }
534 }
535
536 /**
537 * Replace the message sections of a label.
538 * The scopes can be mandatory or error.
539 *
540 * @param string $scope
541 * @param array $messages
542 * @return string $html
543 */
544 protected function replaceLabelContent($scope = '', array $messages) {
545 $messages = implode(' - ', $messages);
546 $return = $this->replaceTagWithMarker($scope . 'value', 'body', $this->getGlobalLayoutByElementType(strtoupper($scope)));
547 $html = str_replace($return['marker'], $messages, $return['html']);
548 return $html;
549 }
550
551 /**
552 * Return the class attribute for a element defined by layout.
553 *
554 * @param string $elementType
555 * @param string $tagName
556 * @return string
557 */
558 protected function getElementClassFromLayout($elementType = '', $tagName = '') {
559 $class = '';
560 $libxmlUseInternalErrors = libxml_use_internal_errors(true);
561 $dom = new \DOMDocument('1.0', 'utf-8');
562 $dom->formatOutput = TRUE;
563 $dom->preserveWhiteSpace = FALSE;
564 if ($dom->loadXML($this->getGlobalLayoutByElementType(strtoupper($elementType)))) {
565 if ($tagName === '') {
566 $tagName = $elementType;
567 }
568 $nodes = $dom->getElementsByTagName($tagName);
569 if ($nodes->length) {
570 $node = $nodes->item(0);
571 if ($node && $node->getAttribute('class') !== '') {
572 $class = $node->getAttribute('class');
573 }
574 }
575 }
576 libxml_use_internal_errors($libxmlUseInternalErrors);
577 return $class;
578 }
579
580 /**
581 * Try to explode the element layout into 2 parts to get the
582 * outer wrapping
583 *
584 * @param string $elementType
585 * @param string $elementLayout
586 * @return string
587 * @deprecated since TYPO3 CMS 7, this function will be removed in TYPO3 CMS 8, as the functionality is now done via fluid
588 */
589 protected function determineElementOuterWraps($elementType, $elementLayout = '') {
590 if ($this->formBuilder->getControllerAction() === 'show') {
591 if ($elementType === 'TEXTAREA') {
592 $return = $this->replaceTagWithMarker('textarea', 'body', $elementLayout);
593 } elseif ($elementType === 'CONTENTELEMENT') {
594 $return = $this->replaceTagWithMarker('content', 'body', $elementLayout);
595 } elseif ($elementType === 'SELECT') {
596 $return = $this->replaceTagWithMarker('select', 'body', $elementLayout);
597 } elseif (in_array($elementType, $this->containerElements)) {
598 $return = $this->replaceTagWithMarker('fieldset', 'body', $elementLayout);
599 } else {
600 $return = $this->replaceTagWithMarker('input', 'body', $elementLayout);
601 }
602 } else {
603 if ($elementType === 'CONTENTELEMENT') {
604 $return = $this->replaceTagWithMarker('content', 'body', $elementLayout);
605 } elseif ($elementType === 'SELECT') {
606 $return = $this->replaceTagWithMarker('elements', 'body', $elementLayout);
607 } elseif (in_array($elementType, $this->containerElements)) {
608 if ($this->formBuilder->getControllerAction() === 'confirmation') {
609 $return = $this->replaceTagWithMarker('fieldset', 'body', $elementLayout);
610 } else {
611 $return = $this->replaceTagWithMarker('containerwrap', 'body', $elementLayout);
612 }
613 } else {
614 $return = $this->replaceTagWithMarker('inputvalue', 'body', $elementLayout);
615 }
616 }
617 return $return;
618 }
619
620 /**
621 * Replace a html tag with a unique marker
622 *
623 * @param string $tagName
624 * @param string $stopTag
625 * @param string $html
626 * @return array
627 */
628 protected function replaceTagWithMarker($tagName, $stopTag = 'body', $html = '') {
629 if (
630 $tagName === ''
631 || $html === ''
632 ) {
633 return array(
634 'html' => '',
635 'marker' => ''
636 );
637 }
638 $libxmlUseInternalErrors = libxml_use_internal_errors(true);
639 $dom = new \DOMDocument('1.0', 'utf-8');
640 $dom->preserveWhiteSpace = FALSE;
641 if (!$dom->loadHTML($html)) {
642 libxml_use_internal_errors($libxmlUseInternalErrors);
643 return array(
644 'html' => '',
645 'marker' => ''
646 );
647 }
648 libxml_use_internal_errors($libxmlUseInternalErrors);
649 $nodes = $dom->getElementsByTagName($tagName);
650 if (!$nodes->length) {
651 return array(
652 'html' => '',
653 'marker' => ''
654 );
655 }
656 $nodeToReplace = $nodes->item(0);
657 /* Replace $tagname tag with a unique marker */
658 $marker = '###' . uniqid() . '###';
659 $markerNode = $dom->createTextNode($marker);
660 $replaceNode = $dom->createDocumentFragment();
661 $domNode = $dom->importNode($markerNode, TRUE);
662 $replaceNode->appendChild($domNode);
663 $parentNode = $nodeToReplace->parentNode;
664 $parentNode->insertBefore($replaceNode, $nodeToReplace);
665 $parentNode->removeChild($nodeToReplace);
666 $nextParent = $parentNode;
667 /* Do not save the stop tag */
668 while($nextParent !== NULL) {
669 if ($nextParent->tagName === $stopTag) {
670 break;
671 }
672 $nextParent = $nextParent->parentNode;
673 }
674 $html = '';
675 /* if stopTag == html, save the whole html */
676 if ($stopTag === 'html') {
677 $html = $nextParent->ownerDocument->saveHTML($nextParent);
678 } else {
679 /* do not save the stopTag */
680 $children = $nextParent->childNodes;
681 foreach ($children as $child) {
682 $html .= $nextParent->ownerDocument->saveHTML($child);
683 }
684 }
685 return array(
686 'html' => $html,
687 'marker' => $marker
688 );
689 }
690
691 /**
692 * Get new name for some old inconsistent attribute names
693 *
694 * @param string $elementType
695 * @param string $attributeName
696 * @return string
697 * @deprecated since TYPO3 CMS 7, this function will be removed in TYPO3 CMS 8, as the functionality is now done via fluid
698 */
699 public function getNewAttributeName($elementType, $attributeName) {
700 if ($elementType === 'OPTION') {
701 if ($attributeName === 'data') {
702 GeneralUtility::deprecationLog('EXT:form: Deprecated since TYPO3 CMS 7, use text instead of data to configure the OPTION text');
703 $attributeName = 'text';
704 }
705 } elseif ($elementType === 'TEXTAREA') {
706 if ($attributeName === 'data') {
707 GeneralUtility::deprecationLog('EXT:form: Deprecated since TYPO3 CMS 7, use text instead of data to configure the TEXTAREA value');
708 $attributeName = 'text';
709 }
710 } elseif ($elementType === 'TEXTBLOCK') {
711 if ($attributeName === 'content') {
712 GeneralUtility::deprecationLog('EXT:form: Deprecated since TYPO3 CMS 7, use text instead of content to configure the TEXTBLOCK value');
713 $attributeName = 'text';
714 }
715 }
716 return $attributeName;
717 }
718 }