4875a9e60bdf00a2e424d3c5f9e5d6908e083df7
[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 /* Set container inner wraps */
438 if (in_array($element->getElementType(), $this->containerElements)) {
439 $elementWrap = $this->determineElementOuterWraps($element->getElementType(), $elementLayout);
440 /* Replace the legend value */
441 $legendLayout = $this->getGlobalLayoutByElementType('LEGEND');
442 $legendValueReturn = $this->replaceTagWithMarker('legendvalue', 'body', $legendLayout);
443 $legendContainContent = FALSE;
444 if ($legendValueReturn['html'] !== '') {
445 if (!empty($element->getAdditionalArgument('legend'))) {
446 $legendContainContent = TRUE;
447 }
448 $legendLayout = str_replace($legendValueReturn['marker'], $element->getAdditionalArgument('legend'), $legendValueReturn['html']);
449 }
450 /* remove <mandatory /> and <error /> from legend */
451 $mandatoryReturn = $this->replaceTagWithMarker('mandatory', 'body', $legendLayout);
452 if (!empty($mandatoryReturn['html'])) {
453 $legendLayout = str_replace($mandatoryReturn['marker'], '', $mandatoryReturn['html']);
454 }
455 $errorReturn = $this->replaceTagWithMarker('error', 'body', $legendLayout);
456 if (!empty($errorReturn['html'])) {
457 $legendLayout = str_replace($errorReturn['marker'], '', $errorReturn['html']);
458 }
459
460 if (!$legendContainContent) {
461 $legendLayout = '';
462 }
463 /* No fieldset tag exist.
464 * Ignore CONTAINERWRAP
465 * */
466 if ($elementWrap['html'] === '') {
467 $containerWrapReturn = $this->replaceTagWithMarker('elements', 'body', $elementLayout);
468 $legendReturn = $this->replaceTagWithMarker('legend', 'body', $containerWrapReturn['html']);
469
470 if ($legendReturn['html'] !== '') {
471 $containerWrapReturn['html'] = str_replace($legendReturn['marker'], $legendLayout, $legendReturn['html']);
472 }
473 if ($containerWrapReturn['marker'] && $containerWrapReturn['html']) {
474 $containerWrap = explode($containerWrapReturn['marker'], $containerWrapReturn['html']);
475 } else {
476 $containerWrap = array('', '');
477 }
478
479 $layout = $element->getLayout();
480 $layout['containerInnerWrap'] = $containerWrap;
481 $layout['noFieldsetTag'] = TRUE;
482 $element->setLayout($layout);
483 } else {
484 $legendReturn = $this->replaceTagWithMarker('legend', 'body', $elementWrap['html']);
485
486 if ($legendReturn['html'] !== '') {
487 $elementWrap['html'] = str_replace($legendReturn['marker'], $legendLayout, $legendReturn['html']);
488 }
489
490 /* set the wraps */
491 $containerOuterWrap = array('', '');
492 $containerOuterWrap = explode($elementWrap['marker'], $elementWrap['html']);
493 $containerWrapReturn = $this->replaceTagWithMarker('elements', 'body', $this->getGlobalLayoutByElementType('CONTAINERWRAP'));
494 $containerInnerWrap = explode($containerWrapReturn['marker'], $containerWrapReturn['html']);
495
496 $containerWrap = array(
497 $containerOuterWrap[0] . $containerInnerWrap[0],
498 $containerInnerWrap[1] . $containerOuterWrap[1],
499 );
500
501 $layout = $element->getLayout();
502 $layout['containerInnerWrap'] = $containerWrap;
503 $element->setLayout($layout);
504 $classFromLayout = $this->getElementClassFromLayout('fieldset');
505 if (!empty($classFromLayout)) {
506 if (!empty($element->getHtmlAttribute('class'))) {
507 $classFromLayout .= ' ' . $element->getHtmlAttribute('class');
508 }
509 $element->setHtmlAttribute('class', $classFromLayout);
510 }
511 }
512 }
513 return;
514 }
515 }
516
517 /**
518 * Replace the message sections of a label.
519 * The scopes can be mandatory or error.
520 *
521 * @param string $scope
522 * @param array $messages
523 * @return string $html
524 */
525 protected function replaceLabelContent($scope = '', array $messages) {
526 $messages = implode(' - ', $messages);
527 $return = $this->replaceTagWithMarker($scope . 'value', 'body', $this->getGlobalLayoutByElementType(strtoupper($scope)));
528 $html = str_replace($return['marker'], $messages, $return['html']);
529 return $html;
530 }
531
532 /**
533 * Return the class attribute for a element defined by layout.
534 *
535 * @param string $elementName
536 * @return string
537 */
538 protected function getElementClassFromLayout($elementName = '') {
539 $class = '';
540 $libxmlUseInternalErrors = libxml_use_internal_errors(true);
541 $dom = new \DOMDocument('1.0', 'utf-8');
542 $dom->formatOutput = TRUE;
543 $dom->preserveWhiteSpace = FALSE;
544 if ($dom->loadXML($this->getGlobalLayoutByElementType(strtoupper($elementName)))) {
545 $nodes = $dom->getElementsByTagName($elementName);
546 if ($nodes->length) {
547 $node = $nodes->item(0);
548 if ($node && $node->getAttribute('class') !== '') {
549 $class = $node->getAttribute('class');
550 }
551 }
552 }
553 libxml_use_internal_errors($libxmlUseInternalErrors);
554 return $class;
555 }
556
557 /**
558 * Try to explode the element layout into 2 parts to get the
559 * outer wrapping
560 *
561 * @param string $elementType
562 * @param string $elementLayout
563 * @return string
564 * @deprecated since TYPO3 CMS 7, this function will be removed in TYPO3 CMS 8, as the functionality is now done via fluid
565 */
566 protected function determineElementOuterWraps($elementType, $elementLayout = '') {
567 if ($this->formBuilder->getControllerAction() === 'show') {
568 if ($elementType === 'TEXTAREA') {
569 $return = $this->replaceTagWithMarker('textarea', 'body', $elementLayout);
570 } elseif ($elementType === 'CONTENTELEMENT') {
571 $return = $this->replaceTagWithMarker('content', 'body', $elementLayout);
572 } elseif ($elementType === 'SELECT') {
573 $return = $this->replaceTagWithMarker('select', 'body', $elementLayout);
574 } elseif (in_array($elementType, $this->containerElements)) {
575 $return = $this->replaceTagWithMarker('fieldset', 'body', $elementLayout);
576 } else {
577 $return = $this->replaceTagWithMarker('input', 'body', $elementLayout);
578 }
579 } else {
580 if ($elementType === 'CONTENTELEMENT') {
581 $return = $this->replaceTagWithMarker('content', 'body', $elementLayout);
582 } elseif ($elementType === 'SELECT') {
583 $return = $this->replaceTagWithMarker('elements', 'body', $elementLayout);
584 } elseif (in_array($elementType, $this->containerElements)) {
585 if ($this->formBuilder->getControllerAction() === 'confirmation') {
586 $return = $this->replaceTagWithMarker('fieldset', 'body', $elementLayout);
587 } else {
588 $return = $this->replaceTagWithMarker('containerwrap', 'body', $elementLayout);
589 }
590 } else {
591 $return = $this->replaceTagWithMarker('inputvalue', 'body', $elementLayout);
592 }
593 }
594 return $return;
595 }
596
597 /**
598 * Replace a html tag with a unique marker
599 *
600 * @param string $tagName
601 * @param string $stopTag
602 * @param string $html
603 * @return array
604 */
605 protected function replaceTagWithMarker($tagName, $stopTag = 'body', $html = '') {
606 if (
607 $tagName === ''
608 || $html === ''
609 ) {
610 return array(
611 'html' => '',
612 'marker' => ''
613 );
614 }
615 $libxmlUseInternalErrors = libxml_use_internal_errors(true);
616 $dom = new \DOMDocument('1.0', 'utf-8');
617 $dom->preserveWhiteSpace = FALSE;
618 if (!$dom->loadHTML($html)) {
619 libxml_use_internal_errors($libxmlUseInternalErrors);
620 return array(
621 'html' => '',
622 'marker' => ''
623 );
624 }
625 libxml_use_internal_errors($libxmlUseInternalErrors);
626 $nodes = $dom->getElementsByTagName($tagName);
627 if (!$nodes->length) {
628 return array(
629 'html' => '',
630 'marker' => ''
631 );
632 }
633 $nodeToReplace = $nodes->item(0);
634 /* Replace $tagname tag with a unique marker */
635 $marker = '###' . uniqid() . '###';
636 $markerNode = $dom->createTextNode($marker);
637 $replaceNode = $dom->createDocumentFragment();
638 $domNode = $dom->importNode($markerNode, TRUE);
639 $replaceNode->appendChild($domNode);
640 $parentNode = $nodeToReplace->parentNode;
641 $parentNode->insertBefore($replaceNode, $nodeToReplace);
642 $parentNode->removeChild($nodeToReplace);
643 $nextParent = $parentNode;
644 /* Do not save the stop tag */
645 while($nextParent !== NULL) {
646 if ($nextParent->tagName === $stopTag) {
647 break;
648 }
649 $nextParent = $nextParent->parentNode;
650 }
651 $html = '';
652 /* if stopTag == html, save the whole html */
653 if ($stopTag === 'html') {
654 $html = $nextParent->ownerDocument->saveHTML($nextParent);
655 } else {
656 /* do not save the stopTag */
657 $children = $nextParent->childNodes;
658 foreach ($children as $child) {
659 $html .= $nextParent->ownerDocument->saveHTML($child);
660 }
661 }
662 return array(
663 'html' => $html,
664 'marker' => $marker
665 );
666 }
667
668 /**
669 * Get new name for some old inconsistent attribute names
670 *
671 * @param string $elementType
672 * @param string $attributeName
673 * @return string
674 * @deprecated since TYPO3 CMS 7, this function will be removed in TYPO3 CMS 8, as the functionality is now done via fluid
675 */
676 public function getNewAttributeName($elementType, $attributeName) {
677 if ($elementType === 'OPTION') {
678 if ($attributeName === 'data') {
679 GeneralUtility::deprecationLog('EXT:form: Deprecated since TYPO3 CMS 7, use text instead of data to configure the OPTION text');
680 $attributeName = 'text';
681 }
682 } elseif ($elementType === 'TEXTAREA') {
683 if ($attributeName === 'data') {
684 GeneralUtility::deprecationLog('EXT:form: Deprecated since TYPO3 CMS 7, use text instead of data to configure the TEXTAREA value');
685 $attributeName = 'text';
686 }
687 } elseif ($elementType === 'TEXTBLOCK') {
688 if ($attributeName === 'content') {
689 GeneralUtility::deprecationLog('EXT:form: Deprecated since TYPO3 CMS 7, use text instead of content to configure the TEXTBLOCK value');
690 $attributeName = 'text';
691 }
692 }
693 return $attributeName;
694 }
695 }