[BUGFIX] Disable output escaping in TypolinkViewHelper
[Packages/TYPO3.CMS.git] / typo3 / sysext / fluid / Classes / ViewHelpers / Link / TypolinkViewHelper.php
1 <?php
2 namespace TYPO3\CMS\Fluid\ViewHelpers\Link;
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 use TYPO3\CMS\Core\Utility\GeneralUtility;
17 use TYPO3\CMS\Fluid\Core\Rendering\RenderingContextInterface;
18 use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
19 use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
20 use TYPO3\CMS\Frontend\Service\TypoLinkCodecService;
21
22 /**
23 * A ViewHelper to create links from fields supported by the link wizard
24 *
25 * == Example ==
26 *
27 * {link} contains "19 _blank - "testtitle with whitespace" &X=y"
28 *
29 * <code title="minimal usage">
30 * <f:link.typolink parameter="{link}">
31 * Linktext
32 * </f:link.typolink>
33 * <output>
34 * <a href="index.php?id=19&X=y" title="testtitle with whitespace" target="_blank">
35 * Linktext
36 * </a>
37 * </output>
38 * </code>
39 *
40 * <code title="Full parameter usage">
41 * <f:link.typolink parameter="{link}" target="_blank" class="ico-class" title="some title" additionalParams="&u=b" additionalAttributes="{type:'button'}">
42 * Linktext
43 * </f:link.typolink>
44 * </code>
45 * <output>
46 * <a href="index.php?id=19&X=y&u=b" title="some title" target="_blank" class="ico-class" type="button">
47 * Linktext
48 * </a>
49 * </output>
50 *
51 */
52 class TypolinkViewHelper extends AbstractViewHelper
53 {
54
55 /**
56 * @var bool
57 */
58 protected $escapeOutput = false;
59
60 /**
61 * Render
62 *
63 * @param string $parameter stdWrap.typolink style parameter string
64 * @param string $target
65 * @param string $class
66 * @param string $title
67 * @param string $additionalParams
68 * @param array $additionalAttributes
69 *
70 * @return string
71 */
72 public function render($parameter, $target = '', $class = '', $title = '', $additionalParams = '', $additionalAttributes = array())
73 {
74 return static::renderStatic(
75 array(
76 'parameter' => $parameter,
77 'target' => $target,
78 'class' => $class,
79 'title' => $title,
80 'additionalParams' => $additionalParams,
81 'additionalAttributes' => $additionalAttributes
82 ),
83 $this->buildRenderChildrenClosure(),
84 $this->renderingContext
85 );
86 }
87
88 /**
89 * @param array $arguments
90 * @param callable $renderChildrenClosure
91 * @param RenderingContextInterface $renderingContext
92 * @return mixed|string
93 * @throws \InvalidArgumentException
94 * @throws \UnexpectedValueException
95 */
96 public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
97 {
98 $parameter = $arguments['parameter'];
99 $target = $arguments['target'];
100 $class = $arguments['class'];
101 $title = $arguments['title'];
102 $additionalParams = $arguments['additionalParams'];
103 $additionalAttributes = $arguments['additionalAttributes'];
104
105 // Merge the $parameter with other arguments
106 $typolinkParameter = self::createTypolinkParameterArrayFromArguments($parameter, $target, $class, $title, $additionalParams);
107
108 // array(param1 -> value1, param2 -> value2) --> param1="value1" param2="value2" for typolink.ATagParams
109 $extraAttributes = array();
110 foreach ($additionalAttributes as $attributeName => $attributeValue) {
111 $extraAttributes[] = $attributeName . '="' . htmlspecialchars($attributeValue) . '"';
112 }
113 $aTagParams = implode(' ', $extraAttributes);
114
115 // If no link has to be rendered, the inner content will be returned as such
116 $content = (string)$renderChildrenClosure();
117
118 if ($parameter) {
119 /** @var ContentObjectRenderer $contentObject */
120 $contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class);
121 $contentObject->start(array(), '');
122 $content = $contentObject->stdWrap(
123 $content,
124 array(
125 'typolink.' => array(
126 'parameter' => $typolinkParameter,
127 'ATagParams' => $aTagParams,
128 )
129 )
130 );
131 }
132
133 return $content;
134 }
135
136 /**
137 * Transforms ViewHelper arguments to typo3link.parameters.typoscript option as array.
138 *
139 * @param string $parameter Example: 19 _blank - "testtitle \"with whitespace\"" &X=y
140 * @param string $target
141 * @param string $class
142 * @param string $title
143 * @param string $additionalParams
144 *
145 * @return string The final TypoLink string
146 */
147 protected static function createTypolinkParameterArrayFromArguments($parameter, $target = '', $class = '', $title = '', $additionalParams = '')
148 {
149 $typoLinkCodec = GeneralUtility::makeInstance(TypoLinkCodecService::class);
150 $typolinkConfiguration = $typoLinkCodec->decode($parameter);
151 if (empty($typolinkConfiguration)) {
152 return $typolinkConfiguration;
153 }
154
155 // Override target if given in target argument
156 if ($target) {
157 $typolinkConfiguration['target'] = $target;
158 }
159
160 // Combine classes if given in both "parameter" string and "class" argument
161 if ($class) {
162 if ($typolinkConfiguration['class']) {
163 $typolinkConfiguration['class'] .= ' ';
164 }
165 $typolinkConfiguration['class'] .= $class;
166 }
167
168 // Override title if given in title argument
169 if ($title) {
170 $typolinkConfiguration['title'] = $title;
171 }
172
173 // Combine additionalParams
174 if ($additionalParams) {
175 $typolinkConfiguration['additionalParams'] .= $additionalParams;
176 }
177
178 return $typoLinkCodec->encode($typolinkConfiguration);
179 }
180 }