Completed
Push — master ( 17598f...0cca5d )
by Tim
14:26
created

Classes/Xclass/ContentObjectRenderer.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * ContentObjectRenderer
4
 */
5
6
namespace FRUIT\Popup\Xclass;
7
8
use FRUIT\Popup\Controller\PluginController;
9
use TYPO3\CMS\Core\Utility\GeneralUtility;
10
use TYPO3\CMS\Core\Utility\HttpUtility;
11
use TYPO3\CMS\Core\Utility\MathUtility;
12
use TYPO3\CMS\Frontend\Http\UrlProcessorInterface;
13
use TYPO3\CMS\Frontend\Page\CacheHashCalculator;
14
use TYPO3\CMS\Frontend\Page\PageRepository;
15
use TYPO3\CMS\Frontend\Plugin\AbstractPlugin;
16
17
/**
18
 * ContentObjectRenderer
19
 */
20
class ContentObjectRenderer extends \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
21
{
22
23
    /**
24
     * Implements the "typolink" property of stdWrap (and others)
25
     * Basically the input string, $linktext, is (typically) wrapped in a <a>-tag linking to some page, email address, file or URL based on a parameter defined by the configuration array $conf.
26
     * This function is best used from internal functions as is. There are some API functions defined after this function which is more suited for general usage in external applications.
27
     * Generally the concept "typolink" should be used in your own applications as an API for making links to pages with parameters and more. The reason for this is that you will then automatically make links compatible with all the centralized functions for URL simulation and manipulation of parameters into hashes and more.
28
     * For many more details on the parameters and how they are interpreted, please see the link to TSref below.
29
     *
30
     * the FAL API is handled with the namespace/prefix "file:..."
31
     *
32
     * @param string $linktxt The string (text) to link
33
     * @param array  $conf    TypoScript configuration (see link below)
34
     *
35
     * @return string A link-wrapped string.
36
     * @see stdWrap(), \TYPO3\CMS\Frontend\Plugin\AbstractPlugin::pi_linkTP()
37
     */
38
    public function typoLink($linktxt, $conf)
39
    {
40
        $linktxt = (string)$linktxt;
41
        $tsfe = $this->getTypoScriptFrontendController();
42
43
        $LD = array();
44
        $finalTagParts = array();
45
        $finalTagParts['aTagParams'] = $this->getATagParams($conf);
46
        $linkParameter = trim(isset($conf['parameter.']) ? $this->stdWrap($conf['parameter'],
47
            $conf['parameter.']) : $conf['parameter']);
48
        $this->lastTypoLinkUrl = '';
49
        $this->lastTypoLinkTarget = '';
50
51
        $resolvedLinkParameters = $this->resolveMixedLinkParameter($linktxt, $linkParameter, $conf);
52
        // check if the link handler hook has resolved the link completely already
53
        if (!is_array($resolvedLinkParameters)) {
54
            return $resolvedLinkParameters;
55
        }
56
57
        $linkParameter = $resolvedLinkParameters['href'];
58
        $forceTarget = $resolvedLinkParameters['target'];
59
        $linkClass = $resolvedLinkParameters['class'];
60
        $forceTitle = $resolvedLinkParameters['title'];
61
62
        if (!$linkParameter) {
63
            return $linktxt;
64
        }
65
66
        // Check, if the target is coded as a JS open window link:
67
        $JSwindowParts = array();
68
        $JSwindowParams = '';
69
        if ($forceTarget && preg_match('/^([0-9]+)x([0-9]+)(:(.*)|.*)$/', $forceTarget, $JSwindowParts)) {
70
            // Take all pre-configured and inserted parameters and compile parameter list, including width+height:
71
            $JSwindow_tempParamsArr = GeneralUtility::trimExplode(',',
72
                strtolower($conf['JSwindow_params'] . ',' . $JSwindowParts[4]), true);
73
            $JSwindow_paramsArr = array();
74
            foreach ($JSwindow_tempParamsArr as $JSv) {
75
                list($JSp, $JSv) = explode('=', $JSv, 2);
76
                $JSwindow_paramsArr[$JSp] = $JSp . '=' . $JSv;
77
            }
78
            // Add width/height:
79
            $JSwindow_paramsArr['width'] = 'width=' . $JSwindowParts[1];
80
            $JSwindow_paramsArr['height'] = 'height=' . $JSwindowParts[2];
81
            // Imploding into string:
82
            $JSwindowParams = implode(',', $JSwindow_paramsArr);
83
            // Resetting the target since we will use onClick.
84
            $forceTarget = '';
85
        }
86
87
        // Internal target:
88
        if ($tsfe->dtdAllowsFrames) {
89
            $target = isset($conf['target']) ? $conf['target'] : $tsfe->intTarget;
90
        } else {
91
            $target = isset($conf['target']) ? $conf['target'] : '';
92
        }
93
        if ($conf['target.']) {
94
            $target = $this->stdWrap($target, $conf['target.']);
95
        }
96
97
        // Title tag
98
        $title = $conf['title'];
99
        if ($conf['title.']) {
100
            $title = $this->stdWrap($title, $conf['title.']);
101
        }
102
103
        $theTypeP = 0;
104
        // Detecting kind of link
105
        $linkType = $this->detectLinkTypeFromLinkParameter($linkParameter);
106
        switch ($linkType) {
107
            // If it's a mail address
108
            case 'mailto':
109
                $linkParameter = preg_replace('/^mailto:/i', '', $linkParameter);
110
                list($this->lastTypoLinkUrl, $linktxt) = $this->getMailTo($linkParameter, $linktxt);
111
                $finalTagParts['url'] = $this->lastTypoLinkUrl;
112
                break;
113
114
            // url (external): If doubleSlash or if a '.' comes before a '/'.
115
            case 'url':
116
                if ($tsfe->dtdAllowsFrames) {
117
                    $target = isset($conf['extTarget']) ? $conf['extTarget'] : $tsfe->extTarget;
118
                } else {
119
                    $target = isset($conf['extTarget']) ? $conf['extTarget'] : '';
120
                }
121
                if ($conf['extTarget.']) {
122
                    $target = $this->stdWrap($target, $conf['extTarget.']);
123
                }
124
                if ($forceTarget) {
125
                    $target = $forceTarget;
126
                }
127
                if ($linktxt === '') {
128
                    $linktxt = $this->parseFunc($linkParameter, array('makelinks' => 0), '< lib.parseFunc');
129
                }
130
                // Parse URL:
131
                $urlParts = parse_url($linkParameter);
132
                if (!$urlParts['scheme']) {
133
                    $scheme = 'http://';
134
                } else {
135
                    $scheme = '';
136
                }
137
138
                $this->lastTypoLinkUrl = $this->processUrl(UrlProcessorInterface::CONTEXT_EXTERNAL, $scheme . $linkParameter,
139
                    $conf);
140
141
                $this->lastTypoLinkTarget = $target;
142
                $finalTagParts['url'] = $this->lastTypoLinkUrl;
143
                $finalTagParts['targetParams'] = $target ? ' target="' . $target . '"' : '';
144
                $finalTagParts['aTagParams'] .= $this->extLinkATagParams($finalTagParts['url'], $linkType);
145
                break;
146
147
            // file (internal)
148
            case 'file':
149
150
                $splitLinkParam = explode('?', $linkParameter);
151
152
                // check if the file exists or if a / is contained (same check as in detectLinkType)
153
                if (file_exists(rawurldecode($splitLinkParam[0])) || strpos($linkParameter, '/') !== false) {
154
                    if ($linktxt === '') {
155
                        $linktxt = $this->parseFunc(rawurldecode($linkParameter), array('makelinks' => 0), '< lib.parseFunc');
156
                    }
157
                    $this->lastTypoLinkUrl = $this->processUrl(UrlProcessorInterface::CONTEXT_FILE,
158
                        $GLOBALS['TSFE']->absRefPrefix . $linkParameter, $conf);
159
                    $this->lastTypoLinkUrl = $this->forceAbsoluteUrl($this->lastTypoLinkUrl, $conf);
160
                    $target = isset($conf['fileTarget']) ? $conf['fileTarget'] : $tsfe->fileTarget;
161
                    if ($conf['fileTarget.']) {
162
                        $target = $this->stdWrap($target, $conf['fileTarget.']);
163
                    }
164
                    if ($forceTarget) {
165
                        $target = $forceTarget;
166
                    }
167
                    $this->lastTypoLinkTarget = $target;
168
                    $finalTagParts['url'] = $this->lastTypoLinkUrl;
169
                    $finalTagParts['targetParams'] = $target ? ' target="' . $target . '"' : '';
170
                    $finalTagParts['aTagParams'] .= $this->extLinkATagParams($finalTagParts['url'], $linkType);
171
                } else {
172
                    $this->getTimeTracker()
173
                        ->setTSlogMessage('typolink(): File "' . $splitLinkParam[0] . '" did not exist, so "' . $linktxt . '" was not linked.',
174
                            1);
175
                    return $linktxt;
176
                }
177
                break;
178
179
            // Integer or alias (alias is without slashes or periods or commas, that is
180
            // 'nospace,alphanum_x,lower,unique' according to definition in $GLOBALS['TCA']!)
181
            case 'page':
182
                $enableLinksAcrossDomains = $tsfe->config['config']['typolinkEnableLinksAcrossDomains'];
183
184
                if ($conf['no_cache.']) {
185
                    $conf['no_cache'] = $this->stdWrap($conf['no_cache'], $conf['no_cache.']);
186
                }
187
                // Splitting the parameter by ',' and if the array counts more than 1 element it's an id/type/parameters triplet
188
                $pairParts = GeneralUtility::trimExplode(',', $linkParameter, true);
189
                $linkParameter = $pairParts[0];
190
                $link_params_parts = explode('#', $linkParameter);
191
                // Link-data del
192
                $linkParameter = trim($link_params_parts[0]);
193
                // If no id or alias is given
194
                if ($linkParameter === '') {
195
                    $linkParameter = $tsfe->id;
196
                }
197
198
                $sectionMark = trim(isset($conf['section.']) ? $this->stdWrap($conf['section'],
199
                    $conf['section.']) : $conf['section']);
200
                if ($sectionMark !== '') {
201
                    $sectionMark = '#' . (MathUtility::canBeInterpretedAsInteger($sectionMark) ? 'c' : '') . $sectionMark;
202
                }
203
204
                if ($link_params_parts[1] && $sectionMark === '') {
205
                    $sectionMark = trim($link_params_parts[1]);
206
                    $sectionMark = '#' . (MathUtility::canBeInterpretedAsInteger($sectionMark) ? 'c' : '') . $sectionMark;
207
                }
208
                if (count($pairParts) > 1) {
209
                    // Overruling 'type'
210
                    $theTypeP = isset($pairParts[1]) ? $pairParts[1] : 0;
211
                    $conf['additionalParams'] .= isset($pairParts[2]) ? $pairParts[2] : '';
212
                }
213
                // Checking if the id-parameter is an alias.
214
                if (!MathUtility::canBeInterpretedAsInteger($linkParameter)) {
215
                    $linkParameter = $tsfe->sys_page->getPageIdFromAlias($linkParameter);
216
                }
217
                // Link to page even if access is missing?
218
                if (isset($conf['linkAccessRestrictedPages'])) {
219
                    $disableGroupAccessCheck = (bool)$conf['linkAccessRestrictedPages'];
220
                } else {
221
                    $disableGroupAccessCheck = (bool)$tsfe->config['config']['typolinkLinkAccessRestrictedPages'];
222
                }
223
                // Looking up the page record to verify its existence:
224
                $page = $tsfe->sys_page->getPage($linkParameter, $disableGroupAccessCheck);
225
                if (!empty($page)) {
226
                    // MointPoints, look for closest MPvar:
227
                    $MPvarAcc = array();
228
                    if (!$tsfe->config['config']['MP_disableTypolinkClosestMPvalue']) {
229
                        $temp_MP = $this->getClosestMPvalueForPage($page['uid'], true);
230
                        if ($temp_MP) {
231
                            $MPvarAcc['closest'] = $temp_MP;
232
                        }
233
                    }
234
                    // Look for overlay Mount Point:
235
                    $mount_info = $tsfe->sys_page->getMountPointInfo($page['uid'], $page);
236
                    if (is_array($mount_info) && $mount_info['overlay']) {
237
                        $page = $tsfe->sys_page->getPage($mount_info['mount_pid'], $disableGroupAccessCheck);
238
                        if (empty($page)) {
239
                            $this->getTimeTracker()
240
                                ->setTSlogMessage('typolink(): Mount point "' . $mount_info['mount_pid'] . '" was not available, so "' . $linktxt . '" was not linked.',
241
                                    1);
242
                            return $linktxt;
243
                        }
244
                        $MPvarAcc['re-map'] = $mount_info['MPvar'];
245
                    }
246
247
248
                    // -----------------------
249
                    // Popup Hook
250
                    // -----------------------
251
                    $plugin = new PluginController();
252
                    $popup = $plugin->pi_getRecord('pages', $page['uid']);
253
                    $popup_configuration = $popup['tx_popup_configuration'];
254
255
256
                    // Setting title if blank value to link:
257
                    if ($linktxt === '') {
258
                        $linktxt = $this->parseFunc($page['title'], array('makelinks' => 0), '< lib.parseFunc');
259
                    }
260
                    // Query Params:
261
                    $addQueryParams = $conf['addQueryString'] ? $this->getQueryArguments($conf['addQueryString.']) : '';
262
                    $addQueryParams .= isset($conf['additionalParams.']) ? trim($this->stdWrap($conf['additionalParams'],
263
                        $conf['additionalParams.'])) : trim($conf['additionalParams']);
264
                    if ($addQueryParams === '&' || $addQueryParams[0] !== '&') {
265
                        $addQueryParams = '';
266
                    }
267
                    if ($conf['useCacheHash']) {
268
                        // Mind the order below! See http://forge.typo3.org/issues/17070
269
                        $params = $tsfe->linkVars . $addQueryParams;
270
                        if (trim($params, '& ') != '') {
271
                            /** @var $cacheHash CacheHashCalculator */
272
                            $cacheHash = GeneralUtility::makeInstance(CacheHashCalculator::class);
273
                            $cHash = $cacheHash->generateForParameters($params);
274
                            $addQueryParams .= $cHash ? '&cHash=' . $cHash : '';
275
                        }
276
                        unset($params);
277
                    }
278
                    $targetDomain = '';
279
                    $currentDomain = (string)$this->getEnvironmentVariable('HTTP_HOST');
280
                    // Mount pages are always local and never link to another domain
281
                    if (!empty($MPvarAcc)) {
282
                        // Add "&MP" var:
283
                        $addQueryParams .= '&MP=' . rawurlencode(implode(',', $MPvarAcc));
284
                    } elseif (strpos($addQueryParams, '&MP=') === false && $tsfe->config['config']['typolinkCheckRootline']) {
285
                        // We do not come here if additionalParams had '&MP='. This happens when typoLink is called from
286
                        // menu. Mount points always work in the content of the current domain and we must not change
287
                        // domain if MP variables exist.
288
                        // If we link across domains and page is free type shortcut, we must resolve the shortcut first!
289
                        // If we do not do it, TYPO3 will fail to (1) link proper page in RealURL/CoolURI because
290
                        // they return relative links and (2) show proper page if no RealURL/CoolURI exists when link is clicked
291
                        if ($enableLinksAcrossDomains && (int)$page['doktype'] === PageRepository::DOKTYPE_SHORTCUT && (int)$page['shortcut_mode'] === PageRepository::SHORTCUT_MODE_NONE) {
292
                            // Save in case of broken destination or endless loop
293
                            $page2 = $page;
294
                            // Same as in RealURL, seems enough
295
                            $maxLoopCount = 20;
296
                            while ($maxLoopCount && is_array($page) && (int)$page['doktype'] === PageRepository::DOKTYPE_SHORTCUT && (int)$page['shortcut_mode'] === PageRepository::SHORTCUT_MODE_NONE) {
297
                                $page = $tsfe->sys_page->getPage($page['shortcut'], $disableGroupAccessCheck);
298
                                $maxLoopCount--;
299
                            }
300
                            if (empty($page) || $maxLoopCount === 0) {
301
                                // We revert if shortcut is broken or maximum number of loops is exceeded (indicates endless loop)
302
                                $page = $page2;
303
                            }
304
                        }
305
306
                        $targetDomain = $tsfe->getDomainNameForPid($page['uid']);
307
                        // Do not prepend the domain if it is the current hostname
308
                        if (!$targetDomain || $tsfe->domainNameMatchesCurrentRequest($targetDomain)) {
309
                            $targetDomain = '';
310
                        }
311
                    }
312
                    $absoluteUrlScheme = 'http';
313
                    // URL shall be absolute:
314
                    if (isset($conf['forceAbsoluteUrl']) && $conf['forceAbsoluteUrl'] || $page['url_scheme'] > 0) {
315
                        // Override scheme:
316
                        if (isset($conf['forceAbsoluteUrl.']['scheme']) && $conf['forceAbsoluteUrl.']['scheme']) {
317
                            $absoluteUrlScheme = $conf['forceAbsoluteUrl.']['scheme'];
318
                        } elseif ($page['url_scheme'] > 0) {
319
                            $absoluteUrlScheme = (int)$page['url_scheme'] === HttpUtility::SCHEME_HTTP ? 'http' : 'https';
320
                        } elseif ($this->getEnvironmentVariable('TYPO3_SSL')) {
321
                            $absoluteUrlScheme = 'https';
322
                        }
323
                        // If no domain records are defined, use current domain:
324
                        $currentUrlScheme = parse_url($this->getEnvironmentVariable('TYPO3_REQUEST_URL'), PHP_URL_SCHEME);
325
                        if ($targetDomain === '' && ($conf['forceAbsoluteUrl'] || $absoluteUrlScheme !== $currentUrlScheme)) {
326
                            $targetDomain = $currentDomain;
327
                        }
328
                        // If go for an absolute link, add site path if it's not taken care about by absRefPrefix
329
                        if (!$tsfe->config['config']['absRefPrefix'] && $targetDomain === $currentDomain) {
330
                            $targetDomain = $currentDomain . rtrim($this->getEnvironmentVariable('TYPO3_SITE_PATH'), '/');
331
                        }
332
                    }
333
                    // If target page has a different domain and the current domain's linking scheme (e.g. RealURL/...) should not be used
334
                    if ($targetDomain !== '' && $targetDomain !== $currentDomain && !$enableLinksAcrossDomains) {
335
                        $target = isset($conf['extTarget']) ? $conf['extTarget'] : $tsfe->extTarget;
336
                        if ($conf['extTarget.']) {
337
                            $target = $this->stdWrap($target, $conf['extTarget.']);
338
                        }
339
                        if ($forceTarget) {
340
                            $target = $forceTarget;
341
                        }
342
                        $LD['target'] = $target;
343
                        // Convert IDNA-like domain (if any)
344
                        if (!preg_match('/^[a-z0-9.\\-]*$/i', $targetDomain)) {
345
                            $targetDomain = GeneralUtility::idnaEncode($targetDomain);
346
                        }
347
                        $this->lastTypoLinkUrl = $this->URLqMark($absoluteUrlScheme . '://' . $targetDomain . '/index.php?id=' . $page['uid'],
348
                                $addQueryParams) . $sectionMark;
349
                    } else {
350
                        // Internal link or current domain's linking scheme should be used
351
                        if ($forceTarget) {
352
                            $target = $forceTarget;
353
                        }
354
                        $LD = $tsfe->tmpl->linkData($page, $target, $conf['no_cache'], '', '', $addQueryParams, $theTypeP,
0 ignored issues
show
'' is of type string, but the function expects a array|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
355
                            $targetDomain);
356
                        if ($targetDomain !== '') {
357
                            // We will add domain only if URL does not have it already.
358
                            if ($enableLinksAcrossDomains && $targetDomain !== $currentDomain) {
359
                                // Get rid of the absRefPrefix if necessary. absRefPrefix is applicable only
360
                                // to the current web site. If we have domain here it means we link across
361
                                // domains. absRefPrefix can contain domain name, which will screw up
362
                                // the link to the external domain.
363
                                $prefixLength = strlen($tsfe->config['config']['absRefPrefix']);
364
                                if (substr($LD['totalURL'], 0, $prefixLength) === $tsfe->config['config']['absRefPrefix']) {
365
                                    $LD['totalURL'] = substr($LD['totalURL'], $prefixLength);
366
                                }
367
                            }
368
                            $urlParts = parse_url($LD['totalURL']);
369
                            if (empty($urlParts['host'])) {
370
                                $LD['totalURL'] = $absoluteUrlScheme . '://' . $targetDomain . ($LD['totalURL'][0] === '/' ? '' : '/') . $LD['totalURL'];
371
                            }
372
                        }
373
                        $this->lastTypoLinkUrl = $this->URLqMark($LD['totalURL'], '') . $sectionMark;
374
                    }
375
                    $this->lastTypoLinkTarget = $LD['target'];
376
                    // If sectionMark is set, there is no baseURL AND the current page is the page the link is to, check if there are any additional parameters or addQueryString parameters and if not, drop the url.
377
                    if ($sectionMark && !$tsfe->config['config']['baseURL'] && (int)$page['uid'] === (int)$tsfe->id && !trim($addQueryParams) && (empty($conf['addQueryString']) || !isset($conf['addQueryString.']))) {
378
                        $currentQueryParams = $this->getQueryArguments(array());
379
                        if (!trim($currentQueryParams)) {
380
                            list(, $URLparams) = explode('?', $this->lastTypoLinkUrl);
381
                            list($URLparams) = explode('#', $URLparams);
382
                            parse_str($URLparams . $LD['orig_type'], $URLparamsArray);
383
                            // Type nums must match as well as page ids
384
                            if ((int)$URLparamsArray['type'] === (int)$tsfe->type) {
385
                                unset($URLparamsArray['id']);
386
                                unset($URLparamsArray['type']);
387
                                // If there are no parameters left.... set the new url.
388
                                if (empty($URLparamsArray)) {
389
                                    $this->lastTypoLinkUrl = $sectionMark;
390
                                }
391
                            }
392
                        }
393
                    }
394
                    // If link is to an access restricted page which should be redirected, then find new URL:
395
                    if (empty($conf['linkAccessRestrictedPages']) && $tsfe->config['config']['typolinkLinkAccessRestrictedPages'] && $tsfe->config['config']['typolinkLinkAccessRestrictedPages'] !== 'NONE' && !$tsfe->checkPageGroupAccess($page)) {
396
                        $thePage = $tsfe->sys_page->getPage($tsfe->config['config']['typolinkLinkAccessRestrictedPages']);
397
                        $addParams = str_replace(array(
398
                            '###RETURN_URL###',
399
                            '###PAGE_ID###'
400
                        ), array(
401
                            rawurlencode($this->lastTypoLinkUrl),
402
                            $page['uid']
403
                        ), $tsfe->config['config']['typolinkLinkAccessRestrictedPages_addParams']);
404
                        $this->lastTypoLinkUrl = $this->getTypoLink_URL($thePage['uid'] . ($theTypeP ? ',' . $theTypeP : ''),
405
                            $addParams, $target);
406
                        $this->lastTypoLinkUrl = $this->forceAbsoluteUrl($this->lastTypoLinkUrl, $conf);
407
                        $this->lastTypoLinkLD['totalUrl'] = $this->lastTypoLinkUrl;
408
                        $LD = $this->lastTypoLinkLD;
409
                    }
410
                    // Rendering the tag.
411
                    $finalTagParts['url'] = $this->lastTypoLinkUrl;
412
                    $finalTagParts['targetParams'] = (string)$LD['target'] !== '' ? ' target="' . htmlspecialchars($LD['target']) . '"' : '';
413
                } else {
414
                    $this->getTimeTracker()
415
                        ->setTSlogMessage('typolink(): Page id "' . $linkParameter . '" was not found, so "' . $linktxt . '" was not linked.',
416
                            1);
417
                    return $linktxt;
418
                }
419
                break;
420
        }
421
422
        $finalTagParts['TYPE'] = $linkType;
423
        $this->lastTypoLinkLD = $LD;
424
425
        if ($forceTitle) {
426
            $title = $forceTitle;
427
        }
428
429
        if ($JSwindowParams) {
430
            // Create TARGET-attribute only if the right doctype is used
431
            $xhtmlDocType = $tsfe->xhtmlDoctype;
432
            if ($xhtmlDocType !== 'xhtml_strict' && $xhtmlDocType !== 'xhtml_11' && $xhtmlDocType !== 'xhtml_2') {
433
                $target = ' target="FEopenLink"';
434
            } else {
435
                $target = '';
436
            }
437
            $onClick = 'vHWin=window.open(' . GeneralUtility::quoteJSvalue($tsfe->baseUrlWrap($finalTagParts['url'])) . ',\'FEopenLink\',' . GeneralUtility::quoteJSvalue($JSwindowParams) . ');vHWin.focus();return false;';
438
            $finalAnchorTag = '<a href="' . htmlspecialchars($finalTagParts['url']) . '"' . $target . ' onclick="' . htmlspecialchars($onClick) . '"' . ((string)$title !== '' ? ' title="' . htmlspecialchars($title) . '"' : '') . ($linkClass !== '' ? ' class="' . $linkClass . '"' : '') . $finalTagParts['aTagParams'] . '>';
439
        } else {
440
            if ($tsfe->spamProtectEmailAddresses === 'ascii' && $linkType === 'mailto') {
441
                $finalAnchorTag = '<a href="' . $finalTagParts['url'] . '"';
442
            } else {
443
                $finalAnchorTag = '<a href="' . htmlspecialchars($finalTagParts['url']) . '"';
444
445
446
                // -----------------------
447
                // Popup Hook
448
                // -----------------------
449
                if (isset($popup_configuration) && strlen($popup_configuration)) {
450
                    $popup = GeneralUtility::makeInstance('FRUIT\\Popup\\Popup');
451
                    $popup_configuration = $popup->convertCfg2Js($popup_configuration);
452
                    $finalTagParts['aTagParams'] .= ' onclick="window.open(this.href,\'\',\'' . $popup_configuration . '\'); return false;"';
453
                }
454
455
            }
456
            $finalAnchorTag .= ((string)$title !== '' ? ' title="' . htmlspecialchars($title) . '"' : '') . $finalTagParts['targetParams'] . ($linkClass ? ' class="' . $linkClass . '"' : '') . $finalTagParts['aTagParams'] . '>';
457
        }
458
459
        // Call user function:
460
        if ($conf['userFunc']) {
461
            $finalTagParts['TAG'] = $finalAnchorTag;
462
            $finalAnchorTag = $this->callUserFunction($conf['userFunc'], $conf['userFunc.'], $finalTagParts);
463
        }
464
465
        // Hook: Call post processing function for link rendering:
466
        if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc'])) {
467
            $_params = array(
468
                'conf'          => &$conf,
469
                'linktxt'       => &$linktxt,
470
                'finalTag'      => &$finalAnchorTag,
471
                'finalTagParts' => &$finalTagParts
472
            );
473
            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc'] as $_funcRef) {
474
                GeneralUtility::callUserFunction($_funcRef, $_params, $this);
475
            }
476
        }
477
478
        // If flag "returnLastTypoLinkUrl" set, then just return the latest URL made:
479
        if ($conf['returnLast']) {
480
            switch ($conf['returnLast']) {
481
                case 'url':
482
                    return $this->lastTypoLinkUrl;
483
                    break;
484
                case 'target':
485
                    return $this->lastTypoLinkTarget;
486
                    break;
487
            }
488
        }
489
490
        $wrap = isset($conf['wrap.']) ? $this->stdWrap($conf['wrap'], $conf['wrap.']) : $conf['wrap'];
491
492
        if ($conf['ATagBeforeWrap']) {
493
            return $finalAnchorTag . $this->wrap($linktxt, $wrap) . '</a>';
494
        }
495
        return $this->wrap($finalAnchorTag . $linktxt . '</a>', $wrap);
496
    }
497
498
}
499