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